imageStore()遇到问题(OpenGL 4.3) [英] Trouble with imageStore() (OpenGL 4.3)

查看:389
本文介绍了imageStore()遇到问题(OpenGL 4.3)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将一些数据从计算着色器输出到纹理,但是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);
}

片段着色器中最后注释的行产生以下输出:渲染输出

顶点数组对象(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

解决方案

这是我显示纹理的方式:

那还不够好.我没有看到glMemoryBarrier 的调用,因此无法保证您的代码确实有效.

记住:通过图像加载/存储写入图像的内存不一致.他们需要显式的用户同步,然后才能显示.如果以后要使用已存储的图像作为纹理,则在写入图像的渲染命令之后但要从其采样的渲染命令之前必须进行 明确的glMemoryBarrier调用.作为纹理.

为什么这是个问题,我不知道

因为桌面OpenGL不是 OpenGL ES.

仅后三个参数 描述您提供的像素数据的布置 OpenGL.他们对OpenGL如何存储数据没有任何改变.在ES中,它们可以这样做,但这仅是因为ES不会进行格式转换.

在桌面OpenGL中,将浮点数据上传到规范化的整数纹理是完全合法的.期望OpenGL尽可能地转换数据. ES不会进行转换,因此必须更改内部格式(第三个参数)以匹配数据.

Desktop GL没有.如果您想要特定的图像格式,请提出要求.桌面GL可以为您提供所需的一切,并且仅满足您的需求.

始终使用大小合适的内部格式.

I'm trying to output some data from compute shader to a texture, but imageStore() seems to do nothing. Here's the shader:

#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));
}

and the application code is here:

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);

then a full screen quad is rendered with that texture but currently it only shows some random old data from video memory. Any idea what could be wrong?

EDIT:

This is how I display the texture:

// 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();

and the drawProgram consists of:

#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;
}

and:

#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);
}

The last commented line in fragment shader produces this output: Render output

The vertex array object (vao) has one buffer with 6 2D vertices:

-1.0, -1.0

1.0, -1.0

1.0, 1.0

1.0, 1.0

-1.0, 1.0

-1.0, -1.0

解决方案

This is how I display the texture:

That's not good enough. I don't see a call to glMemoryBarrier, so there's no guarantee that your code actually works.

Remember: writes to images via Image Load/Store are not memory coherent. They require explicit user synchronization before they become visible. If you want to use an image you have stored to as a texture later, there must be an explicit glMemoryBarrier call after the rendering command that writes to it, but before the rendering command that samples from it as a texture.

Why that is a problem, I don't know

Because desktop OpenGL is not OpenGL ES.

The last three parameters only describe the arrangement of the pixel data you're giving OpenGL. They change nothing about how OpenGL stores the data. In ES, they do, but that's only because ES doesn't do format conversions.

In desktop OpenGL, it is perfectly legal to upload floating-point data to a normalized integer texture; OpenGL is expected to convert the data as best it can. ES doesn't do conversions, so it has to change the internal format (the third parameter) to match the data.

Desktop GL does not. If you want a specific image format, you ask for it. Desktop GL gives you what you ask for, and only what you ask for.

Always use sized internal formats.

这篇关于imageStore()遇到问题(OpenGL 4.3)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆