GLSL switch语句的奇怪行为

时间:2017-01-17 10:12:07

标签: opengl glsl

我想画一个每边都有不同纹理的立方体。我将包含要通过顶点着色器使用的纹理编号的Textnum参数传递给我的片段着色器,然后使用switch语句根据其值选择合适的sampler2D:

#version 150

in float Shade;
in vec2 Textcoord;
in uint Textnum;

out vec4 outColor;

uniform sampler2D tex0;
uniform sampler2D tex1;
uniform sampler2D tex2;
uniform sampler2D tex3;
uniform sampler2D tex4;
uniform sampler2D tex5;

void main()
{
    vec4 textColor;
    switch(Textnum)
    {
        case 0u: textColor = texture(tex0, Textcoord); break;
        case 1u: textColor = texture(tex1, Textcoord); break;
        case 2u: textColor = texture(tex2, Textcoord); break;
        case 3u: textColor = texture(tex3, Textcoord); break;
        case 4u: textColor = texture(tex4, Textcoord); break;
        case 5u: textColor = texture(tex5, Textcoord); break;
    }
    outColor = textColor * vec4(Shade, Shade, Shade, 1);
}

使用此代码,根本不会渲染多维数据集。正确加载纹理,因为当我这样做时:

void main()
{
    vec4 textColor; 
    textColor = texture(tex0, Textcoord);
    outColor = textColor * vec4(Shade, Shade, Shade, 1);
}

我看到每边都有相同纹理的立方体。我尝试了所有采样器,每次都得到预期的结果。当我这样做时,有趣的是:

void main()
{
    vec4 textColor;
    switch(Textnum)
    {
        case 0u: textColor = texture(tex0, Textcoord); break;
        case 1u: textColor = texture(tex1, Textcoord); break;
        case 2u: textColor = texture(tex2, Textcoord); break;
        case 3u: textColor = texture(tex3, Textcoord); break;
        case 4u: textColor = texture(tex4, Textcoord); break;
        case 5u: textColor = texture(tex5, Textcoord); break;
    }
    textColor = texture(tex0, Textcoord);
    outColor = textColor * vec4(Shade, Shade, Shade, 1);
}

我仍然看不到立方体,即使switch语句之后的指令应该覆盖它的效果。我的代码出了什么问题?

编辑:显然这还不是结束,因为如果我这样做(根据维基百科的文章应该是正确的):

void main()
{
    vec4 textColor;
    vec4 textColor0 = texture(tex0, Textcoord);
    vec4 textColor1 = texture(tex1, Textcoord);
    vec4 textColor2 = texture(tex2, Textcoord);
    vec4 textColor3 = texture(tex3, Textcoord);
    vec4 textColor4 = texture(tex4, Textcoord);
    vec4 textColor5 = texture(tex5, Textcoord);
    switch(Textnum)
    {
        case 0u: textColor = textColor0; break;
        case 1u: textColor = textColor1; break;
        case 2u: textColor = textColor2; break;
        case 3u: textColor = textColor3; break;
        case 4u: textColor = textColor4; break;
        case 5u: textColor = textColor5; break;
    }
    outColor = textColor * vec4(Shade, Shade, Shade, 1);
}

立方体仍然没有被渲染。这也不起作用:

void main()
{
    vec4 textColor[6];
    textColor[0] = texture(tex0, Textcoord);
    textColor[1] = texture(tex1, Textcoord);
    textColor[2] = texture(tex2, Textcoord);
    textColor[3] = texture(tex3, Textcoord);
    textColor[4] = texture(tex4, Textcoord);
    textColor[5] = texture(tex5, Textcoord);
    outColor = textColor[Textnum] * vec4(Shade, Shade, Shade, 1);
}

EDIT2:以下是感兴趣的人的完整示例:http://pastebin.com/R2scC0ZZ

1 个答案:

答案 0 :(得分:3)

glsl中的纹理查找必须处于统一控制流程中。在您的情况下,流量是不均匀的,因为它取决于属性。在这种情况下,不会计算自动渐变,并且所有依赖于渐变(mipmap,各向异性过滤)的内容都不起作用。

This link提供了有关此面孔的更详细说明。

编辑:现在我看到了完整的代码,很明显为什么它不起作用。着色器根本不会与以下错误消息链接:

0(4) : error C5215: Integer varying TextNum must be flat

此消息告诉您这里的问题到底是什么:不能在着色器阶段之间插入整数变换,因此必须使用平面插值定义它们。显然你没有检查链接器错误。由于该程序未链接,因此对glUseProgram的每次调用都会生成GL_INVALID_ENUM,因为该程序无效且未绘制任何内容。用以下代码替换属性定义:

flat out uint Textnum;

flat in uint Textnum;

应该解决问题。