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

时间:2017-07-24 13:45:13

标签: opengl glsl volume-rendering

我正在尝试创建一个空的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等,因为这是体积数据,这就是我在我的体积渲染器的其余部分中使用它的方式,它似乎工作正常。

1 个答案:

答案 0 :(得分:1)

所以,愚蠢的错误。结果我的着色器工作正常。我没想到的是我试图写入卷的值在我的传递函数上映射为白色。一旦我拉出传递函数的原理图,并测试了应该正常工作的值,我得到了实际的颜色。

将来有人看到这个问题,如果您的代码不起作用,应该如下:

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

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