2

I have a Bitmap of size 3750x1407, it is loaded as Bitmap into memory with a padding of 2 bytes, so it is of length (3752*1407) bytes in memory. When using PixelUnpackBuffer to fill my textures, do I need to copy the padding bytes as well or can I just skip them?

            GL.BindTexture(TextureTarget.Texture2D, texId);
            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, pboId[currentIndex]);

            GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, bitmap.Width, bitmap.Height, PixelFormat.Luminance,
               PixelType.UnsignedByte, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, pboId[nextIndex]);
            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadOnly, bitmap.PixelFormat);
            GL.ColorTable(ColorTableTarget.ColorTable, PixelInternalFormat.Luminance, _colorTable.Length, PixelFormat.Luminance, PixelType.Byte, new IntPtr(_colorTable[0]));

            IntPtr buf = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
            if (buf != IntPtr.Zero)
            {
              //---------------------------------------- Currently copying padding bytes--------------------------------------------- //
                memcpy(buf, bitmapData.Scan0, new UIntPtr((uint)(bitmapData.Stride * bitmap.Height)));
                GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
            }
            bitmap.UnlockBits(bitmapData);
            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
Dinesh
  • 115
  • 2
  • 7

1 Answers1

1

Either option will work if you apply it correctly. You have control over row padding/size with a set of GL_UNPACK_* parameters you can set with glPixelStorei().

From the question, and the format used in the code, it looks like you have a 1 byte/pixel format. Most of my answer should apply to other formats as well, but I'll use that for the calculation.

The GL_UNPACK_* parameters that are critical here are:

  • GL_UNPACK_ALIGNMENT: Defines the row alignment of the data in bytes. The default is 4. This means that rows that are not a multiple of 4 bytes are padded to the next multiple of 4.
  • GL_UNPACK_ROW_LENGTH: Defines the row size in pixels. The default is 0, which is a special value indicating that the width passed to glTex(Sub)Image2D() will be used.

Padded Input Data

Storing your padded input data in the PBO, the width of the data is 3752 bytes, where the first 3750 are valid. Since 3752 is a multiple of 4, the default value for GL_UNPACK_ALIGNMENT will work for this data.

However, since your texture width is only 3750 pixels, while the width of the data is 3752, you have to set the row length to the width of the data:

glPixelStorei(GL_UNPACK_ROW_LENGTH, 3752);

For the width in the glTexSubImage2D(), you will still specify 3750. Don't forget to reset the row length afterwards.

Unpadded Input Data

If you remove the padding before/while storing the data in the PBO, the width of the data in the PBO is now 3750 bytes. Since this is not a multiple of 4, you have to set the unpack alignment to prevent the data being read as 3752 bytes/row. A value of 1 will avoid any alignment (2 would also work in your case, since your row length is a multiple of 2 bytes):

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

On the other hand, the width of the data in the PBO is now the same as the texture width. Therefore you don't have to bother with setting GL_UNPACK_ROW_LENGTH, since the default of 0 means that the texture width is used for the width of the data.

Reto Koradi
  • 53,228
  • 8
  • 93
  • 133
  • I tried with (bitmap.Width * bitmap.Height) (3750*351) it still works. But I didn't use glPixelStorei(). – Dinesh May 21 '15 at 06:19