如何使用具有 3D 纹理的图像存储?
How do I use image store with 3D textures?
我正在尝试将数据存储到 3D 纹理中,但它似乎不起作用。我这样设置纹理:
glGenTextures(1, &voxelTexture);
glBindTexture(GL_TEXTURE_3D, voxelTexture);
unsigned char clearData[VoxelSize* VoxelSize* VoxelSize];
memset(clearData, 5, sizeof(clearData));
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, VoxelSize, VoxelSize, VoxelSize, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, clearData);
稍后,我写到纹理:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, VoxelSize, VoxelSize);
glUseProgram(voxelProg);
glBindTexture(GL_TEXTURE_3D, voxelTexture);
glBindImageTexture(0, voxelTexture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R8UI);
for(const auto & i : models){
glUniformMatrix4fv(glGetUniformLocation(voxelProg, "M"), 1, GL_FALSE, glm::value_ptr(i->getModelMatrix()));
glBindVertexArray(i->getMesh()->vao);
glDrawElements(GL_TRIANGLES, i->getMesh()->nbVertices, GL_UNSIGNED_INT, 0);
}
我知道绘制操作工作正常,因为我在程序的另一部分中将它与阴影贴图一起使用。
最后,我尝试从纹理中读取数据:
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
static char data[VoxelSize * VoxelSize *VoxelSize] = {0};
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, data);
for(auto & i : data){
if(i!=5)
std::cout << (int)i << " ";
}
endl(std::cout);
如您所见,如果数据被修改,那么它将打印到 cout
。我将数据设置为 5,以便您可以看到 glGetTexImage
实际上读取了纹理数据(否则它将全为零)。
我使用的程序将其作为顶点缓冲区:
#version 430
layout(location = 0) in vec3 position;
uniform mat4 M;
void main(){
gl_Position = M* vec4(position, 1.0);
}
这是片段缓冲区:
#version 430
layout(binding = 0, r8ui)writeonly restrict uniform uimage3D dataTexture;
void main(){
imageStore(dataTexture, ivec3(6,6,6), uvec4(30));
}
我使用了任意位置进行写入,而不是受片段本身影响的位置,这样我至少可以放心,如果任何片段通过它都会影响纹理。但是,似乎没有任何效果。我试过更改 imageStore
写入的位置,我试过以各种方式在顶点缓冲区中缩放 gl_Position
。任何帮助将不胜感激。
编辑:
按照可能重复的解决方案将分层设置从false
更改为true
后,仍然无效。
glUseProgram(voxelProg)
和 glGetUniformLocation(mainProg, "M")
引用不同的着色器程序。因此,矩阵 M
未设置,顶点形成退化三角形并且没有片段被光栅化,因此 imageStore
从未真正被调用。
另外 glBindImageTexture
将 3D 纹理作为 "layered" 2D 纹理处理,因此分层参数必须是 GL_TRUE
。参见 this。
[EDIT] 在这种情况下,M
由于其他原因也没有正确投影几何体(参见评论)。要更改 M
以便将网格缩放并转换为 -1 到 1 的立方体以匹配 3D 图像,请参阅:How to normalize a mesh into -1 to 1, then revert from normalized mesh to original one?
我正在尝试将数据存储到 3D 纹理中,但它似乎不起作用。我这样设置纹理:
glGenTextures(1, &voxelTexture);
glBindTexture(GL_TEXTURE_3D, voxelTexture);
unsigned char clearData[VoxelSize* VoxelSize* VoxelSize];
memset(clearData, 5, sizeof(clearData));
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
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);
glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, VoxelSize, VoxelSize, VoxelSize, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, clearData);
稍后,我写到纹理:
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, VoxelSize, VoxelSize);
glUseProgram(voxelProg);
glBindTexture(GL_TEXTURE_3D, voxelTexture);
glBindImageTexture(0, voxelTexture, 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_R8UI);
for(const auto & i : models){
glUniformMatrix4fv(glGetUniformLocation(voxelProg, "M"), 1, GL_FALSE, glm::value_ptr(i->getModelMatrix()));
glBindVertexArray(i->getMesh()->vao);
glDrawElements(GL_TRIANGLES, i->getMesh()->nbVertices, GL_UNSIGNED_INT, 0);
}
我知道绘制操作工作正常,因为我在程序的另一部分中将它与阴影贴图一起使用。
最后,我尝试从纹理中读取数据:
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
static char data[VoxelSize * VoxelSize *VoxelSize] = {0};
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, data);
for(auto & i : data){
if(i!=5)
std::cout << (int)i << " ";
}
endl(std::cout);
如您所见,如果数据被修改,那么它将打印到 cout
。我将数据设置为 5,以便您可以看到 glGetTexImage
实际上读取了纹理数据(否则它将全为零)。
我使用的程序将其作为顶点缓冲区:
#version 430
layout(location = 0) in vec3 position;
uniform mat4 M;
void main(){
gl_Position = M* vec4(position, 1.0);
}
这是片段缓冲区:
#version 430
layout(binding = 0, r8ui)writeonly restrict uniform uimage3D dataTexture;
void main(){
imageStore(dataTexture, ivec3(6,6,6), uvec4(30));
}
我使用了任意位置进行写入,而不是受片段本身影响的位置,这样我至少可以放心,如果任何片段通过它都会影响纹理。但是,似乎没有任何效果。我试过更改 imageStore
写入的位置,我试过以各种方式在顶点缓冲区中缩放 gl_Position
。任何帮助将不胜感激。
编辑:
按照可能重复的解决方案将分层设置从false
更改为true
后,仍然无效。
glUseProgram(voxelProg)
和 glGetUniformLocation(mainProg, "M")
引用不同的着色器程序。因此,矩阵 M
未设置,顶点形成退化三角形并且没有片段被光栅化,因此 imageStore
从未真正被调用。
另外 glBindImageTexture
将 3D 纹理作为 "layered" 2D 纹理处理,因此分层参数必须是 GL_TRUE
。参见 this。
[EDIT] 在这种情况下,M
由于其他原因也没有正确投影几何体(参见评论)。要更改 M
以便将网格缩放并转换为 -1 到 1 的立方体以匹配 3D 图像,请参阅:How to normalize a mesh into -1 to 1, then revert from normalized mesh to original one?