????????幾何著色器是可編程渲染管線中的一個可選階段,位于頂點著色器之后和片段著色器之前。其核心能力在于動態生成和操作幾何體圖元。
一.圖元
????????了解圖元是理解幾何著色器的基礎和前提,因為幾何著色器的工作就是接收圖元,然后輸出圖元。
幾何著色器是以圖元為單位工作的:
輸入是圖元: 幾何著色器不像頂點著色器那樣單獨處理每個頂點。它的輸入是一個完整的圖元。這意味著它一次性接收構成一個點、一條線或一個三角形的所有頂點數據。例如,當它接收一個三角形時,它會同時獲得這個三角形的三個頂點及其所有屬性。
輸出是圖元: 同樣地,幾何著色器的輸出也不是孤立的頂點,而是組織成完整圖元(點、線或三角形)的頂點流。
1.什么是圖元?
在計算機圖形學中,圖元是構成任何 3D 幾何體的最基本構建塊。 它們是圖形硬件能夠直接理解和渲染的最小單位。
主要的三種基本圖元類型是:
點 (Points): 最簡單的圖元,由一個頂點定義。它沒有面積或體積,只代表一個空間位置。
線 (Lines): 由兩個頂點定義,連接這兩個頂點形成一條線段。它只有長度,沒有面積或體積。
三角形 (Triangles): 由三個頂點定義,這三個頂點構成一個平面多邊形。
2.圖元拓撲類型
在應用階段,CPU需要向GPU提交一系列數據和命令供其渲染。
????????應用階段最重要的任務是輸入裝配(input assembler)。輸入裝配階段會從顯存中讀取幾何數據(頂點和索引),再將它裝配為幾何圖元(geometry primitive)。
????????可是,單憑頂點和索引數據,GPU無法知道頂點究竟如何組成幾何圖元。例如,我們應將頂點2個一組解釋成線段,還是3個一組解釋為三角形呢?對此,我們需要通過指定圖元拓撲(primitive topology)?來告訴GPU如何利用頂點數據來表示幾何圖元。
在DirectX中,基礎圖元拓撲類型有以下五種:點列表(point list),線條帶(line strip),線列表(line list),三角形帶(triangle strip),三角形列表(triangle list)。
? ? ??
3.圖元與拓撲的關系
拓撲 (Topology) 是指幾何對象的連接性 (Connectivity) 或結構關系,它描述了點、邊、面之間是如何相互連接的,而不關注它們在空間中的具體位置或形狀。
圖元就是拓撲的基本表現形式:
頂點是拓撲的基本元素: 它們是構建所有圖元的基礎。
圖元類型定義了局部拓撲:
點圖元: 拓撲上是孤立的頂點。線圖元: 拓撲上是兩個頂點通過一條邊相連。三角形圖元: 拓撲上是三個頂點通過三條邊相連,形成一個面。
多個圖元組合形成復雜拓撲
二.幾何著色器是什么
????????幾何著色器是可編程渲染管線中的一個可選階段,位于頂點著色器之后和片段著色器之前。其核心能力在于動態生成和操作幾何體圖元。特點如下:
1.接收一個完整的圖元(Primitive)作為輸入: 它可以是點、線或三角形。
2.動態生成新的圖元: 根據輸入,它可以決定輸出零個、一個或多個新的點、線或三角形。
3.修改圖元類型: 例如,將一個點擴展成一個四邊形(公告板),或者將一個線段擴展成一個帶狀物體。
幾何著色器位于幾何處理階段的可選頂點處理階段。
三.幾何著色器的核心概念
幾何著色器的一般格式:
[maxvertexcount(N)]
void geom(triangle Attributes input[3], inout TriangleStream<Varyings> stream)
{}
1.最大頂點數量
????????[maxvertexcount(N)] 用來指定幾何著色器單詞調用所輸出的頂點數量最大值。其中,N是幾何著色器單次調用所輸出的頂點數量最大值。幾何著色器每次輸出的頂點個數都可能不同,但是這個數量卻不能超過之前定義的最大值。
????????出于對性能方面的考慮,我們應當令maxvertexcount的值盡可能小。線管資料顯示,GS每次輸出的標量數量在1-20時,它將發揮出最佳的性能;而當27-40時,它的性能將下降到峰值性能的50%。
2.輸入圖元
幾何著色器最根本的特點是它處理的單位是完整的圖元。
頂點著色器中的輸出結構需要與幾何著色器的輸入結構對應一致。
你的頂點著色器中返回的是什么類型,幾何著色器的輸入結構就是什么類型。
1.HLSL語法定義
point YourAttributesStruct input[1]
line YourAttributesStruct input[2]
triangle YourAttributesStruct input[3]
通過幾何著色器函數的第一個參數來指定輸入的圖元類型。
2.輸入圖元類型
(1)點 (Point)
由一個頂點構成。
HLSL 定義:point InputStruct input[1] ,input[1]表示一個包含單個元素的數組。
input[0]即可訪問該點的頂點數據。
何時使用: 當你希望將模型中的離散點(例如粒子系統的粒子、點云數據、骨骼關節)擴展成更復雜的幾何體時(例如,將點變成公告板四邊形)。
(2)線 (Line)
由兩個頂點構成,連接形成一條線段。
HLSL 定義: line?InputStruct input[2]
input[0] 和input[1]分別訪問線段的起始點和結束點的頂點數據。
何時使用: 當你希望將模型中的線段(例如,線框模型、角色骨骼連接線、某些頭發渲染中的發束)加粗、變成帶狀幾何體或在其上生成其他結構時。
(3)三角形 (Triangle)
由三個頂點構成,形成一個平面。
HLSL 定義: triangle?InputStruct input[3]
input[0],input[1],input[2] 分別訪問三角形的三個頂點的頂點數據。
何時使用: 這是最常見的輸入類型,當你希望從網格的面(例如,頭皮表面、地形面)生成額外的幾何體時(如?Fin Fur 毛發、草地、樹葉等)。
3.輸出圖元流
????????幾何著色器不像頂點著色器那樣直接return一個頂點,它通過向一個輸出流 (Stream) 中Append?頂點來構建新的圖元。這個流會累積你生成并追加(Append)入流的頂點,并根據流的類型自動將它們組織成圖元。
????????這里OutputStruct必須是幾何著色器傳遞給片段著色器的數據結構。它至少需要包含SV_POSITION語義的裁剪空間位置。
1.HLSL語法定義
inout PointStream<YourOutputStruct> stream
inout LineStream<YourOutputStruct> stream
inout TriangleStream<YourOutputStruct> stream
????????在HLSL中,幾何著色器函數的第二個參數是標有inout修飾符的流類型(stream type)?。流類型存有一系列頂點,它們定義了幾何著色器輸出的幾何圖形。
流類型的本質是一種模板類型(template type),其模板參數用以指定輸出頂點的具體類型。
2.輸出圖元流類型
(1)PointStream<OutputStruct>
功能: 每次調用Apped()都會向流中添加一個頂點,并將其作為獨立的點圖元輸出。
何時使用: 當希望從輸入的幾何體中提取或生成離散的點時。
(2)LineStream<OutputStruct>
功能: 每兩次調用Append()會創建一個新的線段圖元。如果連續Append多個頂點,它們將形成一個線段條帶 (Line Strip),每條新線段都會重用前一條線段的最后一個頂點。
何時使用: 當你希望從輸入的幾何體中生成線段、輪廓線或細長的帶狀物時。
示例:stream.Append(v3):?輸出線段 (v2, v3)。
(3)TriangleStream<OutputStruct>
功能: 每三次調用Append()會創建一個新的三角形圖元。如果連續Append多個頂點,它們將形成一個三角形條帶 (Triangle Strip),這意味著每個新三角形都會重用前兩個三角形的頂點。
何時使用: 這是最常用的輸出類型,當你希望從輸入的圖元中生成面片(例如毛發、草葉、將點轉換為四邊形)。
4.關鍵函數
(1)stream.Append(OutputStruct vertexData)
作用: 將幾何著色器的輸出數據追加到一個現有的圖元流中。
參數: 接受一個OutputStruct類型的數據,其中包含了新生成頂點在裁剪空間的位置 (SV_POSITION
),以及該頂點需要傳遞給片段著色器的所有其他屬性(如 UV、法線、顏色等)。
工作機制: GPU 會將這個頂點數據暫存起來,直到湊夠構成一個完整圖元所需的頂點數量(例如,對于TriangleStream需要三個頂點)。一旦湊夠,該圖元就會被發送到渲染管線的下一個階段(光柵化器)。
消耗預算: 每次調用Append()都會消耗幾何著色器[maxvertexcount(N)]?預算中的一個頂點。
(2)stream.ResatrtStrip()
作用: 僅用于LineStream和TriangleStream,強制結束當前的基元條帶,開始一個新的條帶。如果當前的條帶沒有足夠的頂點被追加出來以填滿基元拓撲結構,那么末端的不完整基元將被丟棄。
何時使用: 當你需要生成多個不連續的圖元時。
例如: 如果你輸入一個三角形,希望輸出三個獨立的四邊形(而不是一個由 12 個頂點組成的連續三角形條帶),那么在每生成一個四邊形所需的四個頂點后,就需要調用 stream.ResatrtStrip()。這樣下一個四邊形的頂點將從一個新的條帶開始,而不會與前一個四邊形連接。
工作機制: 告訴GPU已經完成了當前這個條帶的圖元,請準備好接收下一個完全獨立的圖元序列。
參考文章
1.(90 封私信 / 80 條消息) Unity幾何著色器詳解 - 知乎