1

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

4

1 回答 1

2

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

以后看到这个问题的人,如果你的代码不起作用,应该如下:

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

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

于 2017-07-25T15:35:02.163 回答