作为一个实验/玩具项目,我正在使用OpenGL 4.3计算着色器重新实现它,但整个过程都遇到了麻烦本地/全局调用ID事物。
基本思想是使用计算着色器计算图像并将其输出为纹理,然后使用简单程序将其复制到帧缓冲区。
这是我正在使用的计算着色器:
#version 430 core
layout (binding = 0, rgba32f) writeonly uniform image2D output_image;
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main()
{
ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
imageStore(output_image, coord, vec4(0.0, 0.0, 1.0, 1.0));
}
这是初始化纹理的方式:
GLuint offscreen_texture;
glGenTextures(1, &offscreen_texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, offscreen_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGBA, GL_FLOAT, nullptr);
glBindImageTexture(0, offscreen_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
这些是我使用的普通顶点着色器:
#version 430 core
void main()
{
const vec4 verts[4] = vec4[4](vec4(-1.0, -1.0, 0.5, 1.0),
vec4( 1.0, -1.0, 0.5, 1.0),
vec4(-1.0, 1.0, 0.5, 1.0),
vec4( 1.0, 1.0, 0.5, 1.0));
gl_Position = verts[gl_VertexID];
}
和片段:
#version 430 core
layout (location = 0) out vec4 color_out;
layout(binding = 0) uniform sampler2D source_image;
void main()
{
color_out = texture(source_image, gl_FragCoord.xy);
}
这是渲染代码:
compute_program.use();
glDispatchCompute(WINDOW_WIDTH / 16, WINDOW_HEIGHT / 16, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
copy_program.use();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
至此,一切正常,我看到我的屏幕完全是蓝色,而不是通常的清晰颜色。 >
当我尝试使用调用ID生成实际数据(如来自相机的光线)时,事情开始崩溃。 br />我尝试切换到计算着色器,例如:
#version 430 core
layout (binding = 0, rgba32f) writeonly uniform image2D output_image;
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main()
{
ivec2 coord = ivec2(gl_GlobalInvocationID.xy);
imageStore(output_image, coord, vec4(0.0, 0.0, coord.x / 1280.0, 1.0));
}
,它使用全局ID生成像素的蓝色。
从OpenGL Suberbible书和OpenGL Wiki上了解,我应该能够将全局ID用作屏幕空间坐标(很容易使用本地ID和工作组ID进行数学运算并确认),就像gl_FragCoord一样,以前的琐碎计算着色器已证实了这一点,该着色器会绘制每个像素。
此计算着色器的输出是一种从黑色到蓝色的水平渐变,但一切都会变成黑色。
我尝试了基于线程的本地/全局ID的“绘画”的几种组合,但是无论如何我都没有运气。
我是否误解了整个过程线程ID是否起作用?
使用它们/将它们映射到屏幕空间坐标(例如gl_FragCoord)的正确方法是什么?
编辑:只是要补充一点,我已经使用集成的Intel HD 5100和离散的Nvidia 765M GPU进行了测试,结果是相同的,所以我这边显然有问题。
#1 楼
问题实际上出在您的片段着色器中:color_out = texture(source_image, gl_FragCoord.xy);
texture()函数接受范围为0.0到1.0的归一化坐标。内置的gl_FragCoord包含范围从(0.0,0.0)到(窗口宽度,窗口高度)的窗口坐标。
要解决此问题,请将片段着色器更改为此:
color_out = texture(source_image, gl_FragCoord.xy / vec2(1280.0, 720.0));
假设您的窗口是1280x720,请根据需要进行更改。
评论
$ \ begingroup $
哇,我现在想死:(我什至说我希望gl_GlobalInvocationID的行为类似于gl_FragCoord,它使用窗口坐标。这是有史以来最愚蠢的错误之一。
$ \ endgroup $
–马特奥·贝特洛(Matteo Bertello)
2015年10月20日在21:56