GLSL switch语句的奇怪行为 [英] Odd behavior of GLSL switch statement

查看:717
本文介绍了GLSL switch语句的奇怪行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

即使switch语句后的指令应覆盖其效果,我仍然看不到任何多维数据集.我的代码有什么问题?

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

显然,这还没有结束,因为如果我这样做(根据Wikipedia文章应该是正确的):

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

这是有兴趣的人的完整示例: http://pastebin.com/R2scC0ZZ

Here is the complete example for anyone interested: http://pastebin.com/R2scC0ZZ

推荐答案

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

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.

既然我看到了完整的代码,就很清楚为什么它不起作用了.着色器根本不与以下错误消息链接:

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

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

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;

flat in uint Textnum;

应该解决问题.

这篇关于GLSL switch语句的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆