正在读取imageStore()之后的texel
Reading texels after imageStore()
我正在用imageStore()修改纹理的texel,之后我用texture()将其他着色器中的这些texel读取为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);
我制作了这个简单的应用程序来测试这一点,因为真实的应用程序非常复杂,我首先用红色清除纹理,但纹素不会显示为蓝色(除了在第二个frag.shader中使用imageLoad)。
哦,那很容易。Image Load/Store的写入使用了非相干内存模型,而不是OpenGL其他大部分使用的同步模型。因此,仅仅因为你用图像加载/存储写了一些东西,并不意味着它对其他人可见。你必须明确地使其可见以供阅读。
在写入数据的渲染操作和读取数据的操作之间需要一个glMemoryBarrier
调用。由于读取操作是纹理提取,因此要使用的正确屏障是GL_TEXTURE_FETCH_BARRIER_BIT
。
仅供参考:您的imageLoad
之所以能够读取写入的数据,是因为纯粹的运气。没有任何东西可以保证它能够读取写入的数据。为了确保这样的读取,您还需要一个内存屏障。虽然明显不同:GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
。
此外,texture
采用归一化纹理坐标。imageStore
取整数像素坐标。除非该纹理是矩形纹理(由于使用了sampler2D
,所以它不是矩形纹理),否则不可能将完全相同的坐标传递给imageStore
和texture
。
因此,要么像素被写入错误的位置,要么纹理被从错误的位置采样。无论哪种方式,都存在明显的沟通错误。假设vs_uv_out
真的是非标准化的,那么你应该使用texelFetch
或者标准化它。幸运的是,你使用的是OpenGL 4.5,所以这应该很简单:
ivec2 size = textureSize(tex);
vec2 texCoord = vs_uv_out / size;
out_color = texture(tex, texCoord);
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 在类定义之后定义一个私有方法
- 在循环C++中指定字符串之后,不会打印该字符串
- C++宏忽略之后的内容
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- strncpy之后的char数组的错误行为
- 计算十进制 c++ 之后的数字
- "x += x--"之后的 x 是什么?
- 类的前向声明之后的类成员函数定义,在类声明之前
- 为什么将双精度转换为 int 似乎在第 16 位数字之后将其四舍五入?
- execlp() 在 fork() 之后无法正常工作
- 我认为我的代码很好,但它在 cin a 之后停止并且没有进一步?
- 如何在MISRA C++之后实施CRTP
- 在 OpenCV 的 namedWindow 之前或之后初始化 Tesseract
- 检测到堆损坏:在正常块 c++ 动态 2D 数组之后
- C++ 如果在 if 为 true 之后运行,为什么还会这样做
- 在 fork() 之后,我在我的程序中不断得到相同的 pid
- OpenSSL C API:如何在程序exec()之后恢复TLS连接?
- 了解在返回值之前和之后使用 EAX 的函数调用
- 正在读取imageStore()之后的texel