OpenGL 红宝书 混合
6.1 混合
6.1.1 源因子和目标因子
假定源和目标混合因子分别为(Sr, Sg, Sb, Sa)和(Dr,Dg,Db,Da), 混合后的RGB值如下:
(RsSr + RdDr, GsSg + GdDg, BsSb + BdDb, AsSa + AdDa)
最后,将该四元组的各个分量截取到[0,1].
将源片元和目标象素合并起来的默认方式是,将它们的值相加.
选择源混合因子和目标混合因子的方式:
第一种方式是调用函数glBlendFunc(),并指定两个混合因子, 其中第一个参数为源RGBA的混合因子, 第二个参数为目标RGBA的混合因子.
第二种方法是调用glBlendFuncSeparate()并指定4个混合因子, 这样可以用不同的方式来混合RGB和alpha值.
void glBlendFunc(GLenum srcfactor, GLenum destfactor);
srcfactor指出如何计算源混合因子; destfactor指出如何计算目标混合因子.
void glBlendFuncSeparate(GLenum srcRGB, GLenum destRGB, GLenum srcalpha, GLenum destalpha);
源混合因子和目标混合因子
常量: RGB混合因子 alpha混合因子
GL_ZERO: (0, 0, 0) 0
GL_ONE: (1, 1, 1) 1
GL_DST_COLOR: (Rd, Gd, Bd)
GL_SRC_COLOR: (Rs, Gs, Bs) A
GL_ONE_MINUS_DST_COLOR: (1, 1, 1) - (Rd, Gd, Bd)
GL_ONE_MINUS_SRC_COLOR: (1, 1, 1) - (Rs, Gs, Bs) 1 - A
GL_SRC_ALPHA: (As,As,As,As)
GL_ONE_MINUS_SRC_ALPHA: (1, 1, 1, 1) - (As,As,As,As)
GL_DST_ALPHA: (Ad, Ad, Ad, Ad)
GL_ONE_MINUS_DST_ALPHA: (1, 1, 1, 1) - (Ad, Ad, Ad, Ad)
GL_SRC_ALPHA_STATURATE: (f, f, f, 1); f = min(As, 1 - Ad)
另将GL*CONSTANT*作为参数时, 需要使用glBlendColor()指定一个常量(constant)颜色
void glBlenColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
设置执行混合操作时使用的常量颜色的红,绿,蓝和alpha值(Rc, Gc, Bc, Ac)
6.1.2 启用混合操作
glEnable(GL_BLEND);
6.1.3 使用混合方程来合并像素
采用标准混合方式时, 将帧缓存中的颜色和输入片元的颜色合并起来, 得到新的帧缓存颜色.
void glBlendEquation(GLenum mode);
上面的函数用来指定其他数学运算,以计算帧缓存颜色和片元颜色的差, 它们中的最大值或最小值.
指定如何混合帧缓存中的颜色和片元颜色.
Cs和Cd表示源颜色和目标颜色, S和D表示函数glBlendFunc()或glBlendFuncSeparate()指定的源混合因子和目标混合因子.
GL_FUNC_ADD CsS + CdD
GL_FUNC_SUBTRACT CsS - CdD
GL_FUNC_REVERSE_SUBTRACT CdD - CsS
GL_MIN min(CsS, CdD)
GL_MAX max(CsS, CdD)
要使用OpenGL扩展代码
1. 增加头文件
#include <GL/glext.h>
2. 定义函数指针
PFNGLBLENDEQUATIONPROC glBlendEquation = NULL; //定义函数指针
3. 在内存中找到函数地址
PFNGLBLENDEQUATIONPROC glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation");
使用深度透视,重绘的时候要注意清除深度缓存,否则会消失.
6.1.4 混合的用途
1. 均匀地混合两幅图像:
首先将源因子和目标因子分别设置为GL_ONE和GL_ZERO. 并绘制第一副图像.
然后将源因子设置为GL_SRC_ALPHA, 目标因子设置为GL_ONE_MINUS_SRC_ALPHA, 并在绘制第二幅图像时使用alpha值0.5. 这是最常用的混合方式.
如要设置第一副图像占75%, 第二幅图像占25%. 可以在绘制第二幅图像使用alpha值0.25.
2. 均匀地混合三幅图像, 目标因子设置为GL_SRC_ALPHA, 然后使用alpha值 0.3333333绘制这些图像.这样每幅图像的亮度只有原来的三分之一.
3. 逐渐加深图像的颜色: 源混合因子和目标混合因子分别设置为GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA, 并将画笔的alpha值设置为0.1
4. 通过将源混合因子设置为GL_DST_COLOR或GL_ONE_MINUS_DST_COLOR.将目标混合因子设置为GL_SRC_COLOR或GL_ONE_MINUS_SRC_COLOR,可以分别调整各个颜色分量.
相当于使用一个简单的滤光器.
如红色分量乘以0.8,绿色分量乘以0.4,蓝色分量乘以0.72. 相当于滤光器滤掉20%的红光, 60%的绿光和28%的蓝光.
5. 纯色背景三个半透明面组成的图像.最远的透过其后80%的颜色, 接下来的面40%,最近的90%.
首先用默认的源混合因子和目标混合因子绘制背景
然后源混合因子和目标混合因子为GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA, 并依次是哟个alpha值0.2绘制最远的面,0.6绘制中间面,0.1绘制最近的面.
6. 如果系统有alpha位面, 可以每次渲染一个物体, 然后将它们读取到内存中, 然后对渲染后的物体执行有趣的合成操作.
7. 通过给图像中的片元指定不同的alpha值,可以实现非矩形光栅图像的效果.
透明片元的alpha值设置为0, 不透明片元的alpha值设置为1.0.
8. 混合也可以用于实现反走样.
6.1.5 一个混合的例子
6.1.6 使用深度缓存的三维混合
方法: 启用深度缓存, 并在绘制半透明物体时, 将深度缓存设置为只读的.
首先, 将深度缓存设置为正常状态, 并绘制所有的不透明物体, 然后将深度缓存设置为只读的, 并使这些深度值保持不变. 绘制半透明物体时,将深度同不透明物体的深度值进行比较,这样, 如果他们位于不透明物体后面,不绘制他们, 如果它们离视点更近, 也不会消除不透明物体, 因为深度缓存的值是无法修改的,而是与不透明物体混合在一起.
函数glDepthMask()可以控制深度缓存的读写状态. 参数GL_FALSE将深度缓存设置为只读. 参数GL_TRUE设置为可写.
http://www.cppblog.com/summericeyl/archive/2009/03/08/75941.html