翻译自: 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)