Irrlicht 源码学习笔记 【Color.h】

不知道现在这个顺序来说现在看这个文件是不是合适的

但是 Color 的操作也是最基本的操作之一,而且也很简单

总之先学习一下记录下来吧  ԅ(¯﹃¯ԅ)



首先总结一下常用的颜色表示格式

如果对常用颜色格式已经很了解,智能略过就好喽

////////////////////////// "话痨" buff 开始 //////////////////////////

目前在计算机游戏中最常使用 RGB 来表示颜色,即是使用 Red Green Blue 三个颜色分量合成颜色

当 RGB = (0, 0, 0) 时, 表示各个颜色都没有 ,也就是黑色

当 RGB = (255, 255, 255) 时, 表示各个颜色都最大, 也就是白色

当 RGB = (255, 0, 0) 时, 表示红色最大,其他颜色都没有, 也就是红色


以前的街机游戏中,常使用 8 位的颜色,但是现在基本上已经不使用了

它并不能完全表示一个颜色,而是记录一个在 调色板(颜色查询表) 中的位置

所以街机游戏中同一个场景中最多只能出现 256 种颜色

( 都是因为那个时候穷,而且内存很贵的! )


现在常常使用 16 位、24 位 和 32位 颜色,即分别使用 16bit 、 24bit 、 32bit 表示一个颜色

其中 24bit 颜色不能在显存中对齐,所以不是所有显卡都支持,但是 32bit 颜色可以对齐,可以获得更多的支持


对于 16bit 颜色,常用的格式有 A1R5G5B5 、 R5G6B5 和 X1R5G5B5

X - 表示没有使用, 如 X1 即表示有 1bit 是没有使用的,但是依然占用了这部分空间

A - 表示 Alpha ,标识颜色的透明度, 如 A1 即表示使用 1bit 存储透明度

R - 表示 Red, 标识颜色的红色分量, 如 R5 即表示使用 5bit 存储红色分量

G - 表示 Green, 标识颜色的绿色分量, 如 G5 即表示使用 5bit 存储绿色分量

B - 表示 Blue, 标识颜色的蓝色分量, 如 B5 即表示使用 5bit 存储蓝色分量


对于 24 位颜色,即是 R8G8B8 

对于 32 位颜色,常使用的格式有 A8R8G8B8、X8R8G8B8

////////////////////////// "话痨" buff 结束 //////////////////////////


Irrlicht 中支持 16位 颜色和 32 位颜色

因为颜色使用一个 unsigned int 或者 unsigned short 表示

所以对颜色的操作基本上都要使用位运算



【创建一个 16bit 颜色】

只要知道不同颜色格式中每一位对应的信息,就都可以使用相同的方式进行操作

所以,这里只对 16 位的 X1R5G5B5 进行分析,理解了原理之后自然可以举一反三

( 其实在这个高手云集的地方,可能有点给爱因斯坦看初中物理课本的意思... 博主只作为笔记,看官们只能略过 )


首先是最高位 1bit 是空闲的,所以不作处理

因为参数中每个颜色分量值的范围应该从 0 ~ 255,即占用 8bit

红色分量占用接下来的 5bit ,Irrlicht 中取的是高 5bit , 所以 ( ( red >> 3 ) & 0x1f)

其中 0x1F 是十六进制的 31, 二进制表示是 11111,与其按位取与即可得到最低位 5bit 

之后需要将红色分量填充到高位中第 11~15位, 所以左移 10 位填充到指定 bit 位置


对于绿色和蓝色同样取有效的 8bit 中高位的 5bit

然后分别填充到 6~10bit 和 1~5bit 

即分别左移 5bit 和 0bit


由于函数内部十分简单而且位运算是十分快速的

所以函数调用本身消耗的时间很可能远超过了函数内部代码执行的时间

所以将函数改写为宏或者设置为内联函数可以大大提高执行的效率

//! Creates a 16 bit A1R5G5B5 color  (创建一个 16 位 Alpha 1bit, Red 5bit, Green 5Bit, Blue 5bit)
inline s16 RGB16(s32 r, s32 g, s32 b)
{
	return (((r>>3) & 0x1F)<<10) | (((g>>3) & 0x1F)<<5) | ((b>>3) & 0x1F);
}


【取某一个颜色分量】

获取某一个颜色分量的操作与设置某一个颜色分量的操作正好相反

例如 16bit X1R5G5B5 取红色分量,即将红色分量部分移位操作使之位于最低的 5bit 然后取出来

//! Returns the red component from the color (提取颜色中的红色值)
inline s32 getRed(s16 color)
{
	return ((color >> 10) & 0x1F);
}


【32bit 颜色格式转换位 OpenGL 颜色格式】

OpenGL 中的 32bit 像素颜色存储格式不是 ARGB ,而是 ABGR

所以在 Color 类中提供了一个转换为 OpenGL 格式的方法

方法内不对当前颜色进行修改,而只是返回一个 OpenGL 格式的 32bit 颜色



【推倒重建?!】

Irrlicht 中对于颜色的转换通通不是只修改某一个部分

哪怕只是修改一下红色的分量,也会从原有颜色中获取每一个分量然后再组成新的

尽管博主曾经认为可以直接修改对应的 bit 部分,没有必要这样推倒重建 ( 毕竟博主是一个念旧的人嘛  ╮(╯▽╰)╭   )

但是博主在尝试了之后发现,将某几位 bit 置为 0 比将某几位置为 1 要复杂

相比之下直接推倒重建可以有更清晰的逻辑,所以博主也理解 Irrlicht 程序猿这样写的原因了

( 各位看官可以自己尝试一下,然后把代码贴出来 )

inline void setRed(s32 r) { color = (((color>>24) & 0xff)<<24) | ((r & 0xff)<<16) | ((color>>8 & 0xff)<<8) | (color & 0xff); }


【浮点数表示颜色分量】

颜色分量的表示除了可以使用 0~255 之间的整数表示之外

也可以使用 0.0 ~ 1.0 之间的小数表示,即 0.0 是没有颜色, 1.0f 是颜色最大

显卡内部表示颜色的时候就是使用这种表示方法

Color.h 中的 Colorf 类即是使用这种表示方法

当然,这两种表示方法是可以相互转换的



如果博主有错误的地方,或者理解不周到的地方,大家多多提出建议吧!




以前看电视的时候老妈经常以"离电视太近"为理由骂我,现在好了,都酱婶儿了~  ლ(╹◡╹ლ)


Irrlicht 源码学习笔记 【Color.h】_第1张图片



你可能感兴趣的:(Irrlicht)