0
\$\begingroup\$

I'm writing a texture viewer application which up until now supported 2D as well as 2D array textures. Recently I wanted to add support for some volumetric 3D textures that I stumbled upon but I am struggling to render them properly in my app.

So the memory layout of the volumetric textures in the file is as follows:

Assuming a texture of size 128x128x128 (DXT5):

At first there is a 2097152 byte region containing the level 0 mipmaps of the 128x128x128 volume texture Next comes a region of 262144 bytes that contains the 2nd mipmap layer data of the 64x64x64 texture. And so on and so forth.

The format is identical with the 2d array textures that I support. Data is organized per mipmap layer.

I'm using OpenGL and the way that I pass each mipmap layer to the GPU is as follows:

//Temp Variables
int w = 128;
int h = 128;
int d = 128;
int mm_count = 8;
int block_size = 16;
int face_count = 16; //This contains the array size when a 2D array is detected.
//In case of volumetric textures face_count = 1

//Calculate size of the top layer
int temp_size = w * h * d * block_size / 16;

TextureTarget gl_target = TextureTargetMap[tex_data.target]; //This fetches Texture3D
InternalFormat gl_pif = InternalFormatMap[tex_data.pif]; //This fetches the correct compression format
GL.BindTexture(gl_target, tex_id);

        

int offset = 0;
for (int i = 0; i < mm_count; i++)
    {
         byte[] temp_data = new byte[temp_size];
         //This copies from the original data to the temporary array
         System.Buffer.BlockCopy(tex_data.Data, offset, temp_data, 0, temp_size);
                
         switch (gl_target)
            {
               case TextureTarget.Texture3D:
                    GL.CompressedTexImage3D(gl_target, i, gl_pif, w, h, d, 0, temp_size, temp_data);
                    break;
                case TextureTarget.Texture2DArray:
                    GL.CompressedTexImage3D(gl_target, i, gl_pif, w, h, face_count, 0, temp_size, temp_data);
                    break;
                
            }
                
            offset += temp_size;

            w = System.Math.Max(w >> 1, 1);
            h = System.Math.Max(h >> 1, 1);
            d = System.Math.Max(d >> 1, 1);

            temp_size = d * System.Math.Max(1, (w + 3) / 4) * 
                            System.Math.Max(1, (h + 3) / 4) * block_size;
    }

In the case of the volumetric texture this code ends up making 8 calls to GL.CompressedTexImage3D, as follows

GL.CompressedTexImage3D(gl_target, 0, gl_pif, 128, 128, 128, 0, 2097152, mip0data);
GL.CompressedTexImage3D(gl_target, 1, gl_pif, 64, 64, 64, 0, 262144, mip1data);
GL.CompressedTexImage3D(gl_target, 2, gl_pif, 32, 32, 32, 0, 32768, mip2data);
GL.CompressedTexImage3D(gl_target, 3, gl_pif, 16, 16, 16, 0, 4096, mip3data);
GL.CompressedTexImage3D(gl_target, 4, gl_pif, 8, 8, 8, 0, 512, mip4data);
GL.CompressedTexImage3D(gl_target, 5, gl_pif, 4, 4, 4, 0, 64, mip5data);
GL.CompressedTexImage3D(gl_target, 6, gl_pif, 2, 2, 2, 0, 32, mip6data);
GL.CompressedTexImage3D(gl_target, 7, gl_pif, 1, 1, 1, 0, 16, mip7data);

The total amount of data uploaded matches perfectly the file size.

In my shaders I sample the texture using

color = textureLod(InTex, vec3(x, y, z), lvl);

The sampler in the shader is defined as

uniform Sampler3D InTex;

For now I'm not expecting it to work with normalized values of z, I have fixed the depth value to 0.0 and I expect to have the first slice of the volumetric texture rendered on my quad, but this doesn't seem the case... Instead I get gibberish data. It seems this layout of the data is not correct with 3D Textures, but honestly I'm not sure what is wrong. Maybe I am not supposed to upload the texture data like that using 3D textures?

\$\endgroup\$

0

You must log in to answer this question.

Browse other questions tagged .