2017-07-24 60 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增加到最終值,以便實時查看顏色變化。