目前我正在尝试使用OpenGL中的imageStore写入图像。但是,使用 renderdock 作为我的调试器,我在运行程序后只发现黑色纹理。
我创建并绑定要写入的图像,如下所示:
glGenTextures(1, &textureID);
glBindTexture(target, textureID);
glObjectLabel(GL_TEXTURE, textureID, -1, ""3D Texture"");
glTexStorage3D(target, 1, GL_RGBA8, width, height, depth);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
然后我通过以下方式将纹理加载到程序中:
glBindImageTexture(0, textureID, 0, GL_TRUE, 0, GL_READ_WRITE, GL_RGBA8);
GLuint location = glGetUniformLocation(programID, uniform);
glUniform1i(location,0);
最后,我通过调用glDrawArrays((来渲染。
我的片段着色器如下所示:
#version 440
out vec3 f_pos;
out vec3 f_norm;
out vec2 f_uv;
layout(RGBA8) uniform image3D volumeMap;
void main()
{
imageStore(volumeMap, ivec3(0,0,0),
vec4(0,1,1,0));
}
所以我的期望是在第一层的左上角找到一个青色像素。但是,该像素是黑色的。
我已经使用 texture(( 调用成功加载并从采样器读取。
我不确定我是否错过了步骤,或者我做事的方式是否错误。
编辑:
我修改了我的代码,不依赖 RenderDoc 来检查颜色。
所以我渲染如下
最终片段着色器:
#version 440
out vec4 fragment_color;
layout(binding=3, RGBA8) uniform image3D vMap;
void main()
{
fragment_color = imageLoad(vMap, ivec3(0,0,0));
}
C++
glUseProgram(Program1);
/*load texture as above*/
draw();
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glUseProgram(Program2);
/*load texture as above*/
draw();
draw 只需设置几何缓冲区,然后调用 glDrawArrays((。
结果是一个黑色网格,我期望一个青色网格
图像加载/存储操作在不连贯的内存访问规则下运行。这意味着对它们的写入对以后的读取不可见,除非您显式执行某些操作以使它们可见。通常,这是对glMemoryBarrier
的调用。
永远记住,glMemoryBarrier
指定您打算如何访问写入的值,而不是您如何写入它。在这种情况下,无论哪种方式,机制都是相同的:GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
。此命令必须放在写入数据的命令之后,以及读取数据的命令之前。
另外,我不能说这个着色器是否有未定义的行为。您有多个调用,这些调用都写入同一内存位置。但在您的情况下,它们正在写入相同的值。从规范中的描述中不清楚这是真正的UB,还是没问题。如果调用写入不同的数据,那肯定是 UB,但我不知道它们写入相同数据是否存在一些例外。
但是,我会非常犹豫是否这样做。