引言:
最近剛好有個專案要用到這個技術,就學習了下dxsdk的sample裡面的instancing10。
例項化的技術是利用多個頂點緩衝區有效的合併,減少draw call的次數,從而有效的提高程式的效能。例項化比較適合於相同物體的重複渲染,例如粒子系統,草被模擬等等。
本文實現了乙個非常簡單,甚至簡陋的例項化的demo。雖然demo非常簡單,但是例項化的每個必要的元素都已經被體現出來了。相對於dx的sample而言簡單的多,不過同樣可以把這個技術簡單解釋清楚。
正文:
例項化適合於相同物體的反覆渲染,例如草,粒子系統等。傳統的渲染方法中,相同物體由於一些細節不同,例如位置,顏色等資訊,使得draw call被迫呼叫多次。對於很小的元素,例如草,可能視野裡面會有上萬根草,那麼如果僅僅因為紋理,方向甚至位置不同,就必須呼叫上萬次drawcall,從而嚴重降低了程式的效能。利用例項化技術,雖然這些mesh在一些簡單的細節上有不同,但是大體上還是一致的,所以可以僅僅用乙個draw call就可以把所有的mesh渲染出來,這樣節省了cpu與gpu之間的頻寬,非常高效。
下面是這次demo的截圖:
這個demo的畫面非常簡單,就是乙個靜態的粒子集合的渲染。但是所有的球體都是利用乙個draw call渲染出來的,就是說每一幀只draw一次。那麼下面我簡單介紹下這個技術的基本原理:
首先需要了解的乙個概念是ia(input assembler)。在vertexshader之前,我們的輸入是乙個或者幾個頂點緩衝區,而這些頂點緩衝區並不是vs的輸入,事實上vs的輸入是經過ia處理後的資訊。ia實際上是不可以程式設計的,它就像乙個狀態機一樣,只能設定簡單的幾個狀態,但是由於不同的應用程式對於ia的要求基本都一致,所以完全沒有可程式設計的必要。ia的目的就是根據頂點緩衝區,圖元拓撲結構以及輸入的資料格式(layout)生成vs所需要的資訊。我們在渲染任何物體之前,都需要為ia設定好這幾個狀態,分別是通過iasetinputlayout,iasetvertexbuffers,iasetprimitivetopology來搞定的。
在簡單的了解了ia之後,我們來看一下instancing的基本思想。其實,例項化就是通過把每個例項的不同的資訊儲存在緩衝(可能是頂點緩衝,常量buffer等)裡面,然後利用過個頂點緩衝區來設定,從而使生成的每個頂點都包含有自己custom的資料定義。舉個簡單的粒子,我們看到這個程式中的每個球體的位置是不同的。按照傳統的做法,偽**如下:
for( i : 0 to spherenum )上面的方法,也是最笨拙的方法。僅僅因為每次的draw call呼叫中world matrix不同,就必須呼叫多次。而其實每次的呼叫都是很相似的。其實我們在set world matrix的時候,我們更新的是某乙個constant value。從巨集觀的角度上來說,就是通過constant value來設定球體的位置資訊。但是既然我們可以描述每個頂點的法線,紋理座標等資訊,我們完全可以為每個頂點描述world matrix資訊,其實就是在vs的輸入裡面多加乙個float4而已(這裡我只用了float4,因為球體不需要旋轉。如果需要旋轉的話,完全可以加四個float4組成乙個matrix)。下面的問題是,我們怎麼樣利用ia生成我們想要的資訊:
假設我們需要渲染100個球體,每個球體256個三角形。那麼我們不可能在cpu端寫入256*100個三角形的頂點資料,因為這樣以來,從cpu到gpu端的傳輸代價會非常大,而這些代價完全可以避免(當然,這裡面如果預處理的話,這些代價也可以無視,但是這種方法實際上相當於用cpu去做gpu擅長的事情,**看著很不舒服)。那麼實際上我們應該怎麼做呢?其實也很簡單,dx10幫我們提供了非常友好的介面。
這個demo裡面需要兩個頂點緩衝區,乙個來描述球體的頂點資訊,256個三角形而已(768個頂點)。另乙個用來描述位置資訊,100個頂點而已。兩個加起來還不到1k個頂點,相對於上面的768000個頂點少了上千倍。這些資料是要走pcie匯流排的!那麼似乎上面的資訊無法描述這麼多個球體,但是通過ia處理之後,我們完全可以達到同樣的效果。唯一需要設定的就是input layout。
//the vertex layout利用上面連個頂點緩衝,我們要設定如上的layout。第乙個element描述的是球體的頂點資訊。第二個element描述的是位置資訊。我們注意到第五個引數,d3d10_input_per_vertex_data/d3d10_input_per_instance_data,這裡面如果是前者,ia會把頂點緩衝中的每個頂點當做頂點處理。而如果是後者,ia實際上是把頂點緩衝區中的每個元素當做例項來處理的。那麼最後ia可以為我們生成 numberofvertex * numberofinstance 個頂點資料,這也正是我們想要的資料。d3d10_input_element_desc layout =
, };
有了這些資料,我們就可以進行頂點處理了。看看vs中有什麼變化:
//the input struct of the vertex shader很簡單的乙個vs。但是這裡我們注意加粗體的一行,這裡我們為每個頂點變換的矩陣是viewprojectionmatrix。我們沒有做worldmatrix變換,原因很簡單,是因為我們根本就沒有worldmatrix這樣乙個常量。我們每個頂點的world matrix都已經儲存到了頂點結構中的vtransform中了。實際上input.vposition + input.vtransform就相當於做了world matrix的變換了。struct vs_input
;//the default vertex shader
vs_output defaultvertexshader( vs_input input )
通過上面的步驟,就可以渲染出來不同位置的球體了。但是我們注意到,vs的input裡面並沒有color這一屬性,為什麼球體會有不同的顏色呢?其實球體的顏色資訊是儲存到了constant array中的,因為簡單的幾種顏色就可以滿足人的視覺需求了,完全沒有必要每個球體都生成不同的顏色。所以這裡面我只生成了8中基本的顏色。每個頂點中是有uinstanceid的屬性的,通過對於這個屬性求模運算,我們可以為每個球體選擇出相應的顏色。這裡的uinstanceid是ia為我們生成的,而不是我們自己寫入的資料。
有了這些處理,我們就可以實現乙個簡單的例項化的demo了,下面是源**:
mysql的基本原理 Mysql 基本原理
mysql 基本原理 mysql是一種關聯式資料庫管理系統,關聯式資料庫將資料儲存在不同的表中,而不是將所有資料放在乙個大倉庫內,這樣就增加了速度並提高了靈活性 ysql是資料庫登入命令 uroot預設超級使用者登入 p 預設沒密碼 中寫密碼 mysqladmin uroot password 12...
PWM的基本原理及應用例項
脈寬調變 pwm 是利用微處理器的數字輸出來對模擬電路進行控制的一種非常有效的技術,廣泛應用在從測量 通訊到功率控制與變換的許多領域中。pwm是一種對模擬訊號電平進行數字編碼的方法。通過高解析度計數器的使用,方波的占空比被調製用來對乙個具體模擬訊號的電平進行編碼。pwm訊號仍然是數字的,因為在給定的...
pwm控制的基本原理 PWM控制的基本原理
pwm pulse width modulation 控制 脈衝寬度調製技術,通過對一系列脈衝的寬度進行調製,來等效地獲得所需要波形 含形狀和幅值 pwm控制技術在逆變電路中應用最廣,應用的逆變電路絕大部分是pwm型,pwm控制技術正是有賴於在逆 變電路中的應用,才確定了它在電力電子技術中的重要地位...