读入外部图像作为opengl中的纹理时,有一些格式上的注意事项
我们读入一张jpg的图片,首先需要清楚图像的像素格式,例如,在Qt中,QImage类中有一些方法可以帮助我们获得关于图像格式的信息
如上图所示,解析后,得到一个RGB32的图像,高位是ff, 后面是RGB
在opengl中,我们通过以下方式加载纹理:
glTexImage2D(GL_TEXTURE_2D,
0, //指定mipmap等级,级别0是基本图像级别。级别n是第n个缩略图缩小图像
GL_RGBA, //指定纹理的内部格式
model.getQImage()->width(), model.getQImage()->height(),
0, //必须为0, 历史遗留的问题
GL_BGRA, //指定纹理外部数据的格式。
GL_UNSIGNED_BYTE, //指定纹理数据的数据类型
model.texData());
这里引入了内部格式和外部格式的概念
所谓内部格式就是opengl内部用来存储用户提供的纹理数据的格式;
外部格式就是用户向opengl提供数据时使用的格式,由format和type来指定。
接着看上面的例子:开始的时候,我们把内部格式和外部格式都设置成GL_RGBA,得到的效果如下:
结果得到的图颜色通道看起来是错误的。其原因在于对于外部格式为GL_RGBA, 对于每个采样器采样得到的vector, 其解释为
GL_RGBA, 但是我们刚才知道从低到高pixel的颜色是BBGGRRff, 因此最终对应到屏幕缓冲区,本来应该是红色的channel变成了蓝色,本来应该是蓝色的地方变成了红色。而原图本来是个整体偏蓝的图,也就是蓝色分量的值整体比较大,所以现在这样就会导致屏幕缓冲区的图整体偏红。
因此,改正方法是外部格式改为GL_BGRA, 这样对于sampler2D而言,就对的上了。
顺着这个问题,继续向下探究:如果我们任意更改内部格式,最终的呈现效果会变成怎样呢?
比如内部格式为GL_R, 外部格式为GL_BGRA, 发现最终只有红色,猜测是着色器的sampler只采集R分量所致?这样输出的时候也只有R分量
又做了个实验,内部格式为GL_RG, 外部格式为GL_BGRA, 发现图像整体偏绿,用ps打开原图,然后关闭B通道,发现效果相同,说明最中输出
到屏幕缓冲区的的确是没有B通道。