Odd behavior of GLSL switch statement

Refresh

November 2018

Views

268 time

4

I want to draw a cube with a different texture on each side. I pass Textnum parameter containing the number of the texture to use through my vertex shader to my fragment shader, then use a switch statement to choose appropriate sampler2D based on its value:

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

With this code, the cube is not being rendered at all. The textures are loaded properly, because when I do:

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

I see a cube with the same texture on each side. I tried this with all of the samplers, each time getting the expected result. What's interesting is when I do:

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

I still see no cube, even when the instruction after the switch statement should overwrite its effects. What's wrong with my code?

EDIT: So apparently this is not the end yet, because if I do this (which should be correct on the grounds of the Wikipedia article):

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

The cube is still not being rendered at all. This doesn't work as well:

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: Here is the complete example for anyone interested: http://pastebin.com/R2scC0ZZ

1 answers

3

Текстурные выборки в GLSL должны быть в едином потоке управления. В вашем случае поток неоднороден, так как это зависит от атрибута. В этом случае не автоматические градиентов вычисляются и все, что зависит от градиентов (мипмапы, анизотропная фильтрация) не будут работать.

Эта ссылка дает более подробное объяснение об этом лице.

Edit: Теперь, когда я увидел полный код, это довольно понятно, почему он не работает. Шейдер просто не связывает со следующим сообщением об ошибке:

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

Это сообщение о том, что именно здесь проблема: Integer varyings не может интерполировать между стадиями шейдерных, таким образом , они должны быть определены с плоской интерполяции. Очевидно , что вы не проверяли на наличие ошибок компоновщика. Поскольку программа не связывала, каждый вызов glUseProgramпроизводит , GL_INVALID_ENUMтак как программа не действует , и ничего не было обращено. Замена определения атрибута с:

flat out uint Textnum;

а также

flat in uint Textnum;

должны решить эту проблему.

BDL