GLSL: 启用/禁用纹理 + 着色器

4
我正在寻找一种从着色器访问OpenGL状态的方式。非常棒的资源GLSL Quick Reference Guide在这方面并没有真正帮助到我。
在我正在处理的示例中,我有以下两个着色器:
顶点着色器:
void    main()
{
    gl_FrontColor = gl_Color;
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = ftransform();
}

片段:

uniform sampler2D   tex;
uniform float   flattening;

void main( void ) 
{
    vec4    texel;
    texel = texture2D(tex, gl_TexCoord[0].st);
    texel.r *= gl_Color.r;
    texel.g *= gl_Color.g;
    texel.b *= gl_Color.b;
    texel.a *= gl_Color.a;
    gl_FragColor = texel;
}

当我渲染未贴图的多边形时,它们的 alpha 值是正确的,但是它们被分配了黑色颜色。
1、如果禁用了 GL_TEXTURE_2D,我可以设置什么条件检查,使变量 'texel' 被设置为 vec4(1.0, 1.0, 1.0, 1.0) 而不是从纹理中采样?
2、如果我为不同的贴图模式编写不同的着色器,并在它们之间切换,在使用 glEnable/glDisable(GL_TEXTURE_2D) 时处理速度会更快吗?

简短说明:您可以将texel *= gl_Color写成一个向量操作,而不是4个标量操作。 - Macke
谢谢,它是否有硬件加速?难道不是一个函数调用和4个标量操作而不是4个标量操作吗? - zyndor
1
它是加速的(如果您没有在软件中运行所有着色器,否则您将进入每帧几秒的领域),但没有额外的函数调用。确实,它仍然是4个标量操作(在现代GPU上),我只是把它看作是一个向量操作,但这样编写代码也更容易跟踪和调试。(GLSL编译器会大量内联以避免函数调用开销。) - Macke
这确实是一个向量操作(=所有4个乘法并行计算),如果可能的话,您应该始终尝试分组标量操作。GLSL编译器可以将4个单独的操作优化为一个操作,但我不会指望它这样做。 - Maurice Gilden
2个回答

8

很抱歉,但是你无法从GLSL中访问这种状态,这一点是确定的。

事实上,在未来的GLSL中,你必须自己发送所有的非统一变量/属性,例如没有魔法的gl_ModelViewMatrix、gl_LightPosition、gl_Normal等。只有基本的东西,如gl_Position和gl_FragColor将可用。

这就使您的第二个问题失去了意义,但如果您发现在着色器中使用#ifdef更方便,则可以使用它来启用/禁用不同纹理模式下的部分内容,而不是编写单独的着色器。

另外请注意,分支通常会导致速度较慢,因此如果您需要速度,请尽可能避免使用它。(尤其是不规则动态分支,因为片元是在SIMD块中处理的,即使只适用于一个或几个片元,块中的所有片元都必须计算相同的指令。)


感谢您提供深入的答案。我刚意识到(除了遇到思维障碍之外),我可以声明一个统一的布尔变量来启用/禁用,并将相关调用路由到该变量。 - zyndor
可以做到,但速度不会很快。 - Macke

3

我见过的一种方法是在渲染没有纹理的多边形时,使用一个1x1的纹理,该纹理只有一个像素点(1.0, 1.0, 1.0, 1.0)。相比于切换着色器来说,切换纹理应该会更加高效,而且1x1的纹理可以完全适配纹理缓存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接