我有一个大小为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);
答案 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意味着纹理宽度用于数据的宽度。