深入了解OpenGL
深入了解 OpenGL [html] view plaincopy大家好。这一讲,我们讲介绍 OpenGL 的颜色混合模式。其实颜色混合用到的场合很多, 比如多张图片的合成,动画游戏中的一些画面特效等都可以 通过颜色混合进行实现。最常用的混合方式就是实现物体与 背景的半透明效果。另外,在制作 2D 游戏时颜色混合可以 用来通过制作目标物体的蒙板实现移动。通过蒙板来消除旧 位置的物体对象可以不必重绘当前整帧内容,而仅仅是发生 变化的那些物体。为了各位从事 iPhone 开发的考虑。后面 的代码例子对 OpenGL API 的使用都会用 OpenGL2.1 与 OpenGL ES1.1 相互兼容的接口。 首先介绍一下 OpenGL 对 源对象和目标对象进行颜色混合的实现。这里,源对象是指 你将要绘制的对象;目标对象是指已在帧缓存中的颜色。比 如调用 glClear(GL_COLOR_BUFFER_BIT);后留在帧缓存 中的颜色。在进行计算时,源和目标的混合都是在绘制源对 象时进行计算的,在绘制对象以外的帧缓存像素不会受任何 影响。为了方便颜色混合,我们往往采用 RGBA 这种颜色模 式。其中 RGB 表示色彩分量,而 A 就是混合因子(blend factor) 。A,我们在图形、图像处理中常常表示为: alpha, 它在图像处理中常用作为透明系数。我们指定了源和目标的 混合因子后, OpenGL会对绘制对象的最终颜色做如下计算: 设:源对象的某个顶点的颜色为(Rs, Gs, Bs, As)目 的对象对应此源对象顶点的颜色为(Rd, Gd, Bd, Ad) 源混合因子为: (Sr, Sg, Sb, Sa)目的混合因子为: (Dr, Dg, Db, Da)那么,该顶点最终目标颜色为:(Rs * Sr opRd * Dr,Gs * SgopGd * Dg,Bs * SbopBd * Db,As * SaopAd * Da) 其中,op可以是加法(+) ,减法(-) , 逆向减法, 最小值, 最大值或按位逻辑操作, 并且其优先级小于乘法 (*) 。 下面,我们介绍相关的OpenGL 接口。首先是开启混合,使 用 glEnable(GL_BLEND);即可。然后我们使用 glBlendEquation()来指定混合操作,参数可以是: GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX。 但这里要注意的是,OpenGL ES1.1 没有 glBlendEquation 接口,因此只能做加法操作。glBlendFunc()接口用于指定源 混合因子与目标混合因子。参数请参考红宝石书中文版的第 140 页,表 6-1。下面给出示例代码:[plain] view plaincopy// //MyView.m//OpenGLTest////Created by Zenny Chen on 4/25/10.//Copyright 2010 GreenGames Studio. All rights reserved.//P44 #import “MyView.h“#include OpenGL/OpenGL.h #include math.h@implementation MyView- (id)initWithFrame:(NSRect)frame {self = [super initWithFrame:frame];if (self) {// Initialization code here.}return self;}// Destination: a rectanglestatic c*****t struct VertexInfo {GLfloat vertices[3];}vertexList[] = {{-0.5f, 0.5f, -1.0f},{-0.5f, -0.5f, -1.0f},{0.5f, 0.5f, -1.0f}, {0.5f, -0.5f, -1.0f}};- (void)prepareOpenGL {glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertexList); glFrontFace(GL_CCW);glCullFace(GL_BACK); glShadeModel(GL_SMOOTH);// Set Background color(frame buffer color) glClearColor(1.0, 0.0, 0.0, 1.0);glViewport(0, 0, 320, 320); glMatrixMode(GL_PROJECTION);glLoadIdentity(); glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0); glMatrixMode(GL_MODELVIEW);glLoadIdentity(); // destination colorglColor4f(1.0f, 1.0f, 1.0f, 0.3f); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA);}- (void)drawRect:(NSRect)dirtyRect {// Drawing code here. glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); gl();}@end上述代码第 67 行的 glBlendFunc(GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA);用于指定: 源混合因子:(As, As, As, As),这里是(0.3, 0.3, 0.3, 0.3) 目标混合因子则是: (1, 1, 1, 1) - (As, As, As, As), 结果是(0.7, 0.7, 0.7, 0.7)。 这里我们能够看到,为目标和源指定混合因子可以是源、目 标的任一颜色分量或 alpha 因子,或是[0, 1]范围内的补。 对于上述代码,我们可以用等价的方式实现。 已知,目的像素颜色值为:(1.0, 0.0, 0.0, 1.0);源像素颜色 值为:(1.0f, 1.0f, 1.0f, 0.3f)。 目的混合因子为: (0.7, 0.7, 0.7, 0.7); 源混合因子为: (0.3, 0.3, 0.3, 0.3) OK。 我们可以直接把最终目标像素颜色值给算出来——(1.0 * 0.3 + 1.0 * 0.7,1.0 * 0.3 + 0.0 * 0.7,1.0 * 0.3 + 0.0 * 0.7,0.3 * 0.3 + 1.0 * 0.7) = (1.0,0.3,0.3,0.79)。 因此,我们可以将 67 行的 glBlendFunc(GL