当我将镶嵌控制着色器添加到渲染程序中时,视口变黑。如果没有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
我该怎么解决这个问题?
如果没有其他着色器的代码,很难帮助您。请确保镶嵌评估着色器也是正确的。默认的应该是这样的:
#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
。
我知道这个问题已经两年了,但我这可能会帮助未来遇到同样问题并找到这个问题的人。
经过几个小时的努力,我终于解决了这个问题。顶点着色器似乎没有写入细分控制着色器的gl_in[].gl_Position
输入。我怀疑这一定是一个驱动程序错误(可能在英伟达驱动程序中?),因为我想不出任何原因不应该这样做。
解决方案:
不依赖细分控制着色器的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]);
}