我的目标是,如果纹理的像素值与设定的RGB颜色完全匹配,则使其像素值100%透明。我的程序使用24位.bmp图像,我知道它不包含第四个通道(除了填充),所以我一直试图想出一个很好的方法来帮助添加一个alpha通道来执行基本的透明度。
我理解如何计算实际的alpha值并正确设置混合函数,但是当我尝试将第四个值添加到GLubyte RGB三元组时遇到了障碍,让我相信这种格式根本不支持α。所以我有一个想法,手动将纹理数据从字节转换为32位无符号整数,但我有执行的麻烦。在我看来(从书上看)内部像素格式GL_UNSIGNED_INT将为每个像素采用四个32位整数,但是当我通过将0.0-1.0字节值钳位到最大范围来转换字节时,我的程序将无法启动一个unsigned int。
我不希望得到答案给我,但我真的很感激推动正确的方向。我是在正确的轨道上转换为每像素4个整数,或者是否有可能使字母数据可以忽略?我考虑使用GL_UNSIGNED_INT_8888格式,但我想尽可能避免位移。
答案 0 :(得分:3)
GL_UNSIGNED_INT
不是"内部像素格式" 。这实际上是像素传输数据类型。
多年来,GL中的内部格式有点神秘,你必须要求组件数量,但不是很多。这些天(GL3 +)你必须使用明确大小的内部格式,例如GL_RGB8
,这样可以避免大部分的猜测。但是,您仍然可以假设驱动程序将GL_RGB8
填充额外的8位,以便每种颜色都以2的幂边界开始。因此,GL_RGB8
与[{1}}具有相同的存储要求,两者之间的唯一区别是GL_RGBA8
具有所有不透明像素。
当您使用GL_RGB8
作为像素传输的数据类型时,这意味着GL将把输入图像数据解释为具有32位(无符号)的每颜色分量(每像素12个字节) )。您不希望这样,您目前每像素有3个无符号8位分量,因此GL_UNSIGNED_INT
是合适的(每像素3个字节)。 添加4 th 组件不会改变单个组件的大小。
关于GL_UNSIGNED_BYTE
,如果您尝试上传RGBA图片,则实际上与GL_UNSIGNED_INT_8_8_8_8
略有不同。它就是所谓的打包数据类型; 4个组件打包到与GL_UNSIGNED_BYTE
相同的占用空间中,每个组件为8位。还存在GL_UNSIGNED_INT
,它更有用 - 它告诉GL在像素传输期间反转颜色分量,如果您只指定GL_UNSIGNED_INT_8_8_8_8_REV
作为数据类型,则无法执行此操作。 GL_UNSIGNED_BYTE
解决了CPU字节顺序问题,而小端CPU GL_UNSIGNED_INT_8_8_8_8[_REV]
则相当于GL_UNSIGNED_INT_8_8_8_8_REV
。
请记住,GL期望图像的每一行都以4字节边界开始。
如果您的每像素24位图像的宽度不能被4整除,那么您的数据将会错位,并且GL会错误地将其解包。要解决此问题,您可以将解压缩对齐设置为 1 -byte(默认为 4 ),如下所示:
GL_UNSIGNED_BYTE
.bmp文件格式已填充每行的末尾以满足4字节对齐,这只是我想指出的完整性。
答案 1 :(得分:2)
它应该是直接的,不需要黑客攻击。有两种方法可以实现您的需求。第一个解决方案是简单地将bmp作为普通RGB数据加载,然后为alpha通道分配一个额外30%大小的新缓冲区,并为每3个字节复制一次,添加一个表示所需alpha值的字节。然后在上传到OpenGL设备时,声明它是GL_RGBA而不是GL_RGB,同时将格式保持为GL_UNSIGNED_BYTE。这样,您可以在加载时将数据从3个通道转换为4个通道。第二种解决方案是在片段着色器中执行片段丢弃,因为丢弃与100%透明相同。由于您知道要丢弃哪种颜色,因此可以使用统一或任何其他方式将这些rgb值传递到着色器,然后片段着色器可以相应地进行检查和丢弃。您甚至不必担心此解决方案中的Alpha通道。