简体   繁体   中英

How do I use image store with 3D textures?

I am trying to store data into a 3D texture, however it doesn't seem to work. I set up the texture like this:

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);

Later, I write to the texture:

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);
}

I know the draw operation works fine because I have used it with a shadow map in another part of the program.

Finally, I try to read the data from the texture:

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);

As you can see, if the data was modified then it would print to cout . I set the data to be 5 so that you can see that glGetTexImage actually reads the texture data (because otherwise it would be all zeroes).

The program that I use has this as the vertex buffer:

#version 430

layout(location = 0) in vec3 position;

uniform mat4 M;

void main(){
    gl_Position = M* vec4(position, 1.0);
}

And this as the fragment buffer:

#version 430

layout(binding = 0, r8ui)writeonly restrict uniform uimage3D dataTexture;
void main(){
    imageStore(dataTexture, ivec3(6,6,6), uvec4(30));
}

I used an arbitrary location to write to rather than one that is affected by the fragment itself so that I could at least be assured that if any fragment got passed through it would affect the texture. However, nothing seems to work. I've tried changing where the imageStore writes to, I've tried scaling gl_Position in the vertex buffer in various ways. Any help would be appreciated.

Edit:

After following the possible duplicates solution of changing the layered setting from false to true , it still doesn't work.

glUseProgram(voxelProg) and glGetUniformLocation(mainProg, "M") reference different shader programs. Consequently, the matrix M isn't set, the vertices form degenerate triangles and no fragments are rasterized so imageStore never actually gets called.

Also glBindImageTexture handles 3D textures as "layered" 2D textures, so the layered argument must be GL_TRUE . see this .

[ EDIT ] In this case, M is not projecting the geometry correctly for other reasons too (see the comments). To change M so that it scales and translates the mesh into a -1 to 1 cube to match the 3D image, see: How to normalize a mesh into -1 to 1, then revert from normalized mesh to original one?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM