Robinson Merillat
Robinson Merillat

Reputation: 1

OpenGL Flickering Fragments when Drawing Wireframe

I've been following along with the OpenGL 4 Shading Language cookbook and have gotten a teapot rendering with bezier surfaces. The next step I'm attempting is to draw a wireframe over the surfaces using a geometry shader. The directions can be found here on pages 228-230. Following the code that is given, I've gotten the wireframe to display, however, I also have multiple fragments that flicker different shades of my material color.

An image of this can be seen here

I have narrowed down the possible issues and have discovered that for some reason, when I perform my triangle height calculations, I am getting variable side lengths for my calculations, as if I hard code the values in the edge distance for each vertex of the triangle within the geometry shader, the teapot no longer flickers, but neither does a wireframe display. (variables ha, hb, hc in the geo shader below)

I was wondering if anyone has run into this issue before or are aware of a workaround.

Below are some sections of my code:

Geometry Shader:

/*
 *   Geometry Shader
 *
 *   CSCI 499, Computer Graphics, Colorado School of Mines
 */

#version 410 core

layout( triangles ) in;

layout( triangle_strip, max_vertices = 3 ) out;

out vec3 GNormal;
out vec3 GPosition;
out vec3 ghalfwayVec;
out vec3 GLight;

noperspective out vec3 GEdgeDistance;

in vec4 TENormal[];
in vec4 TEPosition[];
in vec3 halfwayVec[];
in vec3 TELight[];

uniform mat4 ViewportMatrix;

void main() {
    // Transform each vertex into viewport space
    vec3 p0 = vec3(ViewportMatrix * (gl_in[0].gl_Position / gl_in[0].gl_Position.w));
    vec3 p1 = vec3(ViewportMatrix * (gl_in[1].gl_Position / gl_in[1].gl_Position.w));
    vec3 p2 = vec3(ViewportMatrix * (gl_in[2].gl_Position / gl_in[2].gl_Position.w));

    // Find the altitudes (ha, hb and hc)
    float a = length(p1 - p2);
    float b = length(p2 - p0);
    float c = length(p1 - p0);
    float alpha = acos( (b*b + c*c - a*a) / (2.0*b*c) );
    float beta = acos( (a*a + c*c - b*b) / (2.0*a*c) );
    float ha = abs( c * sin( beta ) );
    float hb = abs( c * sin( alpha ) );
    float hc = abs( b * sin( alpha ) );

    // Send the triangle along with the edge distances

    GEdgeDistance = vec3( ha, 0, 0 );
    GNormal = vec3(TENormal[0]);
    GPosition = vec3(TEPosition[0]);
    gl_Position = gl_in[0].gl_Position;
    EmitVertex();

    GEdgeDistance = vec3( 0, hb, 0 );
    GNormal = vec3(TENormal[1]);
    GPosition = vec3(TEPosition[1]);
    gl_Position = gl_in[1].gl_Position;
    EmitVertex();

    GEdgeDistance = vec3( 0, 0, hc );
    GNormal = vec3(TENormal[2]);
    GPosition = vec3(TEPosition[2]);
    gl_Position = gl_in[2].gl_Position;
    EmitVertex();

    EndPrimitive();

    ghalfwayVec = halfwayVec[0];
    GLight = TELight[0];
}

Fragment Shader:

/*
 *   Fragment Shader
 *
 *   CSCI 441, Computer Graphics, Colorado School of Mines
 */

#version 410 core

in vec3 ghalfwayVec;
in vec3 GLight;
in vec3 GNormal;
in vec3 GPosition;
noperspective in vec3 GEdgeDistance;

layout( location = 0 ) out vec4 FragColor;

uniform vec3 mDiff, mAmb, mSpec;
uniform float shininess;

uniform light {
    vec3 lAmb, lDiff, lSpec, lPos;
};

// The mesh line settings
uniform struct LineInfo {
    float Width;
    vec4 Color;
} Line;

vec3 phongModel( vec3 pos, vec3 norm ) {
    vec3 lightVec2 = normalize(GLight);
    vec3 normalVec2 = -normalize(GNormal);
    vec3 halfwayVec2 = normalize(ghalfwayVec);

    float sDotN = max( dot(lightVec2, normalVec2), 0.0 );
    vec4 diffuse = vec4(lDiff * mDiff * sDotN, 1);

    vec4 specular = vec4(0.0);
    if( sDotN > 0.0 ) {
        specular = vec4(lSpec * mSpec * pow( max( 0.0, dot( halfwayVec2, normalVec2 ) ), shininess ),1);
    }

    vec4 ambient = vec4(lAmb * mAmb, 1);

    vec3 fragColorOut = vec3(diffuse + specular + ambient);
    // vec4 fragColorOut = vec4(0.0,0.0,0.0,0.0);
    return fragColorOut;
}


void main() {
    //     /*****************************************/
    //     /******* Final Color Calculations ********/
    //     /*****************************************/

    // The shaded surface color.
    vec4 color=vec4(phongModel(GPosition, GNormal), 1.0);

    // Find the smallest distance
    float d = min( GEdgeDistance.x, GEdgeDistance.y );
    d = min( d, GEdgeDistance.z );

    // Determine the mix factor with the line color
    float mixVal = smoothstep( Line.Width - 1, Line.Width + 1, d );
    // float mixVal = 1;

    // Mix the surface color with the line color
    FragColor = vec4(mix( Line.Color, color, mixVal ));
    FragColor.a = 1;
}

Upvotes: 0

Views: 401

Answers (1)

Robinson Merillat
Robinson Merillat

Reputation: 1

I ended up stumbling across the solution to my issue. In the geometry shader, I was passing the halfway vector and the light vector after ending the primitive, as such, the values of these vectors was never being correctly sent to the fragment shader. Since no data was given to the fragment shader, garbage values were used and the Phong shading model used random values to compute the fragment color. Moving the two lines after EndPrimative() to the top of the main function in the geometry shader resolved the issue.

Upvotes: 0

Related Questions