翻譯自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader Library)php
親愛的讀者們, 我回來了! 已經三週沒發表新文章了... 不少事情須要去作, 再加上跟明媚的天氣 -- 致使沒有新文章給 Geek3D
.app
今天咱們來看看一個簡單而有用的幾何着色器
(geometry shaders
)的應用: 法線可視化
(normal visualizer). 我已經在文章Simple Introduction to Geometry Shaders in GLSL (Part 1) 和 Simple Introduction to Geometry Shaders in GLSL (Part 2 中討論過 GLSL
的 幾何着色器
.翻譯
一個 幾何着色器
容許建立一個新的幾何圖形(一個頂點, 一條線, 或者一個多邊形) on the fly. 咱們將會利用這個特性生成一個三角形網格的頂點和麪的可視化法線的線條.3d
本文的示例用GLSL Hacker編寫, 你能夠在 Code Sample Pack 的 GLSL_Geometry_Shader_Normal_Visualizer/
目錄中找到所有的源碼. 你能夠來這裏下載(我建議使用最新的 DEV
版本).code
通常而言, GLSL
程序並不特定於 GLSL Hacker
. 你能夠在任何 OpenGL/WebGL
應用中使用它們, 只須要作一些小小的修改(着色器輸入).orm
截圖: 索引
頂點法線的生成很簡單. 每一個法線都是由兩個頂點構成的一條線. 第一個頂點就是輸入的頂點(屬於當前的網格-mesh). 第二個頂點就是第一個頂點沿着它的法線方向作一段位移後的新頂點.ip
V0 = Pi V1 = pi + (normal_length * N)
i
是頂點索引(範圍0~2
是由於幾何着色器
的輸入是一個三角形).Pi
和 Ni
是第i
個頂點的位置
和法線
.V0
和 V1
是新線條的頂點.頂點法線
是幾何着色器
輸入頂點的一部分. 下面是完整的原來渲染頂點法線的 GLSL
程序(頂點
+幾何
+片斷
).get
這是一個簡單的透傳頂點着色器. 這裏沒有任何變換(譯者注:指矩陣變換), 頂點將在幾何着色器
中被變換用於最終的顯示.源碼
#version 150 in vec4 gxl3d_Position; in vec4 gxl3d_Normal; out Vertex { vec4 normal; vec4 color; } vertex; void main() { gl_Position = gxl3d_Position; vertex.normal = gxl3d_Normal; vertex.color = vec4(1.0, 1.0, 0.0, 1.0); }
幾何着色器
作了大部分的工做: 它把頂點從本地空間(譯者注: 也叫模型空間)變換到窗口空間(裁剪空間)(gxl3d_ModelViewProjectionMatrix
)而且建立了那些線條.
#version 150 layout(triangles) in; // Three lines will be generated: 6 vertices layout(line_strip, max_vertices=6) out; uniform float normal_length; uniform mat4 gxl3d_ModelViewProjectionMatrix; in Vertex { vec4 normal; vec4 color; } vertex[]; out vec4 vertex_color; void main() { int i; for(i=0; i<gl_in.length(); i++) { vec3 P = gl_in[i].gl_Position.xyz; vec3 N = vertex[i].normal.xyz; gl_Position = gxl3d_ModelViewProjectionMatrix * vec4(P, 1.0); vertex_color = vertex[i].color; EmitVertex(); gl_Position = gxl3d_ModelViewProjectionMatrix * vec4(P + N * normal_length, 1.0); vertex_color = vertex[i].color; EmitVertex(); EndPrimitive(); } }
#version 150 in vec4 vertex_color; out vec4 Out_Color; void main() { Out_Color = vertex_color; }
截圖:
頂點法線的生成很簡單. 讓咱們看看如何在幾何着色器
中生成面法線. 咱們所須要的是定義一個三角形的三個頂點. 幸運的是這些頂點是幾何着色器
的輸入, 感謝這一行代碼:
layout(triangles) in;
若是 P0
, P1
和P2
是面頂點的位置, 面法線就是下面的叉積(cross product
)的結果:
V0 = P0-P1 V1 = P2-P1 N = cross (V1, V0)
截圖:
如今咱們已經有了編寫面法線可視化的全部理論. 下面就是單獨的 幾何着色器
的代碼, 由於跟前面的 GLSL
程序相比, 只有 幾何着色器
作了更新. 這個 幾何着色器
生成 3
條頂點法線(黃色), 1
條面法線(紅色): 4
條線或者 8
個新頂點.
#version 150 layout(triangles) in; layout(line_strip, <b>max_vertices=8</b>) out; uniform float normal_length; uniform mat4 gxl3d_ModelViewProjectionMatrix; in Vertex { vec4 normal; vec4 color; } vertex[]; out vec4 vertex_color; void main() { int i; //------ 3 lines for the 3 vertex normals // for(i=0; i<gl_in.length(); i++) { vec3 P = gl_in[i].gl_Position.xyz; vec3 N = vertex[i].normal.xyz; gl_Position = gxl3d_ModelViewProjectionMatrix * vec4(P, 1.0); vertex_color = vertex[i].color; EmitVertex(); gl_Position = gxl3d_ModelViewProjectionMatrix * vec4(P + N * normal_length, 1.0); vertex_color = vertex[i].color; EmitVertex(); EndPrimitive(); } //------ One line for the face normal // vec3 P0 = gl_in[0].gl_Position.xyz; vec3 P1 = gl_in[1].gl_Position.xyz; vec3 P2 = gl_in[2].gl_Position.xyz; vec3 V0 = P0 - P1; vec3 V1 = P2 - P1; vec3 N = cross(V1, V0); N = normalize(N); // Center of the triangle vec3 P = (P0+P1+P2) / 3.0; gl_Position = gxl3d_ModelViewProjectionMatrix * vec4(P, 1.0); vertex_color = vec4(1, 0, 0, 1); EmitVertex(); gl_Position = gxl3d_ModelViewProjectionMatrix * vec4(P + N * normal_length, 1.0); vertex_color = vec4(1, 0, 0, 1); EmitVertex(); EndPrimitive(); }
OpenGL Superbible, fifth edition, chapter 11
Mesh Exploder with Geometry Shaders
Simple Introduction to Geometry Shaders in GLSL (Part 2)
Particle Billboarding with the Geometry Shader (GLSL)
(Shader Library) Bumpy Sphere Env Normal Mapping
Simple Introduction to Geometry Shaders in GLSL (Part 1)