GLIR数组元素运算符在sampler2D数组上的奇怪行为

时间:2017-07-26 00:54:31

标签: arrays opengl glsl

我正在编写一个简单的着色器并遇到一个奇怪的问题。

我基本上是使用sampler2D数组渲染一堆纹理,我从中选择所需的纹理。

#version 330 core

layout (location = 0) out vec4 color;

in DATA
{
    vec4 position;
    vec4 color;
    vec2 texCoord;
    flat int texID;
} fs_in;

uniform sampler2D textures[16];

void main()
{
    vec4 texColor = fs_in.color;
    if (fs_in.texID > 0)
    {
        texColor = fs_in.color * texture(textures[fs_in.texID - 1], fs_in.texCoord);
    }
    color = texColor;
}

然而,这段代码在纹理上给了我奇怪的文物: image

现在这里是一个奇怪的部分:

更换

texColor = fs_in.color * texture(textures[fs_in.texID - 1], fs_in.texCoord);

以下

for (int i = 0; i < 16; i++)
    if (fs_in.texID - 1 == i)
        texColor = fs_in.color * texture(textures[i], fs_in.texCoord);

解决了问题:image

此外,此问题仅出现在使用OpenGL的基于AMD的计算机上4.5.13469兼容性配置文件上下文21.19.525.258

在Surface Pro上运行原始程序非常合适。

也许我错过了一些明显的东西,但我不知道为什么会出现这个问题,或者为什么更改会修复它。解释赞赏。

〜石头

1 个答案:

答案 0 :(得分:3)

#version 330 core

在GLSL 3.30中,constant expressions只能访问 的采样器数组。你的着色器不应该编译。

但是,让我们假装您的硬件比GLSL 3.30支持更多。在这种情况下:

textures[fs_in.texID - 1]

在GLSL 4.00+中,dynamically uniform expressions只能访问 的采样器数组。除非您只渲染一个三角形,或者每个三角形都具有相同的fs_in.texID值,否则该表达式动态均匀。而且我猜不是,因为你没有使用uniform

如果使用不是动态统一的表达式索引不透明类型的数组,则会得到未定义的行为。

  

以下

for (int i = 0; i < 16; i++)
    if (fs_in.texID - 1 == i)
        texColor = fs_in.color * texture(textures[i], fs_in.texCoord);

即使这会调用未定义的行为。虽然表达式i本身可以是动态统一的,因为该语句只是有条件地执行,但该条件并不保证所使用的i的值对于调用组中的所有调用都是相同的。

所以它仍然没有动态统一。它只是未定义的行为,恰好恰好工作。不保证它可以用于其他任何事情。

你无法逃避规则;您无法在渲染命令的中间切换要使用的纹理。如果这是你真正想要的,那么你不需要一系列纹理;你想要一个数组纹理:

uniform sampler2DArray textures;

void main()
{
    vec4 texColor = fs_in.color;
    if (fs_in.texID > 0)
    {
        texColor = fs_in.color * texture(textures, vec3(fs_in.texCoord, fs_in.texID - 1));
    }
    color = texColor;
}

或者,只需删除条件,使纹理的第0层仅包含1,并始终从纹理中获取(因为有条件地执行may require you to manually provide derivatives):

uniform sampler2DArray textures;

void main()
{
    color = fs_in.color * texture(textures, vec3(fs_in.texCoord, fs_in.texID));
}