本文记录作者在使用glPixelStorei (GLenum pname, GLint param)
的一些笔记。
本文主要介绍参数pname
为GL_UNPACK_ALIGNMENT
时的情况,使用该值时可指定内存中每个像素行开头的对齐要求,主要影响到glTexImage2D
等函数。
1.用法
GL_UNPACK_ALIGNMENT
是用来指定图像中各行的对齐方式。参数param
用来设置多少字节对齐。默认值是4,即图像始于4字节边界,每一行的字节数需是4的倍数。glPixelStorei(GL_UNPACK_ALIGNMENT,1)
将该值设置为1意味着图像紧密打包,各行对齐到字节边界。param
可以选择的值是1,2,4或8。
假设图像的宽是9,像素格式是GL_RGB
,每个分量1个字节,即第一行的字节数为27个字节。
当GL_UNPACK_ALIGNMENT
设置为1时,27是1的倍数,OpenGL则会从27个字节后读取。
当GL_UNPACK_ALIGNMENT
设置为4时,即要求每一行的字节数为4的倍数,而27不是4的倍数,这时候OpenGL会从32个字节后读取。
详细介绍请参考链接。
2.示例
用以下方法生成一个纹理。大小是2X2,格式为GL_RGB
。
GLubyte pixels[4 * 3] =
{
255, 0, 0, // Red
0, 255, 0, // Green
0, 0, 255, // Blue
255, 255, 0 // Yellow
};
glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 );
//glPixelStorei ( GL_UNPACK_ALIGNMENT, 4 );
glGenTextures ( 1, &textureId );
glBindTexture ( GL_TEXTURE_2D, textureId );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels );
1、当GL_UNPACK_ALIGNMENT
设置为1时,纹理效果如图1所示,与期望效果相符合。
注:纹理的(0,0)是从左下方开始,所以红色应该在左下方。这里为了方便与代码快速对应起来,在渲染上做了一些处理。
2、当GL_UNPACK_ALIGNMENT
设置为4时,纹理效果如图2所示。与期望效果不符合。
此时该纹理数据如图3所示。
此时CPU中pixels的存储地址和内容如图中方框中所示,当param
为4时,虽然原图像中每一行的自己数为2X3=6,但是因为6不是4的倍数,所以OpenGL第2行从第8个字节后开始读取。
以这样的方式读取,第一行的的数据与期望值相同,如上图中第一行的显示效果符合预期与原效果相同。但OpenGL读取的第2行数据已经错误,而且造成读取越界,读取到不属于pixels数组的204,(归一化后即为0.8,与图3对应)。相关如图4所示。
注:为什么是204?参考链接, Microsoft’s C++ 在调试时会把没有初始化的栈空间内存设置为0xcccccccc,即每个字节表现为204.
参考:
1、https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout
3、内存中常见异常值的解释(比如0xcccccccc、0xcdcdcdcd和 0xfeeefeee 异常值)以及关于VC 中 debug和Release模式下的变量初始化问题