翻譯:探索GLSL-用幾何着色器(着色器庫)實現法線可視化
翻譯自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader Library)
- 譯者: FreeBlues
概述
親愛的讀者們, 我回來了! 已經三周沒發表新文章了... 很多事情需要去做, 再加上跟明媚的天氣 -- 導致沒有新文章給 Geek3D
.
今天我們來看看一個簡單而有用的幾何着色器
(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. 我們將會利用這個特性生成一個三角形網格的頂點和面的可視化法線的線條.
本文的示例用GLSL Hacker編寫, 你可以在 Code Sample Pack 的 GLSL_Geometry_Shader_Normal_Visualizer/
目錄中找到全部的源碼. 你可以來這里下載(我建議使用最新的 DEV
版本).
一般而言, GLSL
程序並不特定於 GLSL Hacker
. 你可以在任何 OpenGL/WebGL
應用中使用它們, 只需要做一些小小的修改(着色器輸入).
頂點法線可視化
截圖:
頂點法線的生成很簡單. 每個法線都是由兩個頂點構成的一條線. 第一個頂點就是輸入的頂點(屬於當前的網格-mesh). 第二個頂點就是第一個頂點沿着它的法線方向做一段位移后的新頂點.
V0 = Pi
V1 = pi + (normal_length * N)
i
是頂點索引(范圍0~2
是因為幾何着色器
的輸入是一個三角形).Pi
和Ni
是第i
個頂點的位置
和法線
.V0
和V1
是新線條的頂點.
頂點法線
是幾何着色器
輸入頂點的一部分. 下面是完整的原來渲染頂點法線的 GLSL
程序(頂點
+幾何
+片段
).
- 頂點着色器
這是一個簡單的透傳頂點着色器. 這里沒有任何變換(譯者注:指矩陣變換), 頂點將在幾何着色器
中被變換用於最終的顯示.
#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)