计算着色器未修改3D纹理

10

我想将我3D纹理的初始化从CPU移到GPU。作为测试,我编写了一个着色器将所有体素设置为常量值,但纹理没有被修改。我该如何让它起作用?

计算着色器:

#version 430

layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
layout(r8, location = 0) uniform image3D volume;

void main()
{
  imageStore(volume, ivec3(gl_WorkGroupID), vec4(0));
}

调用:

glEnable(GL_TEXTURE_3D);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &volume_tid);
glBindTexture(GL_TEXTURE_3D, volume_tid);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, volume_dims[0], volume_dims[1], volume_dims[2], 0, GL_RED, GL_UNSIGNED_BYTE, voxels);

ShaderProgram computeVolumeShader;
computeVolumeShader.loadShader(GL_COMPUTE_SHADER, "compute_volume.glsl");
computeVolumeShader.link();
computeVolumeShader.use();
computeVolumeShader.uniform("volume", 0);
glBindImageTexture(0, volume_tid, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R8);
glDispatchCompute(volume_dims[0], volume_dims[1], volume_dims[2]);
glBindImageTexture(0, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R8);
computeVolumeShader.unUse();
glMemoryBarrier(GL_ALL_BARRIER_BITS);
注意:glTexImage3D 函数输入的voxels 包含CPU初始化数据。

你尝试过使用真实的图像格式而不是 GL_RED 吗? - Nicol Bolas
@Nicol 当我使用GL_R8UI时,即使没有使用计算着色器,我也看不到任何东西了。 我使用sampler3D进行渲染,这有什么区别吗?由于在此处表1中列出了GL_RED,我认为可以使用它,你是在说internalFormat参数对吧? - Andreas Haferburg
但是你不知道GL_RED实际上代表什么。它可能会给你GL_R8,也可能会给你GL_R16。当你不选择特定格式时,你放弃了选择格式的权利。当你使用GL_R8UI时,它停止工作,因为你可能没有将像素传输设置为上传整数数据而不是标准化浮点数 - Nicol Bolas
@Nicol 谢谢你的解释。我已经将它更改为无符号归一化整数(在问题中更新了代码),因为我喜欢在其他着色器中使用浮点数。不幸的是,它仍然不起作用。 - Andreas Haferburg
1个回答

23

糟糕。显然,3D纹理必须绑定为层级纹理,否则着色器无法修改任何带有 w>0 的 uvw 坐标。

glBindImageTexture(0, volume_tid, 0, /*layered=*/GL_TRUE, 0, GL_READ_WRITE, GL_R8);

有用的。


2
我为此浪费了半天时间。谢谢!!!我觉得我永远也不会想出来。 - Timothy Wright
1
刚刚也经历了一次疯狂的旅程。这个问题非常令人困惑,因为它在 Nvidia GM107 上运行正常,但在 GK110b 上却不行(两者都是最新驱动)。 :-/ - FHoenig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接