从 OpenGL 计算着色器中的不同采样器读取会导致奇怪的像素化
Reading from different samplers in an OpenGL Compute Shader results in odd pixelation
使用 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], vec2(0,0), 0);
// col = texelFetch(textures[index], ivec2(0,0), 0);
imageStore(framebuffer, pix, col);
}
奇怪的是,当不同纹理的样本发生时使用 while 循环进行偏移似乎可以解决问题。使用大小为 1 的工作组似乎也可以解决此问题。任何人都知道为什么会发生这种行为 and/or 有更简单的预防方法吗?
代码的完整 MRE 可以在 https://github.com/Luminic/TextureSamplingIssues
找到
您得到的结果完全符合规范。 GLSL 规范指出:
Texture-combined sampler types are opaque types, declared and behaving as described above for
opaque types. When aggregated into arrays within a shader, they can only be indexed with a
dynamically uniform integral expression, otherwise results are undefined.
你不能真的那样做,循环的解决方法仍然是未定义的行为(尽管它更有可能按照当前 GPU 的工作方式工作)。正确的解决方法是:
vec4 texSamples[2];
texSamples[0]=texture(textures[0],...);
texSamples[1]=texture(textures[1],...);
col = texSamples[index];
但是,您可以使用 阵列纹理 ,您可以通过任意 non-uniform 表达式 select 图层。
使用 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], vec2(0,0), 0);
// col = texelFetch(textures[index], ivec2(0,0), 0);
imageStore(framebuffer, pix, col);
}
奇怪的是,当不同纹理的样本发生时使用 while 循环进行偏移似乎可以解决问题。使用大小为 1 的工作组似乎也可以解决此问题。任何人都知道为什么会发生这种行为 and/or 有更简单的预防方法吗?
代码的完整 MRE 可以在 https://github.com/Luminic/TextureSamplingIssues
找到您得到的结果完全符合规范。 GLSL 规范指出:
Texture-combined sampler types are opaque types, declared and behaving as described above for opaque types. When aggregated into arrays within a shader, they can only be indexed with a dynamically uniform integral expression, otherwise results are undefined.
你不能真的那样做,循环的解决方法仍然是未定义的行为(尽管它更有可能按照当前 GPU 的工作方式工作)。正确的解决方法是:
vec4 texSamples[2];
texSamples[0]=texture(textures[0],...);
texSamples[1]=texture(textures[1],...);
col = texSamples[index];
但是,您可以使用 阵列纹理 ,您可以通过任意 non-uniform 表达式 select 图层。