2

I'm trying to bind a 3D texture to an image unit in OpenGL. Current shader code:

#version 450 core

out vec4 OutBuffer;

in GS_OUT {
    vec3 Position;
    vec4 ScreenPosition;
    vec3 Normal;
    vec2 TexCoords;
} fs_in;

uniform uvec3 uVoxelSpan;

layout(rgba16f) coherent uniform image3D uVoxelMap;

void main() {
    imageStore(uVoxelMap, ivec3(floor(fs_in.ScreenPosition.xyz)), vec4(1.0f));
    ivec3 sz = imageSize(uVoxelMap); // This ends up being ivec3(0, 0, 0)

    OutBuffer = vec4(vec3(sz.xyz), 1.0f);
}

Currently, this shader is being used to debug this problem.

// Earlier in the program

unsigned int voxel_tex = 0;
glGenTextures(1, &voxel_tex);
glBindTexture(GL_TEXTURE_3D, voxel_tex);
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, 128, 128, 128, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA16F, 128, 128, 128, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA16F, 128, 128, 128, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexImage3D(GL_TEXTURE_3D, 3, GL_RGBA16F, 64, 64, 64, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexImage3D(GL_TEXTURE_3D, 4, GL_RGBA16F, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_3D, previous_texture);

// Somewhere in the render loop
{
    static glm::vec3 clear_vec = glm::vec3(0.0f);
    glUseProgram(voxel_shader);
    glClearTexImage(voxel_tex, 0, GL_BGR, GL_FLOAT, &clear_vec);
    
    glm::vec3 sz; // This ends up being the correct value
    glBindTexture(GL_TEXTURE_3D, voxel_tex);
    glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &sz.x);
    glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &sz.y);
    glGetTexLevelParameteriv(GL_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &sz.z);
    glBindTexture(GL_TEXTURE_3D, previous_texture);

    glBindImageTexture(2, voxel_tex, 0, GL_TRUE, NULL, GL_READ_WRITE, GL_RGBA16F);
    glUniform1i(voxelmap_location, 2);

    // ... Render meshes ...

    glUseProgram(previous_program);
}

This C++ code is a snippet of everything related to the use of the 3D texture.

Am I doing something wrong? glGetError() never returns an error, but imageSize(uVoxelMap) returns ivec3(0, 0, 0), meaning something went wrong.

William
  • 63
  • 1
  • 8
  • 1
    So what exactly is the problem? What makes you think this code does not work as it should? Your texture is not mipmap complete, so sampling from it is goaranteed to fail, as per the spec. I'd also expect that 90% of real world implementations will actually have trouble with the scheme you mis-use the mipmap levels, altough that even is allowed by the spec (and I had to look that one up). – derhass Mar 07 '21 at 16:18
  • I should have been a little bit more clear. The texture isn't binding properly. In the shader code, `imageSize(uVoxelMap)` returns `ivec3(0, 0, 0)`, meaning something has gone wrong (I don't know what exactly). As for the mipmap, I'm using a technique I came across called clipmapping. As far as I know, you have to do the mipmap levels manually for a clipmap. – William Mar 07 '21 at 16:32

1 Answers1

1
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA16F, 128, 128, 128, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexImage3D(GL_TEXTURE_3D, 1, GL_RGBA16F, 128, 128, 128, 0, GL_RGBA, GL_FLOAT, nullptr);
glTexImage3D(GL_TEXTURE_3D, 2, GL_RGBA16F, 128, 128, 128, 0, GL_RGBA, GL_FLOAT, nullptr);

You have created an incomplete texture. You created 3 different mipmap levels with the same size. This makes the texture not mipmap complete, and therefore the texture is incomplete. And if a texture bound to an image unit is incomplete, then all accesses to it from a shader are invalid.

If you want a 128x128x128 image as your base level, the next mipmap level should be 64x64x64, then 32x32x32, etc.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Although this is correct, I need to have the mipmap levels sized like they are while keeping it mipmap complete. Is there a way to have mipmap complete texture, while being sized like they currently are? – William Mar 07 '21 at 17:40
  • 1
    @William: Mipmap sizes aren't something you get to make up as you go along (despite the fact that the API appears to give you the freedom to do exactly that). If the base level is 128, the next level *must* be 64. It's not clear what exactly it is that you're trying to accomplish with such a texture, so I can't really offer a solution. – Nicol Bolas Mar 07 '21 at 17:42