2
votes

When I add my tesselation control shader to my rendering program, the viewport gets black. Without the TSC the vertex and fragment shader work fine. I also checked for compile errors but no occurs.

Vertex shader:

#version 410 core

layout (location = 0) in vec4 offset;
layout (location = 1) in vec4 color;

out VS_OUT {
    vec4 color;
} vs_out;

void main(void) {
    const vec4 vertices[3] = vec4[3]
    (
        vec4( 0.25, -0.25, 0.5, 1.0),
        vec4(-0.25, -0.25, 0.5, 1.0),
        vec4( 0.25,  0.25, 0.5, 1.0)
    );

    // Add "offset" to our hard-coded vertex position
    gl_Position = vertices[gl_VertexID] + offset;

    // Output the color from input attrib
    vs_out.color = color;
}

Tessellation control shader:

#version 410 core

layout (vertices = 3) out;

void main(void) {
    if (gl_InvocationID == 0) {
        gl_TessLevelInner[0] = 5.0;
        gl_TessLevelOuter[0] = 5.0;
        gl_TessLevelOuter[1] = 5.0;
        gl_TessLevelOuter[2] = 5.0;
    }
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}

Tessellation evaluation shader:

#version 410 core

layout (triangles, equal_spacing, cw) in;

void main(void) {
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position +
                   gl_TessCoord.y * gl_in[1].gl_Position +
                   gl_TessCoord.z * gl_in[2].gl_Position);
}

Fragment shader:

#version 410 core

in VS_OUT {
    vec4 color;
} fs_in;

out vec4 color;

void main(void) {
    color = fs_in.color;
}

I forgot to check for shader linking errors. And this is what I get:

WARNING: Output of vertex shader '<out VS_OUT.color>' not read by tessellation control shader
ERROR: Input of fragment shader '<in VS_OUT.color>' not written by tessellation evaluation shader

How can I fix this?

2
If it works with just a vertex and fragment shader, that means you're not drawing GL_PATCHES primitives. You need to do that when you use a TCS, and set the number of vertices per-patch as well. You will need a call like this: glPatchParameteri ​(GL_PATCH_VERTICES​​, N); somewhere.Andon M. Coleman
I do call it with N=3, but no triangle at all.Flupp

2 Answers

2
votes

Without the code of the other shaders it's hard to help you. Make sure your tessellation evaluation shader is correct too. A default one should look like this :

#version 410 core
layout(triangles, equal_spacing, ccw) in;
layout(packed) uniform MatrixBlock
{
    mat4 projmat;
    mat4 viewmat;
} matTransform;
void main ()
{
    vec4 pos = gl_TessCoord.x * gl_in[0].gl_Position
             + gl_TessCoord.y * gl_in[1].gl_Position
             + gl_TessCoord.z * gl_in[2].gl_Position;
    gl_Position = matTransform.projmat * matTransform.viewmat * pos;
}

The important part is the interpolation using the barycentric coordinates on the patch triangle. Also if the transformations are done in your vertex shader instead of the tess eval shader you may have strange results too.

Edit :

Now that you added tessellation stages you can't pass varying data from the vertex shader to the fragment shader. Indeed their are new triangles in the original patch triangle so you have to set the color for all these new triangles too. Actually when you use tessellation stages, the vertex shader and the tess control usually forward the vertices input to the tess eval shader.

So your tess control shader should be like :

#version 410 core

layout (vertices = 3) out;

in VS_OUT { vec4 color; } tcs_in[];   /* new */
out TCS_OUT { vec4 color; } tcs_out[];  /* new */

void main(void) {
    if (gl_InvocationID == 0) {
        gl_TessLevelInner[0] = 5.0;
        gl_TessLevelOuter[0] = 5.0;
        gl_TessLevelOuter[1] = 5.0;
        gl_TessLevelOuter[2] = 5.0;
    }
    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    tcs_out[gl_InvocationID].color = tcs_in[gl_InvocationID].color; /* forward the data */
}

And you tess eval shader must also interpolate the color :

#version 410 core

layout (triangles, equal_spacing, cw) in;

in TCS_OUT { vec4 color; } tes_in[];  /* new */
out TES_OUT { vec4 color; } tes_out;  /* new */

void main(void) {
    tes_out.color = (gl_TessCoord.x * tes_in[0].color + /* Interpolation */
                     gl_TessCoord.y * tes_in[1].color +
                     gl_TessCoord.z * tes_in[2].color );
    gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position +
                   gl_TessCoord.y * gl_in[1].gl_Position +
                   gl_TessCoord.z * gl_in[2].gl_Position);
}

And of course in your fragment shader you now have a TES_OUT instead of VS_OUT.

1
votes

I know this question is two years old now, but I this might help people in the future who experience the same issue and find this question.


After many hours of trying I figured out the problem. It seems as though the gl_in[].gl_Position inputs of the Tessellation Control Shader are not written to by the vertex shader. I suspect this must be a driver bug (maybe in the NVidia drivers?) because I cannot think of any reason this shouldn't work.

Solution:

Instead of relying on the gl_in[].gl_Position inputs of the Tessellation Control Shader just pass them yourself in a custom output/input.

This can be done by (roughly )adding the following lines to the respective shader:

// vertex shader
// ...
out vec4 vVertexOut;

void main() {
    // ...
    vVertexOut = uMVPMatrix * inVertex; // output your transformed vertex
}

// tesselation control shader
// ...
in vec4 vVertexOut[];

out vec4 tVertexOut[];

void main() {
    // ...
    tVertexOut[gl_InvocationID] = vVertexOut[gl_InvocationID];
}

// tesselation evaluation shader
// ...
in vec4 tVertexOut[];

void main() {
    // ...
    gl_Position = (tVertexOut[0] * gl_TessCoord[0]) + (tVertexOut[1] * gl_TessCoord[1]) + (tVertexOut[2] * gl_TessCoord[2]);
}