在计算着色器中写入一个空的 3D 纹理

Writing to an empty 3D texture in a Compute Shader

我正在尝试创建一个空的 3D 纹理,其尺寸和格式在运行时加载。然后我想修改这个纹理的值,然后我用光线追踪器进行体积渲染。我知道我的渲染功能工作正常,因为我可以毫无问题地渲染尺寸和格式来自的体积。空卷也会呈现,但我无法向其中写入任何数据,因此它一直都是白色的。

//My function that creates the blank texture initially
//Its part of a larger class that reads in a populated volume and a transfer function,
//I'm just initialising it in this way so it is identical to the other volume, but empty
GLuint Texture3D::GenerateBlankTexture(VolumeDataset volume)
{
GLuint tex;

glEnable(GL_TEXTURE_3D);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_3D, tex);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


// Reverses endianness in copy
if (!volume.littleEndian)
    glPixelStoref(GL_UNPACK_SWAP_BYTES, true);

if (volume.elementType == "MET_UCHAR")
{
    //          texture format, ?, channels, dimensions,                        ?, pixel format, data type, data
    glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, volume.xRes, volume.yRes, volume.zRes, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
    glBindImageTexture(0, tex, 0, GL_TRUE, 0, GL_READ_WRITE, GL_R8);
}

else if (volume.elementType == "SHORT")
{
    glTexImage3D(GL_TEXTURE_3D, 0, GL_R16F, volume.xRes, volume.yRes, volume.zRes, 0, GL_RED, GL_UNSIGNED_SHORT, NULL);
    glBindImageTexture(0, tex, 0, GL_TRUE, 0, GL_READ_WRITE, GL_R16F);
}
else if (volume.elementType == "FLOAT")
{
    glTexImage3D(GL_TEXTURE_3D, 0, GL_R32F, volume.xRes, volume.yRes, volume.zRes, 0, GL_RED, GL_FLOAT, NULL);
    glBindImageTexture(0, tex, 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32F);
}
glPixelStoref(GL_UNPACK_SWAP_BYTES, false);

GLenum err = glGetError();

glBindTexture(GL_TEXTURE_3D, 0);

return tex;
}

创建体积后,我将其读入显示函数中的计算着色器:

glUseProgram(Compute3DShaderID);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, tex_output);

glDispatchCompute((GLuint)volume.xRes/4, (GLuint)volume.yRes/4, (GLuint)volume.zRes/4);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

在我的着色器中,我要做的就是根据它在体积中的位置更改颜色:

#version 430
layout (local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
layout (r8, binding = 0) uniform image3D tex_output;

void main()
{
    ivec3 dims = imageSize (tex_output);
    ivec3 pixel_coords = ivec3(gl_GlobalInvocationID.xyz);

    vec4 pixel = vec4(pixel_coords.x/dims.x, pixel_coords.y/dims.y, pixel_coords.y/dims.y, 1.0);


    imageStore (tex_output, pixel_coords, pixel);
}

我确定该错误与写入权限被拒绝有关,但我无法准确指出是什么原因。

注意:我正在使用 GL_RED 等,因为这是体积数据,这就是我在体积渲染器的其余部分中使用它的方式,它似乎工作正常。

所以,愚蠢的错误。原来我的着色器工作正常。我没有预料到的是,我试图写入卷的值在我的传递函数上映射为白色。一旦我拉出传递函数的原理图,并使用应该可以正常工作的值进行测试,我就得到了实际的颜色。

以后看到这个问题的任何人,如果您的代码无法正常工作,应该如下所示:

创建您的纹理,并使用 glTexImage3D 将其设置为图像纹理。然后,当你想使用它时,调用 glBindImageTexture 并绘制,确保将 layered 设置为 GL_TRUE 因为它是 3D 纹理。还要确保你绑定到正确的绑定(在我上面的代码中我绑定到 0,但我已经添加了第二个绑定到 1 的纹理)并且如果你要使用第二组纹理和着色器则取消绑定.

如果您遇到问题,请将其设置为计算中的每次迭代都会将最终值增加 0.01,这样您就可以实时看到颜色变化。