opengl纹理格式与图像格式辨析

读入外部图像作为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通道。

 

posted on 2021-09-14 22:55  疾速瓜牛  阅读(561)  评论(0编辑  收藏  举报

导航