【问题标题】:Bitmap Padding Bytes in OpenGL PixelBufferObjectOpenGL PixelBufferObject 中的位图填充字节
【发布时间】:2015-05-20 12:07:49
【问题描述】:

我有一个大小为 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);

【问题讨论】:

  • 你的纹理格式是什么? RGBA,即每像素 4 个字节?
  • @RetoKoradi 不,它是每个像素一个字节。 8bpp 索引灰度。

标签: opengl opentk opengl-4


【解决方案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 的值将避免任何对齐(@9​​87654331@ 也适用于您的情况,因为您的行长度是 2 个字节的倍数):

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

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

【讨论】:

  • 我试过 (bitmap.Width * bitmap.Height) (3750*351) 它仍然有效。但我没有使用 glPixelStorei()。
猜你喜欢
  • 2010-09-29
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-18
  • 2011-02-05
  • 1970-01-01
相关资源
最近更新 更多