当前位置: 首页 > 知识库问答 >
问题:

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

宇文和昶
2023-03-14

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

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

共有1个答案

慕容安易
2023-03-14

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

在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页)

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

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

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

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

平面片段着色器输入对于单个基元是不变的,但对于整个网格不是,对于分别由单个“绘图调用”处理的所有基元,它对于调用组是不一样的。(平面)片段着色器输入在动态上不统一。

 类似资料:
  • 我需要一个着色程序,然后我需要一个着色程序。一旦我从我的着色器中获得和后,是否可以将它们作为采样器发送到着色器中,以便在屏幕上渲染到四元体上? 我需要将颜色附件发送到第二个着色器的原因是,我正在不同的监视器上渲染和将出现在一个屏幕上,而将出现在另一个屏幕上。。。 我正在做测试视力的心理实验。我的第一个着色器处理我的原始纹理集,但由于两个输出纹理所需的大部分处理是相同的,所以如果不需要,我基本上不想

  • 我希望在2D OpenGL应用程序上实现着色器。我的计划是将场景渲染到帧缓冲区对象,然后使用着色器将该帧缓冲区对象渲染到屏幕。 这是我绘制到帧缓冲区对象的场景,然后从那里绘制到屏幕。使用箭头键可以让月亮四处移动(我很自豪!) 但是,当我尝试使用着色器程序将帧缓冲区对象渲染到屏幕上时,我得到以下结果: 这是非常可悲的。这个片段着色器是我从一个教程中得到的,我相信问题一定是统一变量。 以下是片段着色器

  • 问题内容: 我想清除并更改给定URL上的输入值。我使用的js不会执行任何操作,也不会导致任何错误。为什么会发生这种情况,我该如何解决? 问题答案: 一个可能且可能的答案是,在尝试清除的元素之前,您还有另一个具有相同名称的元素。 请检查html并检查是否找到多个元素,然后采用第一个。 另外,您可以使用css选择器,例如:

  • 应该是这样的: 而不是这个: 我的屏幕宽度是1000,高度是600。 我正在使用OpenGL(lwjgl)在java中制作2d游戏。我可以画一个三角形,但使用我的着色器时它不起作用。着色器编译没有错误,但屏幕变黑了。 我完全不知道该怎么做,我必须启用什么吗? 这是我在GLSL中的vertexShader代码 这是片段着色器: 我最近发现,如果我只运行它有效的片段着色器,我就会得到指定的颜色。但是如

  • 假设我遇到这样的问题:现在我有一个帧缓冲区,一个纹理只包含一个颜色组件(例如,GL_RED)已经绑定到它。碎片着色器会是什么样子?我想答案是: ...浮出ex_color; 颜色=。。。; 我的问题来了:着色器会自动检测帧缓冲区的格式并向其写入值吗?如果片段着色器输出浮点值但帧缓冲区格式GL_RGBA怎么办? 顺便问一下,创建只有一个组件的纹理的正确方法是什么?我阅读了g-truc的示例,其示例如

  • 我创建了一个FBO,并有一个纹理绑定作为其颜色附件,我有多个着色器程序,对纹理做一些后处理,一切都很好,但它对我来说没有意义,纹理可以用作输入(sampler2D)以及同时着色器的输出。 以下是我采取的步骤: 创建一个FBO。 创建一个纹理,并将其绑定为的颜色附件。 调用将绑定到帧缓冲区目标。 调用使用着色器程序。 调用来绘制一些东西(最终在上绘制,因为当前绑定)。 调用使用shader程序,它在