我试图将一些数据从计算着色器输出到纹理,但是imageStore()似乎什么都不做。这是着色器:
#version 430
layout(RGBA32F) uniform image2D image;
layout (local_size_x = 1, local_size_y = 1) in;
void main() {
imageStore(image, ivec2(gl_GlobalInvocationID.xy), vec4(0.0f, 1.0f, 1.0f, 1.0f));
}
,应用程序代码在这里:
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_FLOAT, 0);
glBindImageTexture(0, tex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
glUseProgram(program->GetName());
glUniform1i(program->GetUniformLocation("image"), 0);
glDispatchCompute(WIDTH, HEIGHT, 1);
然后使用该纹理渲染全屏四边形,但目前它只显示来自视频内存的一些随机旧数据。知道什么可能是错的吗?
编辑:
这是我显示纹理的方式:
// This comes right after the previous block of code
glUseProgram(drawProgram->GetName());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(drawProgram->GetUniformLocation("sampler"), 0);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers();
并且drawProgram包含:
#version 430
#extension GL_ARB_explicit_attrib_location : require
layout(location = 0) in vec2 position;
out vec2 uvCoord;
void main() {
gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);
uvCoord = position;
}
和
#version 430
in vec2 uvCoord;
out vec4 color;
uniform sampler2D sampler;
void main() {
vec2 uv = (uvCoord + vec2(1.0f)) / 2.0f;
uv.y = 1.0f - uv.y;
color = texture(sampler, uv);
//color = vec4(uv.x, uv.y, 0.0f, 1.0f);
}
片段着色器中的最后一个注释行产生此输出:Render output
顶点数组对象(vao)有一个带有6个2D顶点的缓冲区:
-1.0,-1.0
1.0,-1.0
1.0,1.0
1.0,1.0
-1.0,1.0
-1.0,-1.0
答案 0 :(得分:6)
这是我显示纹理的方式:
这还不够好。我没有看到call to glMemoryBarrier
,因此无法保证您的代码确实有效。
请记住:通过Image Load/Store写入图像并不是内存连贯的。他们require explicit user synchronization before they become visible。如果您想将以后存储的图像用作纹理,那么必须在写入它的渲染命令之后,但在渲染命令之前进行显式glMemoryBarrier
调用从它作为一种纹理。
为什么这是一个问题,我不知道
因为桌面OpenGL 不是 OpenGL ES。
最后三个参数仅描述了您提供OpenGL的arrangement of the pixel data。他们改变没有关于OpenGL如何存储数据。在ES中,他们这样做,但这只是因为ES不进行格式转换。
在桌面OpenGL中,将浮点数据上传到规范化的整数纹理是完全合法的。预计OpenGL会尽可能地转换数据。 ES不进行转换,因此必须更改内部格式(第三个参数)以匹配数据。
桌面GL没有。如果你想要一个特定的image format,你会要求它。 Desktop GL为您提供您所要求的内容,以及您所要求的内容。
始终使用大小的内部格式。
答案 1 :(得分:3)
GL_RGBA不是一个大小的内部格式,所以你无法知道它是真的。大多数情况下,它被OpenGL转换为GL_RGBA8。
在您的情况下,您设置的GL_FLOAT参数仅描述 在纹理中上传的像素数据。
阅读表格here以了解您可以设置为内部纹理格式的内容。
答案 2 :(得分:2)
好的,我找到了解决方案。问题出在这里:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, WIDTH, HEIGHT, 0, GL_RGBA, GL_FLOAT, 0);
此行未指定内部格式(GL_RGBA)的大小。当我提供GL_RGBA32F时,它开始工作。为什么这是一个问题,我不知道(希望有人能够解释)。