不解

《深入了解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  <op>  Rd * Dr,  Gs * Sg  <op>  Gd * Dg,  Bs * Sb  <op>  Bd * Db,  As * Sa  <op>  Ad * 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。

下面给出示例代码:


  1. //
  2. //  MyView.m
  3. //  OpenGLTest
  4. //
  5. //  Created by Zenny Chen on 4/25/10.
  6. //  Copyright 2010 GreenGames Studio. All rights reserved.
  7. //  P44
  8.  
  9. #import "MyView.h"
  10.  
  11. #include <OpenGL/OpenGL.h>
  12. #include <math.h>
  13.  
  14.  
  15. @implementation MyView
  16.  
  17. - (id)initWithFrame:(NSRect)frame {
  18.     self = [super initWithFrame:frame];
  19.     if (self) {
  20.         // Initialization code here.
  21.     }
  22.     return self;
  23. }
  24.  
  25. // Destination: a rectangle
  26. static const struct VertexInfo
  27. {
  28.     GLfloat vertices[3];
  29. }vertexList[] = {
  30.     {-0.5f, 0.5f, -1.0f},
  31.     {-0.5f, -0.5f, -1.0f},
  32.     {0.5f, 0.5f, -1.0f},
  33.     {0.5f, -0.5f, -1.0f}
  34. };
  35.  
  36. - (void)prepareOpenGL
  37. {
  38.     glEnable(GL_CULL_FACE);
  39.     glEnable(GL_BLEND);
  40.     
  41.     glEnableClientState(GL_VERTEX_ARRAY);
  42.     
  43.     glVertexPointer(3, GL_FLOAT, 0, vertexList);
  44.     
  45.     glFrontFace(GL_CCW);
  46.     glCullFace(GL_BACK);
  47.     
  48.     glShadeModel(GL_SMOOTH);
  49.     
  50.     // Set Background color(frame buffer color)
  51.     glClearColor(1.0, 0.0, 0.0, 1.0);
  52.     
  53.     glViewport(0, 0, 320, 320);
  54.     
  55.     glMatrixMode(GL_PROJECTION);
  56.     glLoadIdentity();
  57.     glOrtho(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);
  58.     
  59.     glMatrixMode(GL_MODELVIEW);
  60.     glLoadIdentity();
  61.     
  62.     // destination color
  63.     glColor4f(1.0f, 1.0f, 1.0f, 0.3f);
  64.     
  65.     glBlendEquation(GL_FUNC_ADD);
  66.     
  67.     glBlendFunc(GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA);
  68. }
  69.  
  70. - (void)drawRect:(NSRect)dirtyRect {
  71.     
  72.     // Drawing code here.
  73.     glClear(GL_COLOR_BUFFER_BIT);
  74.     
  75.     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  76.     
  77.     glFlush();
  78. }
  79.  
  80. @end

评论