【问题标题】:OpenGL - Adding Tessellation Control Shader yields black screenOpenGL - 添加镶嵌控制着色器会产生黑屏
【发布时间】:2017-05-08 07:57:37
【问题描述】:

当我将镶嵌控制着色器添加到渲染程序时,视口变黑。如果没有 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

我该如何解决这个问题?

【问题讨论】:

  • 如果它只适用于顶点和片段着色器,这意味着您没有绘制GL_PATCHES 基元。当您使用 TCS 时,您需要这样做,并设置每个补丁的顶点数。您将需要这样的电话:glPatchParameteri ​(GL_PATCH_VERTICES​​, N); 某处。
  • 我确实用 N=3 来称呼它,但根本没有三角形。

标签: opengl glsl opengl-4


【解决方案1】:

如果没有其他着色器的代码,很难为您提供帮助。 确保您的曲面细分评估着色器也是正确的。默认的应该是这样的:

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

而且你 tess eval 着色器还必须插入颜色:

#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

【讨论】:

  • 其他着色器没有影响代码,因此镶嵌着色器不应该介意。他们只是画了一个没有任何投影的蓝色三角形。但是,我不知道我需要一个曲面细分评估着色器。现在已修复,但我的视口仍然是黑色的。我将在我的原始帖子中添加更多代码。
  • 我现在检查了着色器链接错误,似乎着色器管道有错误,我该如何解决?
  • 您必须将颜色转发到镶嵌评估着色器并为新顶点插入颜色,我更新了答案。
  • 我按照你的解释编辑了着色器。现在我没有链接错误,但屏幕仍然是黑色的。如果我将片段着色器中的颜色设置为像 color = vec4(0.0,0.0,1.0,1.0); 这样的恒定颜色,我也没有得到任何蓝色三角形。所以,曲面细分可能有问题,但我不明白。
【解决方案2】:

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


经过几个小时的尝试,我发现了问题所在。似乎 Tessellation Control Shader 的 gl_in[].gl_Position 输入没有被顶点着色器写入。我怀疑这一定是驱动程序错误(可能在 NVidia 驱动程序中?)因为我想不出任何原因这不应该工作。

解决方案:

不要依赖镶嵌控制着色器的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]);
}

【讨论】:

    猜你喜欢
    • 2020-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多