图形学基础:第1章 颜色
来源:互联网 发布:游戏美工原画招聘 编辑:程序博客网 时间:2024/06/05 22:30
第1章:颜色
任何事物的颜色可以通过三基色(红red、绿green、蓝blue)混合而成,颜色的分量(也有叫做通道)即指red、green、blue的所占比例,除了这三种分量外,我们有时候还需要使用到透明度分量(alpha)
颜色的表示
使用3个float表示颜色
考虑到运算性能和内存开销,使用3个float来表示其red、green、blue分量,一般使用范围为0到1,1为100%
struct Color3f { float _red; float _green; float _blue; public: Color3f() {} Color3f(const Color3f& c):_red(c._red), _green(c._green), _blue(c._blue) {} Color3f(float r, float g, float b) : _red(r), _green(g), _blue(b) {} Color3f operator +(const Color3f& c) const { return Color3f(_red + c._red, _green + c._green, _blue + c._blue); } Color3f operator -(const Color3f& c) const { return Color3f(_red - c._red, _green - c._green, _blue - c._blue); } Color3f& operator +=(const Color3f& c) { _red += c._red, _green += c._green, _blue += c._blue; return *this; } Color3f& operator -=(const Color3f& c) { _red -= c._red, _green -= c._green, _blue -= c._blue; return *this; } Color3f operator *(float k) const { return Color3f(_red * k, _green * k, _blue * k); } Color3f operator /(float k) const { return Color3f(_red / k, _green / k, _blue / k); } Color3f& operator *=(float k) { _red *= k, _green *= k, _blue *= k; return *this; } Color3f& operator /=(float k) { _red /= k, _green /= k, _blue /= k; return *this; } };
使用4个float表示颜色
使用4个float表示具有透明度的颜色,其中alpha,0表示全透明,1表示不透明
struct Color4f { float _red; float _green; float _blue; float _alpha; public: Color4f() {} Color4f(const Color3f &c) :_red(c._red), _green(c._green), _blue(c._blue), _alpha(1.0f) {} Color4f(float r, float g, float b, float a = 1.0f) : _red(r), _green(g), _blue(b), _alpha(a) {} Color4f operator +(const Color4f& c) const { return Color4f(_red + c._red, _green + c._green, _blue + c._blue, _alpha + c._alpha); } Color4f operator -(const Color4f& c) const { return Color4f(_red - c._red, _green - c._green, _blue - c._blue, _alpha - c._alpha); } Color4f& operator +=(const Color4f& c) { _red += c._red, _green += c._green, _blue += c._blue, _alpha += c._alpha; return *this; } Color4f& operator -=(const Color4f& c) { _red -= c._red, _green -= c._green, _blue -= c._blue, _alpha -= c._alpha; return *this; } Color4f operator *(float k) const { return Color4f(_red * k, _green * k, _blue * k, _alpha * k); } Color4f operator /(float k) const { return Color4f(_red / k, _green / k, _blue / k, _alpha / k); } Color4f& operator *=(float k) { _red *= k, _green *= k, _blue *= k, _alpha *= k; return *this; } Color4f& operator /=(float k) { _red /= k, _green /= k, _blue /= k, _alpha /= k; return *this; } };
使用4个字节表示颜色
很多时候我们也采用4个字节表示颜色,由于每个字节的表示范围为0-255,可以理解为它将颜色的各分量分成了256个程度,那么除去透明度,它可以表示的颜色共256*256*256种,相比上一种表示方式,它的精度远不如上一种,但节省大量内存开销,事实上目前的显示设备大多也只支持这么多的颜色种数。
typedef unsigned char byte; union Color4b { int _value; struct { byte _alpha; byte _blue; byte _green; byte _red; }; public: Color4b() {} Color4b(const Color4b& c) : _value(c._value) {} Color4b(int value) : _value(value) {} Color4b(byte a, byte r, byte g, byte b) : _alpha(a), _blue(b), _green(g), _red(r) {} };
- 这里我们使用了联合体定义Color4b结构,这样可以方便了各分量进行访问,也方便了int赋值(形如0xAABBGGRR)。
- 这里我们没有使用class来定义颜色,因为颜色本来就只是一种描述结构,与类的封装、继承、多态毫无关系,我们仅重载一些运算符方便计算表达。
颜色的混合
不透明颜色和半透明颜色的混合
假设一不透明的背景图像是A,另一幅透明的图象是B,那么透过B去看A,看上去的图象C就是B和A的混合图象
C = (1 - B.alpha) * A + B.alpha * B
Color3f sge::alphaBlend(const Color3f &bgcolor, const Color4f &fcolor){ float pA = 1.0f - fcolor._alpha; Color3f out; out._red = pA * bgcolor._red + fcolor._alpha * fcolor._red; out._green = pA * bgcolor._green + fcolor._alpha * fcolor._green; out._blue = pA * bgcolor._blue + fcolor._alpha * fcolor._blue; return out;}
半透明颜色和半透明颜色的混合
半透明玻璃A与半透明玻璃B重叠与单个半透明玻璃C的效果一样,我们可以根据A与B计算出C的颜色和透明度。
可以想象一束光透过透明度为80%的玻璃后光线强度变为80%,再透过一个透明度为60%的玻璃后光线强度剩下48%,由于我们采用不透明度,我们将A、B、C透明度简写为A.a、B.a、C.a,则:
C.a = 1 - ((1 - A.a) * (1 - B.a)) = A.a + B.a - A.a * B.a
我们已经知道,在背景色上如何叠加半透明色,我们可以分为两步,先在背景色上叠上第一个半透明颜色A,然后在叠好的结果上叠上第二个半透明颜色B,设原始背景色为R1,第一次的叠好的结果为T1,全叠好的结果为T2
T1 = (1 - A.a) * R1 + A.a * A;
T2 = (1 - B.a) * T1 + B.a * B
= (1 - B.a) * ((1 - A.a) * R1 + A.a * A) + B.a * B
= (1 - B.a) * (1 - A.a) * R1 + (1 - B.a) * A.a * A + B.a * B而T2还应等同于R1与C的直接混合结果
T2 = (1 - C.a) * R1 + C.a * C
= (1 - (A.a + B.a - A.a * B.a)) * R1 + (A.a + B.a - A.a * B.a) * C
= (1 - A.a) * (1 - B.a) * R1 + (A.a + B.a - A.a * B.a) * C联立上述等式,同减(1 - A.a) * (1 - B.a) * R1,可以消除R1,化简得C:
C = [(1 - B.a) * A.a * A + B.a * B] / (A.a + B.a - A.a * B.a)
Color4f sge::alphaBlend(const Color4f &c1, const Color4f &c2){ Color4f out; out._alpha = c1._alpha + c2._alpha - c1._alpha * c2._alpha; float k = (1.0f - c2._alpha) * c1._alpha; out._red = (k * c1._red + c2._alpha * c2._red) / out._alpha; out._green = (k * c1._green + c2._alpha * c2._green) / out._alpha; out._blue = (k * c1._blue + c2._alpha * c2._blue) / out._alpha; return out;}
本节不能生成可执行程序
本章代码位于sgeMath.h中,github链接https://github.com/xiangwencheng1994/sge/tree/master/lesson1.Color
- 图形学基础:第1章 颜色
- 图形学基础:第2章 画布
- 图形学基础:第3章 画线
- 图形学基础:第4章 画三角形
- 图形学基础: 第5章 纹理贴图
- 图形学基础(1)
- OpenGL超级宝典学习笔记第一部分:OpenGL API基础 第1章 3D图形学的基本原理
- 图形学基础
- 图形学 基础
- 计算机图形学导论(1)-基础数学
- 计算机图形学基础(三) 观察1
- 计算机图形学基础(五) 光照1
- 第26周-window程序设计(基础篇)-第5章(图形基础)-关于颜色
- 图形学基础(2)
- 图形学基础(3)
- 图形学基础--画直线
- 计算机图形学基础
- 图形学基础词汇解释
- 在Openwrt上安装alar以便进行录音,播音功能
- 深度学习之基础模型-FractalNet
- Android自定义折线图
- mysql5.7.19版本数据表名不区分大小写
- word转出图片(使用免费插件)03
- 图形学基础:第1章 颜色
- Java用MyEclipse 连接数据库
- Google Map开发系列(七)——使用谷歌地图API实现自定义控件
- 续厨师与母亲的厨艺问题的一些想法
- Android常见动画以及分类
- 使用Python机器识别库pytesseract遇到的问题
- 三道典型C语言题(3)
- 命令行编译一个简单的 VC 程序
- leetcode 16. 3Sum Closest