OpenGL - 添加细分控制着色器会产生黑屏

时间:2015-03-04 21:19:20

标签: opengl glsl opengl-4

当我将tesselation控件着色器添加到渲染程序时,视口变黑。没有TSC,顶点和片段着色器工作正常。我还检查了编译错误但没有发生。

顶点着色器:

#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;
}

细分控制着色器:

#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;
}

细分评估着色器:

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

片段着色器:

#version 410 core

in VS_OUT {
    vec4 color;
} fs_in;

out vec4 color;

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

我忘了检查着色器链接错误。这就是我得到的:

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

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

如果没有其他着色器的代码,很难帮助您。 确保您的曲面细分评估着色器也是正确的。默认值应如下所示:

#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;
}

重要的部分是使用贴片三角形上的重心坐标进行插值。此外,如果在顶点着色器而不是tess eval着色器中完成变换,您也可能会得到奇怪的结果。

编辑:

现在您添加了曲面细分阶段,您无法将不同的数据从顶点着色器传递到片段着色器。实际上它们是原始贴片三角形中的新三角形,因此您必须为所有这些新三角形设置颜色。实际上,当您使用曲面细分阶段时,顶点着色器和tess控件通常会将顶点输入转发到tess eval着色器。

所以你的tess控件着色器应该是这样的:

#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 */
}

你和eiv着色器也必须插入颜色:

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

当然,在您的片段着色器中,您现在拥有TES_OUT而不是VS_OUT

答案 1 :(得分:1)

我知道这个问题现在已经有两年了,但我可能会帮助将来遇到同样问题的人找到这个问题。

经过几个小时的尝试,我发现了问题。似乎Tessellation控件着色器的gl_in[].gl_Position输入不是由顶点着色器写入的。我怀疑这肯定是一个驱动程序错误(可能在NVidia驱动程序?)因为我想不出任何原因这不起作用。

解决方案:

不要依赖Tessellation Control Shader的gl_in[].gl_Position输入,而是自己在自定义输出/输入中传递它们。

这可以通过(大致)将以下行添加到相应的着色器来完成:

// 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]);
}