這篇文章屬于典型的剝洋蔥文,由表及里,逐步引入新的知識點,挖掘最本質的原因。這篇文的邏輯是先假設再證明,按照這個思路去閱讀會比較輕松。
Maya里的GPU Cache導入的幾何體為什么不能編輯頂點?這可以算是一個高頻問題了,這個問題可以轉換為:GPU Cache導入的幾何體為什么不能編輯Mesh(不僅不能編輯頂點,為它添加bevel一類的節(jié)點也不可以)?實際上這個問題在Maya的幫助文檔中是有明確答案的。
我們來看看官方是如何解釋的:
GPU caches are Alembic-based files that are optimized for fast playback performance in Maya. These performance gains come from the way GPU cache files are evaluated. The GPU cache node routes cached data directly to the system graphics card for processing, bypassing Maya dependency graph evaluation.
GPU cache是由Alembic文件派生出來的一種文件格式,為獲取Maya中快速播放的性能專門做了優(yōu)化。這些性能的提升來自于GPU cache文件求值的方式。GPU cache節(jié)點會避開Maya的dependency graph求值機制,把緩存數(shù)據(jù)直接發(fā)送到系統(tǒng)的圖形卡接口進行處理。
現(xiàn)今的圖形卡都有著比cpu夸張很多的線程數(shù)量,在并行計算的應用上有著極大優(yōu)勢,而圖形處理的計算幾乎都是線性計算,與圖形卡的多線程簡直是天作之合,GPU cache利用了圖形卡的優(yōu)勢,把GPU cache文件中的緩存數(shù)據(jù)直接發(fā)送給圖形卡進行計算,效率自然與基于傳統(tǒng)計算框架cpu《--》memory的DG(dependency graph)機制不可同日而語。
但仔細一想,這段話有一個漏洞:雖然GPU cache導入的geometry無法編輯頂點,但整體移動還是可以的。這就與官方的解釋相悖了,說好了會避開DG求值機制呢?
為了在這個問題上做更深層次的分析,我們插播一個DAG的小廣告,快速的了解一下DAG的概念:
In Maya, a directed acyclic graph (DAG), defines elements such as the position, orientation, and scale of geometry. The DAG is composed of two types of DAG nodes, transforms and shapes. Maya‘s Directed Acyclic Graph (DAG) scene architecture, organized as a tree of transform nodes and shape nodes.
在Maya中,有向非循環(huán)圖(Directed Acyclic Graph,DAG),定義了諸如幾何體的位置、方向和大小等元素。有向非循環(huán)圖由兩種DAG節(jié)點構成,分別是Transform和Shape。Maya的有向非循環(huán)圖(Directed Acyclic Graph,DAG)場景結構就是由transform和shape節(jié)點組成的一顆層級樹。
A DAG node is simply an entity in the DAG. It may have and know about parents, siblings, and children, but it does not necessarily know about transformations or geometry. Transforms and Shapes are two types of nodes derived from a DAG node. A transform node is a type of DAG node which handles transformations (translate, rotate, and scale), while a shape node is a type of DAG node which handles geometry. A shape node does not maintain transformation information, and geometry cannot be hung below a transform node. This means that any piece of geometry requires two DAG nodes above it, a shape node immediately above it, and a transform node above the shape node.
DAG節(jié)點就是有向非循環(huán)圖中的實體,該節(jié)點有且知道有哪些父節(jié)點、鄰節(jié)點和子節(jié)點,但它并不必需要知道相關的transform信息和幾何體信息。Transform和Shape是兩種派生自DAG節(jié)點的節(jié)點,Transform節(jié)點是一種能處理transformation(譯作變換,屬于線性計算,包含translate、rotate、scale信息)信息的DAG節(jié)點,Shape節(jié)點是一種能處理geometry(幾何體)信息的DAG節(jié)點。Shape節(jié)點不會維護transformation信息,geometry也不能放在Tranform節(jié)點下面。這意味著任意一片geometry都需要有兩個DAG節(jié)點放在它的層級之上,Shape節(jié)點放置在geometry上面,transform放置在Shape節(jié)點上面,通過這種方式構造出一個層級關系樹,供DAG使用。
Geometry層級示例:
Transform Node --》 處理transformation信息
|
Shape Node --》 處理下方Geometry信息
|
Geometry Data --》 可能存放在內(nèi)存中,也可能存放在GPU顯存中
根據(jù)DAG的概念,我們可以推論:對于GPU cache導入進來的geometry來說,必然會為它創(chuàng)建兩個DAG節(jié)點,一個是Transform Node,一個是Shape Node。其中Tramsform節(jié)點中的tramsformation信息是可以編輯的,可以接受外部的位移操作,而Shape節(jié)點持有的geometry信息是不可編輯的。
但現(xiàn)在這個推論還是不夠深入,為什么Alembic Cache既能編輯transformation又能編輯geometry信息,唯獨GPU cache只能編輯transformation?
下面我們再引入DG(dependency graph)的概念,更進一步的,去Maya的底層找答案。
The dependency graph lies at the heart of Maya. It maintains the construction history of the scene: a record of what operations you have applied in what order. The graph is made up of a series of interconnected nodes, each of which encapsulates a single operation or a single set of calculations. Each node accepts a limited set of well-defined input data, performs its calculations based on that data, and produces one or more output values.
Dependency graph(依賴圖)位于Maya核心,它維護著場景的構造歷史,在這里,構造歷史指的是你以某種順序應用的操作記錄。該圖由一系列相互連接的節(jié)點組成,每一個節(jié)點封裝一個操作或一組計算。每個節(jié)點接受有限的一組定義好的輸入數(shù)據(jù),再根據(jù)該數(shù)據(jù)執(zhí)行計算,并生成一個或多個輸出值。
Most objects in Maya are dependency graph nodes, or networks of nodes (several nodes connected together)。 For example, DAG nodes are dependency graph nodes, and shaders are networks of nodes.
Maya中的大多數(shù)對象都是依賴圖節(jié)點或是由多個節(jié)點連接到一起構成的子網(wǎng)絡。例如,DAG節(jié)點是依賴圖節(jié)點,著色器是節(jié)點網(wǎng)絡。
Certain events cause the dependency graph to re-evaluate itself, examples being screen refresh, and animation playback. During a refresh for example, the system will walk down the DAG and for each DAG node check to see whether it needs to be re-evaluated.
某些事件會觸發(fā)依賴圖重新對自己求值,例如屏幕刷新和動畫回放。在屏幕刷新期間,Maya底層將遍歷DAG層級結構,并檢查每一個經(jīng)過的DAG節(jié)點是否需要重新求值。
由上可知,Transform和Shape節(jié)點實際上就是DG節(jié)點的一種,我們可以猜測,“The GPU cache node routes cached data directly to the system graphics card for processing, bypassing Maya dependency graph evaluation. ”這句話指的是,在viewport顯示geometry的時候,GPU cache構造的Shape node所持有的geometry數(shù)據(jù)會直接發(fā)送到系統(tǒng)的圖形卡接口進行直接處理,避開DG的求值;而GPU cache構造的Transform node則依然會進入DG的求值機制,用戶可以像使用Polygon一樣,在Transform node上添加歷史節(jié)點,比如Time node來key關鍵幀。
實際上,在GPU cache的開發(fā)文檔中還提到了這樣一句:
The gpuCache node is a Shape node that holds baked animated geometry in memory.The node can stream the animated geometry to the viewport without triggering any DG evaluation of geometry attributes (mesh, nurbs or subd surface data)。
gpuCache 節(jié)點是一個在內(nèi)存中持有幾何體數(shù)據(jù)的Shape節(jié)點,當然這個幾何體數(shù)據(jù)是烘焙后的、有動畫的幾何體數(shù)據(jù)。gpuCahe節(jié)點可以把幾何體數(shù)據(jù)傳遞給viewport(就是hardware renderer或者viewport2.0),而不會觸發(fā)任何幾何體屬性的DG求值行為。
這條說明就充分佐證了我們的猜測,這個解釋無疑比文章最開始的答案要更深入。但我們依然還有一個疑惑,這種特性是如何實現(xiàn)的呢?為什么Alembic Cache導入abc文件可以編輯頂點,GPU Cache就不行?下面我們打破砂鍋問到底,去GPU Cache的源碼里尋找答案。
GPU cache的源碼是公開的,你可以通過下載對應Maya版本的devkit來獲取,附個鏈接:Maya2017 devkit下載地址?,F(xiàn)在我們閱讀GPU cache的源碼來驗證這個猜測是否為真。
首先,在doGpuCacheExportArgList.mel中有這樣一段代碼可以展示GPU cache創(chuàng)建DAG節(jié)點的過程:
3string $xformNode = `createNode transform -name $nodeName`;
createNode gpuCache -name ($nodeName + “Shape”) -parent $xformNode;
setAttr “.cacheFileName” -type “string” $fileFullPath;
其中第一行創(chuàng)建transform節(jié)點;第二行創(chuàng)建gpuCache節(jié)點,gpuCache節(jié)點就是shape節(jié)點,下面會講到;第三行為gpuCache節(jié)點制定abc文件路徑。這就印證了我們在DAG環(huán)節(jié)的推論,GPU cache導入abc數(shù)據(jù)時會分別創(chuàng)建一個transform節(jié)點,一個shape節(jié)點。而transform節(jié)點就是Maya內(nèi)置的transform節(jié)點,所以當然可以提供位移、旋轉、縮放等操作。
我們再看下一段代碼,在gpuCacheShapeNode.cpp中有如下定義:
這段代碼這足以證明gpuCache是一個標準的Shape node。倒數(shù)第一行意為ShapeNode的類型名是“gpuCache”,倒數(shù)第二行意為ShapeNode繼承自MPxSurfaceShape。這這里簡單介紹一下MPxSurfaceShape,該類主要用于實現(xiàn)新的shape,并且有可選、可操作的組件,還有與Maya中默認shape相似的行為。也就是說,ShapeNode是可以提供與默認Shape相似功能的,比如,在viewport2.0中能顯示并編輯點線面,能添加bevel一類的歷史節(jié)點。
但顯然gpuCache并沒有顯示頂點,在被選中時,顯示的邊緣也是dashed line,不是正常的實線。在這里我們應該去查看MPxSurfaceShapeUI類,MPxSurfaceShape和MPxSurfaceShapeUI是需要一并實現(xiàn)的,MPxSurfaceShape主要用于操作幾何體數(shù)據(jù),MPxSurfaceShapeUI則用于顯示幾何體。在gpuCache中這兩個類分別由ShapeNode、ShapeUI實現(xiàn)。
在ShapeNode中沒有實現(xiàn)setInternalValue()方法,而MPxSurfaceShape類中對頂點的編輯都是通過setInternalValue()來處理的,顯然ShapeNode不具備編輯頂點的接口,自然gpuCache也就無法編輯頂點了;
在ShapeUI只有drawBoundingBox()、drawWireframe()、drawShaded()三個繪制函數(shù),分別繪制boundingbox、模型線框及表面。在這個類里并沒有找到繪制頂點的函數(shù),這就是你在Viewport 2.0中無法看到gpuCache頂點的原因,無法看到頂點,自然也無法操作頂點。另外drawWireframe()函數(shù)中也指定了線框的繪制方式:kLineStippleShortDashed,強制Maya以虛線的方式繪制線框。
可以斷定,gpuCache的源碼中一定重寫相關方法。繼續(xù)閱讀源碼能夠看到在gpuCacheSubSceneOverrride.h文件中有如下聲明:
1class SubSceneOverride : public MHWRender::MPxSubSceneOverride
MPxSubSceneOverride是Viewport 2.0的繪圖基類,該類允許用戶完整的定義渲染單元(MRenderItem),通過update()方法將計算后的geometry數(shù)據(jù)添加到MRenderItem,再通過繪圖函數(shù)進行繪制。該類主要用于在使用Viewport 2.0時繪制sub-scene類型的DAG節(jié)點。SubSceneOverride子類在gpuCachePluginMain.cpp中通過MHWRender::MDrawRegistry::registerSubSceneOverrideCreator()方法注冊到了Maya中,并與ShapeNode建立關系。這就意味著一旦創(chuàng)建了gpuCache的DAG Shape Node實例,就會有SubSceneOverride負責它在Viewport 2.0中的繪制工作。當然具體的點線面繪制工作由Viewport 2.0來執(zhí)行,SubSceneOverride主要負責獲取renderitem,并將處理過的renderitem推送至Viewport 2.0。
而幾何體數(shù)據(jù)就是在MPxSubSceneOverride中發(fā)送到GPU memory中的。這個過程會涉及到更多的開發(fā)細節(jié),以后有時間再做分享吧。
另外,為什么不能在gpuCache上添加諸如bevel之類的歷史節(jié)點呢?答案很簡單,因為gpuCache節(jié)點沒有outmesh屬性,bevel這類節(jié)點是無法連上去的。
以上,就是gpuCache不能編輯頂點的真相。
評論
查看更多