问题描述
当使用OpenGL 4.5计算着色器时,按照以下方式从基于变量的不同纹理进行采样会导致奇数像素化。 (第一个纹理是红色,第二个纹理是蓝色)
#version 450
uniform sampler2D textures[2];
layout (binding = 0,rgba32f) uniform image2D framebuffer;
layout (local_size_x = 32,local_size_y = 32) in;
void main() {
ivec2 pix = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(framebuffer);
if (pix.x >= size.x || pix.y >= size.y) {
return;
}
vec2 tex_coords = vec2(pix)/size;
int index;
vec4 col;
if (tex_coords.x > tex_coords.y) {
index = 0;
} else {
index = 1;
}
/* This works */
// for (int i=0; i<=index; i++)
// if (i==index)
// col = textureLod(textures[index],vec2(0,0),0);
/* These don't */
col = textureLod(textures[index],0);
// col = texelFetch(textures[index],ivec2(0,0);
imageStore(framebuffer,pix,col);
}
奇怪的是,使用while循环抵消不同纹理的样本发生时的偏移量似乎可以解决此问题。使用大小为1的工作组似乎也可以解决该问题。任何人都知道为什么会发生这种行为和/或没有那么简单的方法来阻止它吗?
有关代码的完整MRE,请访问https://github.com/Luminic/TextureSamplingIssues
解决方法
您得到的结果完全符合规范。 GLSL规范指出:
纹理组合的采样器类型是不透明的类型,声明和行为如上所述。 不透明的类型。 在着色器中聚合到数组中时,只能用 动态统一整数表达式,否则结果不确定。
您实际上无法做到这一点,并且循环的解决方法仍然是未定义的行为(尽管按照当前GPU的工作方式更可能起作用)。正确的解决方法是:
vec4 texSamples[2];
texSamples[0]=texture(textures[0],...);
texSamples[1]=texture(textures[1],...);
col = texSamples[index];
但是,您也许可以使用阵列纹理,您可以在其中通过任意非均匀表达式选择图层。