在片段着色器中,为什么我不能使用平坦的输入整数来索引sampler2D的统一数组?

Mar*_*rkL 5 opengl glsl glsles

这里是着色器的新手,有点疑惑.

我想指定在渲染精灵数组时使用的纹理.所以我在它们的顶点数据中放置一个纹理索引,并将它作为一个平面值从我的顶点着色器传递到我的片段着色器,但不能用它来按预期索引一个采样器数组,因为编译器认为它是"非常数" ".相反,我不得不求助于下面令人作呕的代码.谁能解释一下这里发生了什么?

const int numTextures = 2;

uniform sampler2D textures[numTextures];

in vec2 uv;
flat in int tex;
out vec4 colour;

void main(void)
{
    // this caused the compiler error 
        /// "sampler arrays indexed with non-constant expressions"
    // colour = texture( textures[ tex ], uv );

    // hence this (ugh) ...
    switch ( tex ) 
    {
        case 0:
            colour = texture( textures[0], uv );
            break;
        case 1:
            colour = texture( textures[1], uv );
            break;
        default:
            colour = vec4( 0.3f, 0.3f, 0.3f, 1.0f );
            break;
    };
} 

Run Code Online (Sandbox Code Playgroud)

Rab*_*d76 6

[...]但不能使用它来按预期索引采样器数组,因为编译器将其视为"非常数"[...]

在GLSL最高版本3.30和GLSL ES版本3.00之间,纹理采样器数组的索引必须是一个常量表达式:

GLSL 3.30规格 - 4.1.7取样器(第21页)
GLSL ES 3.00规格 - 4.1.7.1取样器(第29页):

在着色器中聚合成数组的采样器(使用方括号[])只能用整数常量表达式索引[...]


在以后的版本中,采样器数组的索引必须是"动态统一的".这意味着索引必须与所有片段"相同"(例如,常数或统一变量).

GLSL 4.60规范 - 4.1.11.不透明类型(第31页)
GLSL ES 3.20规范 - 4.1.11.不透明类型(第32页)

当聚合到着色器内的数组中时,opaque类型只能使用动态统一的整数表达式进行索引.[...]

[...]采样器类型(例如sampler2D)是不透明类型[...]

GLSL 4.60规范 - 3.8.2.动态统一表达式(第20页)
GLSL ES 3.20规范 - 3.9.3.动态统一表达式(第22页)

如果评估它的所有片段获得相同的结果值,则片段着色器表达式是动态均匀的.

  • @MarkL 不,它对于单个基元是不变的,但对于整个网格来说是不变的,对于由单个“绘制调用”处理的所有基元也不是,对于调用组来说是不同的。 (2认同)