OpenGL PixelBufferObject中的位图填充字节

时间:2015-05-20 12:07:50

标签: opengl opentk opengl-4

我有一个大小为3750x1407的位图,它作为位图加载到内存中,填充为2个字节,因此它在内存中的长度为(3752 * 1407)字节。当使用PixelUnpackBuffer来填充我的纹理时,我是否还需要复制填充字节,还是可以跳过它们?

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

1 个答案:

答案 0 :(得分:1)

如果正确应用,任何一个选项都可以使用。您可以使用GL_UNPACK_*设置的一组glPixelStorei()参数来控制行填充/大小。

从问题和代码中使用的格式看,您看起来像是1字节/像素格式。我的大部分答案也应该适用于其他格式,但我会将其用于计算。

此处至关重要的GL_UNPACK_*参数是:

  • GL_UNPACK_ALIGNMENT:定义数据的字节对齐。默认值为4.这意味着不是4个字节的倍数的行将填充到下一个4的倍数。
  • GL_UNPACK_ROW_LENGTH:定义行大小(以像素为单位)。默认值为0,这是一个特殊值,表示将使用传递给glTex(Sub)Image2D()的宽度。

填充输入数据

将填充的输入数据存储在PBO中,数据宽度为3752字节,其中第一个3750有效。由于3752是4的倍数,GL_UNPACK_ALIGNMENT的默认值将适用于此数据。

但是,由于纹理宽度仅为3750像素,而数据宽度为3752,因此必须将行长度设置为数据宽度:

glPixelStorei(GL_UNPACK_ROW_LENGTH, 3752);

对于glTexSubImage2D()中的宽度,您仍然会指定3750.不要忘记之后重置行长。

未填充的输入数据

如果在PBO中存储数据之前/之后删除填充,则PBO中的数据宽度现在为3750字节。由于这是不是 4的倍数,因此必须设置解包对齐以防止数据被读取为3752字节/行。值1将避免任何对齐(2也适用于您的情况,因为您的行长度是2个字节的倍数):

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

另一方面,PBO中数据的宽度现在与纹理宽度相同。因此,您不必费心设置GL_UNPACK_ROW_LENGTH,因为默认值为0意味着纹理宽度用于数据的宽度。