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

Posted

技术标签:

【中文标题】在片段着色器中,为啥我不能使用平面输入整数来索引 sampler2D 的统一数组?【英文标题】:In a fragment shader, why can't I use a flat input integer to index a uniform array of sampler2D?在片段着色器中,为什么我不能使用平面输入整数来索引 sampler2D 的统一数组? 【发布时间】:2019-01-27 12:50:04 【问题描述】:

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

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

【问题讨论】:

可以使用sampler2DArray吗?见Sampler 使用 mipmap 是一个很酷的主意。我认为对于这个应用程序,我将使用大型纹理页面,为每个页面维护单独的绘制列表,并在我的渲染函数中的绘制元素调用之间切换活动纹理。 【参考方案1】:

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

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

GLSL 3.30 Specification - 4.1.7 Samplers (page 21)GLSL ES 3.00 Specification - 4.1.7.1 Samplers (page 29):

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


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

GLSL 4.60 Specification - 4.1.11. Opaque Types (page 31)GLSL ES 3.20 Specification - 4.1.11. Opaque Types (page 32)

当在着色器中聚合成数组时,不透明类型只能使用动态统一的整数表达式进行索引。 [...]

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

GLSL 4.60 Specification - 3.8.2. Dynamically Uniform Expressions (page 20)GLSL ES 3.20 Specification - 3.9.3. Dynamically Uniform Expressions (page 22)

如果评估它的所有片段都获得相同的结果值,则片段着色器表达式是动态统一的。


flat 片段着色器输入对于单个图元是不变的,但对于整个网格,对于由单个“绘制调用”分别处理的所有图元而言,调用组是不一样的。 (flat) 片段着色器输入不是 Dynamically uniform。

【讨论】:

感谢您提供如此详细的回放。我看到在新版本的 GLSL 中我可以做我想做的事。我可能应该升级我的笔记本电脑,它的 GPU 无法升级,只支持 GLSL 130。 @MarkL 不,采样器数组的索引永远不能依赖于变化的 (in) 变量。 是的,这是有道理的,但我使用的是平面 int,它是不变的。 @MarkL 不,它对于单个图元是不变的,但对于整个网格来说不是不变的,对于由单个“绘制调用”分别处理的所有图元来说它是不一样的调用组。 好的,我现在明白了.. 我曾假设着色器是按图元执行的。明显的废话,现在我开始考虑它!感谢您帮助我解决这个问题。

以上是关于在片段着色器中,为啥我不能使用平面输入整数来索引 sampler2D 的统一数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用在质心处计算的光来实现平面着色?

在顶点和片段着色器中访问同名统一失败

为啥我需要在 webgl 着色器中定义一个精度值?

有没有办法在片段着色器中使用先前渲染的结果?

从顶点到片段着色器的平滑 64 位输入 - “错误 C7570:64 位输入应该是平坦的”

为啥我的着色器中的 GLSL 纹理坐标不是线性的?