How to do it...

To create a shader program that utilizes the geometry shader to render silhouette edges, use the following steps:

  1. Use the following code for the vertex shader:
layout (location = 0 ) in vec3 VertexPosition; 
layout (location = 1 ) in vec3 VertexNormal; 
 
out vec3 VNormal; 
out vec3 VPosition; 
 
uniform mat4 ModelViewMatrix; 
uniform mat3 NormalMatrix; 
uniform mat4 ProjectionMatrix; 
uniform mat4 MVP; 
void main() {
    VNormal = normalize( NormalMatrix * VertexNormal); 
    VPosition = vec3(ModelViewMatrix *  
                     vec4(VertexPosition,1.0)); 
    gl_Position = MVP * vec4(VertexPosition,1.0); 
} 
  1. Use the following code for the geometry shader:
layout( triangles_adjacency ) in; 
layout( triangle_strip, max_vertices = 15 ) out; 
 
out vec3 GNormal; 
out vec3 GPosition; 
 
// Which output primitives are silhouette edges 
flat out bool GIsEdge; 
 
in vec3 VNormal[];   // Normal in camera coords. 
in vec3 VPosition[]; // Position in camera coords. 
 
uniform float EdgeWidth;  // Width of sil. edge in clip cds. 
uniform float PctExtend;  // Percentage to extend quad 
 
bool isFrontFacing( vec3 a, vec3 b, vec3 c ) {
    return ((a.x * b.y - b.x * a.y) +  
            (b.x * c.y - c.x * b.y) + 
            (c.x * a.y - a.x * c.y)) > 0; 
} 
void emitEdgeQuad( vec3 e0, vec3 e1 ) {
    vec2 ext = PctExtend * (e1.xy - e0.xy); 
    vec2 v = normalize(e1.xy - e0.xy); 
    vec2 n = vec2(-v.y, v.x) * EdgeWidth; 
 
    // Emit the quad 
    GIsEdge = true;   // This is part of the sil. edge 
 
    gl_Position = vec4( e0.xy - ext, e0.z, 1.0 );  
    EmitVertex(); 
    gl_Position = vec4( e0.xy - n - ext, e0.z, 1.0 );  
    EmitVertex(); 
    gl_Position = vec4( e1.xy + ext, e1.z, 1.0 );  
    EmitVertex(); 
    gl_Position = vec4( e1.xy - n + ext, e1.z, 1.0 ); 
    EmitVertex(); 
 
    EndPrimitive(); 
} 
 
void main() {
    vec3 p0 = gl_in[0].gl_Position.xyz /  
              gl_in[0].gl_Position.w; 
    vec3 p1 = gl_in[1].gl_Position.xyz /  
              gl_in[1].gl_Position.w; 
    vec3 p2 = gl_in[2].gl_Position.xyz /  
              gl_in[2].gl_Position.w; 
    vec3 p3 = gl_in[3].gl_Position.xyz /  
              gl_in[3].gl_Position.w; 
    vec3 p4 = gl_in[4].gl_Position.xyz /  
              gl_in[4].gl_Position.w; 
    vec3 p5 = gl_in[5].gl_Position.xyz /  
              gl_in[5].gl_Position.w; 
 
    if( isFrontFacing(p0, p2, p4) ) { 
        if( ! isFrontFacing(p0,p1,p2) )  
                    emitEdgeQuad(p0,p2); 
        if( ! isFrontFacing(p2,p3,p4) )  
                    emitEdgeQuad(p2,p4); 
        if( ! isFrontFacing(p4,p5,p0) )  
                    emitEdgeQuad(p4,p0); 
    } 
 
    // Output the original triangle 
    GIsEdge = false; // Triangle is not part of an edge. 
 
    GNormal = VNormal[0]; 
    GPosition = VPosition[0]; 
    gl_Position = gl_in[0].gl_Position; 
    EmitVertex(); 
    GNormal = VNormal[2]; 
    GPosition = VPosition[2]; 
    gl_Position = gl_in[2].gl_Position; 
    EmitVertex();
    GNormal = VNormal[4]; 
    GPosition = VPosition[4]; 
    gl_Position = gl_in[4].gl_Position; 
    EmitVertex(); 
 
    EndPrimitive(); 
}

  1. Use the following code for the fragment shader:
//*** Light and material uniforms... **** 
 
uniform vec4 LineColor;  // The sil. edge color 
 
in vec3 GPosition;  // Position in camera coords 
in vec3 GNormal;    // Normal in camera coords. 
 
flat in bool GIsEdge; // Whether or not we're drawing an edge 
 
layout( location = 0 ) out vec4 FragColor; 
 
vec3 toonShade( ) {
   // *** toon shading algorithm from Chapter 4 *** 
} 
 
void main() {
    // If we're drawing an edge, use constant color,  
    // otherwise, shade the poly. 
    if( GIsEdge ) { 
        FragColor = LineColor; 
    } else { 
        FragColor = vec4( toonShade(), 1.0 ); 
    }
} 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.123.120