在计算着色器中写入空的3D纹理
问题描述:
我正在尝试创建一个空的3D纹理,其尺寸和格式在运行时加载。然后我想修改这个纹理的值,然后我用射线跟踪器进行体绘制。我知道我的渲染功能正常工作,因为我可以渲染尺寸和格式来自没有问题的卷。空卷也呈现,但我无法写入任何数据,所以它一直是白色的。在计算着色器中写入空的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
并进行绘制,确保将其设置为分层为GL_TRUE
,因为它具有3D纹理。还要确保你绑定到正确的绑定(在我上面的代码中绑定到0,但我已经添加了第二个纹理绑定到1),并解除绑定,如果你要使用第二套纹理和着色器。
如果遇到问题,请将其设置为使计算中的每次迭代都将0.01增加到最终值,以便实时查看颜色变化。
为什么你将纹理绑定到纹理单元?您似乎在着色器中使用了“image3D”,而不是“sampler3D”。 – BDL
我以为我需要,我有点不确定我在做什么,关于'image3D'和'sampler3D'之间的区别虽然它看起来没有什么区别,看到我从来没有访问它作为一个纹理单元无论如何 – irishMTS
是的,但似乎你没有将它绑定到图像单元(除非你只调用一次'GenerateBlankTexture',并且不要将任何其他图像绑定到图像单元0)。 – BDL