GPU Pro2 - 1.Terrain and Ocean Rendering with Hardware Tessellation
最近時(shí)間多了起來,準(zhǔn)備撿起扔下了的渲染部分的知識(shí)。想拜讀下GPU Pro系列并且做個(gè)筆記,不知道自己能否堅(jiān)持下來,但愿可以吧。自己能力也有限,寫的東西也只是自己的理解,肯定有很多理解不到位甚至錯(cuò)誤的地方,也希望如果哪位大神看到了可以指正。關(guān)于tessellation,這篇博客介紹的很好https://blog.csdn.net/weixin_43675955/article/details/85005229
如果想讓場(chǎng)景更真實(shí),你可能需要細(xì)節(jié)更高,面數(shù)更多的模型,但是這樣會(huì)使得cpu計(jì)算增加,運(yùn)行變慢。
The best solution for tessellation is the recently developed tessellator stage in DirectX 11. This stage, together with the hull and the domain shader, allows the programmer to tessellate very quickly into the GPU. With this method you can send low-level detail meshes to the GPU and generate the missing geometry to the GPU depending on the camera distance, angle, or whatever you want.?
Tessellation(細(xì)分曲面)技術(shù)是將低模細(xì)節(jié)度低的模型輸入至gpu中,在DirectX11之后,在hull 和 domain shader中可以通過tessellation快速的增加細(xì)節(jié)來增強(qiáng)表現(xiàn)力,卻又不需要損耗cpu的性能。
?
?
通過DirectX 11中的渲染流水線可以看出,在Vertex Shader和 Geometry Shader之間插入了 Hull Shader Stage ,Tessellator Stage 和 Domain Shader Stage三個(gè)階段,用于處理Tessellation。
Hull Shader Stage
Hull shader 的 輸入比較特殊,叫做 contral point patch list。常規(guī)情況下,vertex shader的輸出是頂點(diǎn), 但是如果要用硬件曲面細(xì)分,那么頂點(diǎn)著色器輸出就不再是頂點(diǎn),而是control point的patch,一個(gè)patch包含多個(gè)control point,最多可以包含32個(gè)。vertex shader輸出patch給HS用。
Hull shader 的輸出包含兩部分,一部分是control points(可以在Hull shader階段進(jìn)行修改),另一部分是一些常量,用于后續(xù)的tessellator stage 和 domain shader stage。為了計(jì)算這兩部分輸出,在該階段需要有兩個(gè)函數(shù)。
第一個(gè)函數(shù)叫做Constant Hull Shader,這個(gè)函數(shù)executed for every patch,也就是以patch為單位執(zhí)行,在這個(gè)函數(shù)里,設(shè)置了tessellation的一些參數(shù)。
由示例代碼可以看出,該函數(shù)的輸入InputPatch是一個(gè)模板類,對(duì)應(yīng)的是頂點(diǎn)著色器的輸出,如果這里要用曲面細(xì)分的話,就不能在VS中乘以世界和攝像機(jī)投影矩陣(這是因?yàn)樵趖essellation中新加入了細(xì)節(jié),新生成了頂點(diǎn),如果在vertex shader中就做完了這些操作,新生成的頂點(diǎn)咋辦吶),而是要留到細(xì)分結(jié)束后再變換(如果有幾何著色器的話就留到幾何著色器階段再變換)。然后這里可以用SV_PrimitiveID獲取Primitive的id。這里可以把細(xì)分等級(jí)和離攝像機(jī)的遠(yuǎn)近、屏幕覆蓋范圍、朝向、粗糙度等掛鉤,而不是寫一個(gè)定的值,可以起到優(yōu)化的效果。
該函數(shù)的輸出有兩個(gè)值,分別為SV_TessFactor和SV_InsideTessFactor,前者是邊的細(xì)分等級(jí),后者是面片中心的細(xì)分等級(jí)。前者有幾條邊就要輸出幾個(gè),分別對(duì)應(yīng)每條邊的參數(shù),后者則要輸出兩個(gè),分別對(duì)應(yīng)的是u和v方向。
struct PatchTess { float EdgeTess[4] : SV_TessFactor; float InsideTess[2] : SV_InsideTessFactor; // Additional info you want associated per patch. }; PatchTess ConstantHS(InputPatch<VertexOut, 4> patch, uint patchID : SV_PrimitiveID) { PatchTess pt; // Uniformly tessellate the patch 3 times. pt.EdgeTess[0] = 3; // Left edge pt.EdgeTess[1] = 3; // Top edge pt.EdgeTess[2] = 3; // Right edge pt.EdgeTess[3] = 3; // Bottom edge pt.InsideTess[0] = 3; // u-axis (columns) pt.InsideTess[1] = 3; // v-axis (rows) return pt; }第二個(gè)函數(shù)叫做Control Point Hull Shader,這個(gè)部分是每個(gè)control point都調(diào)用一次,因此和頂點(diǎn)著色器類似,只不過對(duì)象是control point,在這個(gè)階段我們可以改變曲面的表達(dá)形式,比如把輸入的三角面(三個(gè)control point)變成由包含十個(gè)control point的patch控制的貝塞爾曲線輸出,等等。
Control Point HS要定義不少屬性,其中domain是patch type,可選的有tri,quad或者isoline。
partitioining是細(xì)分模式,integer的細(xì)分等級(jí)會(huì)突變,而fractional_odd或者fractional_even的細(xì)分等級(jí)會(huì)漸變,頂點(diǎn)會(huì)逐漸移動(dòng)直到消失,而不會(huì)突然pop出來或者消失。
outputtopology輸出的三角面的winding order,有triangle_cw,triangle_ccw,line這三個(gè)選項(xiàng)
outputcontrolpoints是輸出頂點(diǎn)的數(shù)量,也就是hs的執(zhí)行次數(shù),可以用SV_OutputControlPointID獲取當(dāng)前Control Point的ID。
patchconstantfunc則是constantHS的名字
maxtessfactor是最大細(xì)分?jǐn)?shù)量,dx11最高支持到64,這里可以手動(dòng)設(shè)置得更低。
?
The Tessellation Stage
Hull shader結(jié)束之后就是細(xì)分階段,該階段由硬件完成,不可編程,通過Hull shader中設(shè)置的參數(shù),該階段會(huì)新生成頂點(diǎn),但是得出的只是頂點(diǎn)的uv,實(shí)際的位置等信息是在之后的domain shadr中進(jìn)行計(jì)算。
在這里,可以理解下之前設(shè)置的參數(shù),SV_TessFactor和SV_InsideTessFactor。
對(duì)于四邊形圖元,邊的順序是左上右下順時(shí)針。如下圖中的第一個(gè)圖:每個(gè)邊的參數(shù)都為4,也就是說每個(gè)邊等分成了四份。中心的參數(shù)為(4,4),也就是中心也等分成了4份。
再如下圖中的第三個(gè)圖:左邊和上邊參數(shù)為2,則二等分,右邊和下邊為4則是4等分。中心參數(shù)為2和4,分別對(duì)應(yīng)u方向和v方向,所以中心部分橫向(u方向)二等分,縱向(v方向)四等分。
對(duì)于三角形圖元,細(xì)分操作同,只不過中心參數(shù)只有一個(gè),中心的操作是在每個(gè)三角形定點(diǎn)到中心的延長(zhǎng)線方向進(jìn)行。
Domain Shader Stage
In the domain shader we have to reconstruct every final vertex and we have to calculate the position, normal, and texture coordinates. This is the part where the difference between terrain and ocean rendering is more important.
該階段的輸入是細(xì)分好了的曲面,在該階段我們要做的是根據(jù)uv來算出頂點(diǎn)的位置,法線和真正的紋理坐標(biāo)。然后如果沒有幾何著色器的話,我們需要在這個(gè)階段把頂點(diǎn)變換到屏幕坐標(biāo)里。
這里說的給定uv是針對(duì)四邊面,如果用的是三個(gè)control point的patch,那么這里給定的是質(zhì)心坐標(biāo)系下的uvw。
Terrain&Ocean
說實(shí)話,后邊這些沒有太看懂。。還望各位大佬指導(dǎo),大體總結(jié)幾個(gè)點(diǎn)吧:
1.對(duì)于tessellation新生成的頂點(diǎn),x和z方向的坐標(biāo)可以通過patch中已有頂點(diǎn)的位置用插值方式得到。對(duì)于Terrain,y方向的坐標(biāo)可以通過高度圖和法線圖得到已有頂點(diǎn)的高度參數(shù)后進(jìn)行插值,對(duì)于Ocean,y坐標(biāo)可以通過波浪函數(shù)計(jì)算得到。
2.很重要的一點(diǎn)是使用一些技術(shù)來計(jì)算tessellation factor,也就是tessellation的參數(shù)。比如對(duì)于某條邊,它必然屬于兩個(gè)patch,要確保在這兩個(gè)patch中該邊的參數(shù)一致。再比如通過mipmap參數(shù)計(jì)算tessellation參數(shù),距離攝像機(jī)越近的,tessellation參數(shù)越大,距離攝像機(jī)越遠(yuǎn)的地方,tessellation參數(shù)越小。
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的GPU Pro2 - 1.Terrain and Ocean Rendering with Hardware Tessellation的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: markdown工具对比: 作业部落 v
- 下一篇: GPU Pro2 - 3.Proced