copengl-esglsltextures

How to efficiently upload transposed data to GL_TEXTURE_2D_ARRAY


I want to use a GL_TEXTURE_2D_ARRAY to hold a texture in OpenGL ES 3.0. I'm reading the OpenGL wiki for Array Textures and it has an example for data that is ordered by all pixels of the first image, then all pixels of the second image.

GLubyte texels[32] = 
{
     // Texels for first image.
     0,   0,   0,   255,
     255, 0,   0,   255,
     0,   255, 0,   255,
     0,   0,   255, 255,
     // Texels for second image.
     255, 255, 255, 255,
     255, 255,   0, 255,
     0,   255, 255, 255,
     255, 0,   255, 255,
};

However, my data is ordered by 1st pixel of the first image, 1st pixel of the second image, 2nd pixel of the first image, 2nd pixel of the second image, etc. If we were using the same images as above, the data would look like:

GLubyte texels[32] = 
{
     0,   0,   0,   255, // 1st pixel of first image
     255, 255, 255, 255, // 1st pixel of second image
     255, 0,   0,   255, // 2nd pixel of first image
     255, 255,   0, 255, // 2nd pixel of second image
     0,   255, 0,   255, // 3rd pixel of first image
     0,   255, 255, 255, // 3rd pixel of second image
     0,   0,   255, 255, // 4th pixel of first image
     255, 0,   255, 255, // 4th pixel of second image    
};

The default has the data arranged in data[image_num][width][height], but my data is data[width][height][image_num]. Because the data is large and is being streamed, I would prefer to not have to reorder the data on CPU.

I tried to upload each image separately using multiple glTexSubimage3D(). However, for this to work, I need the OpenGL upload to skip (num_layers-1)*4 bytes after each pixel it uploads. I looked at the glPixelStore() parameters, and saw the GL_UNPACK_ROW_LENGTH param, but this doesn't work, since it skips after an entire row of pixels is done being read, and I need it to skip X bytes after every pixel. Is there something similar to GL_UNPACK_ROW_LENGTH or GL_UNPACK_IMAGE_HEIGHT but for single pixels? Or another way to upload sparsely packed pixels?


Solution

  • You will have to un-interleave the pixel data. OpenGL (and Vulkan for that matter) does not have a way to upload data where array layers are pixel-interleaved. And even if they did, what that would ultimately boil down to is someone else having to do the un-interleaving, since hardware can't directly consume such data.