Reputation:
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
Upvotes: 4
Views: 1363
Reputation: 22168
Texture lookups in glsl have to be in uniform control flow. In your case the flow is non-uniform since it depends on a attribute. In this case no automatic gradients are calculated and everything that depends on gradients (mipmaps, anisotropic filtering) will not work.
This link gives a more detailed explanation about this face.
Edit: Now that I saw the complete code, it is rather clear why it is not working. The shader simply doesn't link with the following error message:
0(4) : error C5215: Integer varying TextNum must be flat
This message tells you exactly what is the problem here: Integer varyings cannot be interpolated between shader stages, thus they have to be defined with flat interpolation. Obviously you didn't check for linker errors. Since the program did not link, every call to glUseProgram
produces a GL_INVALID_ENUM
because the program wasn't valid and nothing was drawn. Replacing the attribute definition with:
flat out uint Textnum;
and
flat in uint Textnum;
should solve the problem.
Upvotes: 3