Exploring GLSL – Normal Visualizer with Geometry Shaders

来源:互联网 发布:js文本超出显示省略号 编辑:程序博客网 时间:2024/05/18 01:52

http://www.geeks3d.com/20130905/exploring-glsl-normal-visualizer-with-geometry-shaders-shader-library/

Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader Library)



GLSL Hacker, normal visualizer in GLSL


Article index:

  • 1 – Vertex Normal Visualizer
  • 2 – Face Normal Visualizer
  • 3 – References

Hi dear readers, I’m back! Three weeks without new posts… Lot of things to do combined with many sunny days == no post on Geeks3D 

Today, we’re going to see a simple but really useful application of geometry shaders: anormal visualizer. I already talked about GLSL geometry shaders HERE and HERE.

A geometry shader allows to create new geometry (a vertex, a line or a polygon) on the fly. We will use this feature to generate lines for visualizing the normals of both vertices and faces of a triangular mesh.

The demos of this article have been coded with GLSL Hacker and you can find all source codes in the Code Sample Pack under the GLSL_Geometry_Shader_Normal_Visualizer/ folder. You can download GLSL Hacker fromthis page (I recommend to grab the latest DEV version).

As usual, the GLSL programs are not specific to GLSL Hacker. You can use them in any OpenGL/WebGL application with minor changes only (shader inputs).

1 – Vertex Normal Visualizer

GLSL Hacker, vertex normal visualizer with geometry shader

The generation of the vertex normals is simple. Each normal is a line made up of two vertices. The first vertex is equal to the incoming vertex (which belongs to the current mesh). The second vertex is equal to the first vertex with a displacement along the direction of the vertex normal:

V0 = Pi
V1 = Pi + (normal_length * Ni)

Where i is the vertex index (0 to 2 because the input of the geometry shader is a triangle), Pi and Ni are the position and the normal of the i-th vertex. V0 and V1 are the vertices of the new line.

The vertex normal is part of the geometry shader input vertex. Here is the complete GLSL program (vertex + geometry + fragment) that renders the vertex normals:

Vertex shader
This is a simple pass-trough vertex shader. No transformation here, vertices will be transformed for final display in the geometry shader.

#version 150in 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);}

Geometry shader
The geometry shader does most of the work: it transforms vertices from local space to window space (gxl3d_ModelViewProjectionMatrix) and creates the lines:

#version 150layout(triangles) in;// Three lines will be generated: 6 verticeslayout(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();  }}

Fragment shader

#version 150in vec4 vertex_color;out vec4 Out_Color;void main(){  Out_Color = vertex_color;}

2 – Face Normal Visualizer

GLSL Hacker, face normal visualizer with geometry shader

The generation of the vertex normal was simple. Let’s see now how to generate the face normal in the geometry shader. All we need are the thee vertices that define a triangle. We are lucky because those vertices are the inputs of the geometry shader thanks to the following line:

layout(triangles) in; 

If P0, P1 and P2 are the positions of the face vertices, the face normal is the result of the followingcross product:

V0 = P0-P1V1 = P2-P1N = cross (V1, V0)

triangle, face normal, cross product

We have now all the theory we need to code the face normal visualizer. Here is the code of the geometry shader alone because compared to the previous GLSL program, only the geometry shader is updated. This geometry shader generates 3 lines for the vertex normals (in yellow) and one line for the face normal (in red): 4 lines or 8 vertices.

Geometry shader

#version 150layout(triangles) in;layout(line_strip, max_vertices=8) 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();}

3 – References

  • OpenGL Superbible, fifth edition, chapter 11





0 0
原创粉丝点击