GLSL-幾何著色器詳解跟執行個體(GS:Geometry Shader)[轉]

來源:互聯網
上載者:User

標籤:des   cWeb   style   blog   http   java   

【OpenGL4.0】GLSL-幾何著色器詳解和執行個體(GS:Geometry Shader)

一、什麼是幾何著色器(GS:Geometry Shader)


Input Assembler(IA)從頂點緩衝區上的輸入資料流中接收頂點資料,並且把資料項目轉換為規範的格式。vertex shader通常用來把頂點從模型空間變換到平面空間,vertex shader讀取一個頂點,輸出一個頂點。Pixel Shader讀取單一pixel屬性,輸出包含顏色和Z資訊的的片斷。而geometry shader是DirectX10提出的,把同一地區的所有頂點作為輸入,產生新的頂點或者地區。此外資料流輸出(steam output)把geometry shader輸出的頂點資訊複製為4個連續的輸出緩衝子集。理論上來說,steam output的輸出能力和Input Assembler的輸入能力相匹配。
Shader就是一段可以改變像素、頂點和幾何學特徵的小程式。Vertex Shader是專門處理多邊形頂點的。那麼Geometry shader就是專門用來處理情境中的幾何圖形。在過去Vertex Shader每一次運行只能處理一個頂點的資料,並且每次只能輸出一個頂點的結果。在整個遊戲情境中,繪製的幾何圖形的任務量非常龐大,如果僅僅依靠Vertex Shader單一來完成,效率會極其低下。

現在DX10的設計師們在頂點與像素的處理過程中又加入了(Geometry shader)幾何著色器。它可以根據頂點的資訊來批量處理幾何圖形,對Vertex附近的資料進行函數處理,快速創造出新的多邊形。通過stream out將這些結果傳遞給其他Shader或buffer,將CPU從複雜龐大的幾何運算中解放出來。大爆炸,粒子效果,瀑布流水等複雜又關聯的情境都可以用Geometry shader很逼真的表現出來。

圖一是渲染管線。


圖一 渲染管線

GS位於VS與PS之間,可以完成許多模型層面上的工作諸如LOD。以往這些工作都是在CPU上完成的,佔用了寶貴的CPU迴圈 —— CPU可是很繁忙的東西,遊戲邏輯、音樂、輸入接受都是靠它,卻無法提高多少效能,CPU的並行計算效能是遠遠無法和GPU相比的。



二、幾何著色器功能簡介

GS被設計針對每個圖元執行一次。它能夠訪問圖元的所有頂點,以及與其相關的輸入變數的值。換句話說,如果前一階段提供了某一個輸出變數,那麼GS就可以訪問圖元中所有頂點的那個變數的值。因此,GS中的輸入變數都是數群組類型。


需要注意的是,GS所接受的圖元和以前的不同,它只接受“可調整的”圖元。


可調整的圖元(Adjacency Primitive)

在OpenGL中,我們定義了新的圖元類型:

GL_LINES_ADJACENCY_EXT 
GL_LINE_STRIP_ADJACENCY_EXT 
GL_TRIANGLES_ADJACENCY_EXT 
GL_TRIANGLE_STRIP_ADJECENCY_EXT

我們可以在glBegin()、glDrawElements()中將他們作為新的參數使用。下面分別說明這4中類型的特點。

(1)Lines with Adjacecy


4*N個頂點被提供,N是要繪製的線段的數目。線段在#1個#2之間繪製,#0和#3提供調整資訊。

(2)Line Strip with Adjacency


頂點數目是N+3,N是要繪製的線段的數目。線段在#1、#2、。。。、#N+1之間繪製,#0和#N+2提供調整資訊。

(3)Triangles with Adjacency


頂點數目是6*N,組成三角形的是#0、#2、#4.而#1、#3、#5定義了修正三角形。

(4)Triangle Strip with Adjacency


頂點數目是2N+4.#0、#2、。。。定義三角形序列。其他的定義調整三角形。


在著色器連結之前,必須調用glProgramParameter進行相應的設定。

(1)設定GS可以輸出的最大頂點數目

glProgramParameteriEXT( progname, GL_GEOMETRY_VERTICES_OUT_EXT, int value )

(2)設定GS接收的圖元的類型

glProgramParameteriEXT( progname, GL_GEOMETRY_INPUT_TYPE_EXT, int value )

需要注意的是,GS的輸出圖元的類型必須和輸入圖元的類型匹配。

value的可能取值是:

A、GL_POINTS

B、GL_LINES

對應的輸入圖元類型可以是:GL_LINES、GL_LINE_STRIP、GL_LINE_LOOP

C、GL_LINES_ADJACENCY_EXT

對應的輸入圖元類型可以是:GL_LINES_ADJACENCY_EXT、GL_LINES_STRIP_ADJACENCY_EXT

D、GL_TRIANGLES

對應的輸入圖元類型可以是:GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN

E、GL_TRIANGLE_ADJACENCY_EXT

對應的輸入圖元類型可以是:GL_TRIANGLES_ADJACENCY_EXT、GL_TRIANGLE_STRIP_ADJACENCY_EXT

(3)設定輸出圖元類型

glProgramParameteriEXT( progname, GL_GEOMETRY_OUTPUT_TYPE_EXT, int value )

value的可能取值是:

GL_POINTS

GL_LINE_STRIP

GL_TRIANGLE_STRIP


GS可以輸出0個、1個或者多個圖元。這些圖元的類型和它從前一階段接收到的圖元的類型不一定相同。然而,GS不能輸出多種類型的圖元。比如,GS可以接收三角形,輸出多個線段序列,或者是輸出0個或多個三角形序列。

這就是的GS有多種用途。下面是幾個典型例子。一個GS可以依據某些準則比如可見度來移除一些圖元。GS也可以產生額外的圖元擴大所渲染的對象的形狀。GS也可以計算圖元的額外資訊,而把圖元原封不動的輸出。GS也可以輸出和輸入圖元完全不同的圖元。


GLSL中GS與VS的互動


在GS中,綠色正方形所表示的是由變數gl_VerticesIn所指定的,即最大維數。

GS內建輸出變數:
varying out vec4 gl_FrontColor;
varying out vec4 gl_BackColor;
varying out vec4 gl_FrontSecondaryColor;
varying out vec4 gl_BackSecondaryColor;
varying out vec4 gl_TexCoord[]; // at most gl_MaxTextureCoords
varying out float gl_FogFragCoord;



GS內建輸入變數:
varying in vec4 gl_FrontColorIn[gl_VerticesIn];
varying in vec4 gl_BackColorIn[gl_VerticesIn];
varying in vec4 gl_FrontSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_BackSecondaryColorIn[gl_VerticesIn];
varying in vec4 gl_TexCoordIn[gl_VerticesIn][]; // at most will be// gl_MaxTextureCoords
varying in float gl_FogFragCoordIn[gl_VerticesIn];
varying in vec4 gl_PositionIn[gl_VerticesIn];
varying in float gl_PointSizeIn[gl_VerticesIn];
varying in vec4 gl_ClipVertexIn[gl_VerticesIn];

 


GS的功能實現基於兩個很重要的內建函數:EmitVertex和EndPrimitive.這兩個函數使得GS能夠傳送多個頂點或者圖元到管線的下一階段。GS為一個頂點定義輸出變數,然後調用EmitVertex。之後,GS就能夠接著定義下一個頂點的相關輸出變數,再次調用EmitVertex。在對圖元的所有頂點完成相同的操作之後,GS調用EndPrimitive讓OpenGL知道圖元的所有頂點都傳送完畢。如果沒有顯式調用EndPrimitive,系統會隱式調用。不過顯式調用是一個好的習慣,建議這麼做。如果GS沒有調用EmitVertex,那麼輸入的圖元就不會被渲染。


需要注意的是,GS保證輸出由輸入圖元產生的結果的順序和輸入圖元的順序是相同的。這會造成效能上的影響。比如,多個著色器單元並行運算,結果必須被儲存然後進行排序。為了在相容性和效率之間平衡,Shader  Model4.0做了一個限制:每一次執行最多隻能產生1024個32位的值。


三、幾何著色器運用執行個體

下面介紹一個執行個體:用GS實現一個粒子系統,繪製了很多上面貼了紋理的小正方形。

效果如下:


頂點著色器:

#version 400layout (location = 0) in vec3 VertexPosition;uniform mat4 ModelViewMatrix;uniform mat3 NormalMatrix;uniform mat4 ProjectionMatrix;void main(){    gl_Position = ModelViewMatrix * vec4(VertexPosition,1.0);}

幾何著色器:

#version 400layout( points ) in;layout( triangle_strip, max_vertices = 4 ) out;uniform float Size2;   // Half the width of the quaduniform mat4 ProjectionMatrix;out vec2 TexCoord;void main(){    mat4 m = ProjectionMatrix;    gl_Position = m * (vec4(-Size2,-Size2,0.0,0.0) + gl_in[0].gl_Position);    TexCoord = vec2(0.0,0.0);    EmitVertex();    gl_Position = m * (vec4(Size2,-Size2,0.0,0.0) + gl_in[0].gl_Position);    TexCoord = vec2(1.0,0.0);    EmitVertex();    gl_Position = m * (vec4(-Size2,Size2,0.0,0.0) + gl_in[0].gl_Position);    TexCoord = vec2(0.0,1.0);    EmitVertex();    gl_Position = m * (vec4(Size2,Size2,0.0,0.0) + gl_in[0].gl_Position);    TexCoord = vec2(1.0,1.0);    EmitVertex();    EndPrimitive();}

片斷著色器:

#version 400in vec2 TexCoord;uniform sampler2D SpriteTex;layout( location = 0 ) out vec4 FragColor;void main(){    FragColor = texture(SpriteTex, TexCoord);}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.