2017-07-24 144 views
0

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

+1

为什么你将纹理绑定到纹理单元?您似乎在着色器中使用了“image3D”,而不是“sampler3D”。 – BDL

+0

我以为我需要,我有点不确定我在做什么,关于'image3D'和'sampler3D'之间的区别虽然它看起来没有什么区别,看到我从来没有访问它作为一个纹理单元无论如何 – irishMTS

+1

是的,但似乎你没有将它绑定到图像单元(除非你只调用一次'GenerateBlankTexture',并且不要将任何其他图像绑定到图像单元0)。 – BDL

回答

0

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

任何人在将来看到这个问题,如果你的代码不能正常工作,它应该是如下:

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

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