在imageStore()之后读取纹素

时间:2016-07-21 19:07:27

标签: c++ opengl glsl

我正在使用imageStore()修改纹理的纹素,之后我将其他着色器中的那些纹素作为sampler2D读取纹理()但是我得到了在imageStore()之前存储在纹理中的值。使用imageLoad()它工作正常,但我需要使用过滤和texture()的性能更好,所以有没有办法用texture()获取修改后的数据?

修改

第一个片段着色器(用于写入):

#version 450 core

layout (binding = 0, rgba32f) uniform image2D img;

in vec2 vs_uv_out;

void main()
{
    imageStore(img, ivec2(vs_uv_out), vec4(0.0f, 0.0f, 1.0f, 1.0f));
}

第二个片段着色器(用于阅读):

#version 450 core

layout (binding = 0) uniform sampler2D tex;

in vec2 vs_uv_out;

out vec4 out_color;

void main()
{
    out_color = texture(tex, vs_uv_out);
}

这就是我如何运行着色器:

glUseProgram(shader_programs[0]);
glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, 
                   GL_RGBA32F);

glDrawArrays(GL_TRIANGLES, 0, 6);

glUseProgram(shader_programs[1]);
glBindTextureUnit(0, texture);

glDrawArrays(GL_TRIANGLES, 0, 6);

我做了这个简单的应用程序来测试,因为真正的应用程序非常复杂,我首先用红色清除纹理但是纹素不会显示为蓝色(除了在第二个碎片中使用imageLoad。着色器)。

1 个答案:

答案 0 :(得分:1)

哦,那很简单。 Image Load/Store's写入使用incoherent memory model,而不是OpenGL其余大多数使用的同步模型。因此,仅仅因为您使用Image Load / Store编写内容并不意味着其他任何人都可以看到它。你必须明确地让它可供阅读。

在写入数据的呈现操作和读取数据的操作之间需要glMemoryBarrier call。由于读取操作是纹理提取,因此使用的正确障碍是GL_TEXTURE_FETCH_BARRIER_BIT

和我们的imageLoad只能由于纯粹的运气而能够阅读书面数据。没有任何保证它能够读取书面数据。为了确保这样的读取,您还需要一个内存屏障。虽然显然是另一个:GL_SHADER_IMAGE_ACCESS_BARRIER_BIT

此外,texture采用标准化纹理坐标。 imageStore采用整数像素坐标。除非该纹理是矩形纹理(并且它不是,因为您使用了sampler2D),否则无法将完全相同的坐标传递给imageStoretexture。< / p>

因此,要么将像素写入错误的位置,要么错误的位置对纹理进行采样。无论哪种方式,都存在明显的错误传达。假设vs_uv_out确实是非规范化的,那么您应该使用texelFetch,或者应该将其标准化。幸运的是,您正在使用OpenGL 4.5,因此应该非常简单:

ivec2 size = textureSize(tex);
vec2 texCoord = vs_uv_out / size;
out_color = texture(tex, texCoord);