OpenGL中的颜色混合功能(一)     
        我们知道,材料属性和光照参数可以极大地增加图形的逼真度,但除此之外,我们在对现实世界进行建模时,有许多效果是通过混合颜色的方式实现的。透明的物体,像是玻璃水杯,在它后面发射过来的光会与透明物体的颜色混合在一起。这种透明在OpenGL中的实现方式,是通过首先绘制背景物体,然后把前景物体(比如水杯)与颜色缓冲区中已经存在的颜色进行混合而实现的。在这一过程中,颜色的alpha值成分发挥了重要作用。

     颜色的混合功能
     在一般情况下,OpenGL在渲染时把颜色值存放在颜色缓冲区中,把每个片段(像素)的深度值存放在深度缓冲区中。当深度检测被关闭时,新的颜色值简单地覆盖颜色缓冲区中已经存在的颜色值;当深度检测被打开时,新的颜色值只有当它比原来的颜色更接近临近的裁剪平面时才会替换原来的颜色。当然,这是在OpenGL的混合功能被关闭的情况下。当混合功能被启用时,新的颜色会与颜色缓冲区中原有的颜色进行组合。通过对这些颜色进行不同的组合,可以产生许多种不同的效果。
     在介绍颜色混合之前,我们需要首先明确目标颜色和源颜色这两个术语的概念。首先,已经存储在颜色缓冲区中的颜色称为目标颜色,这个颜色包含了单独的红、绿、蓝成分以及一个可选的alpha值。其次,作为当前渲染命令的结果进入颜色缓冲区中的颜色称为源颜色,它同样也包含了四种颜色成分(红、绿、蓝和可选的alpha值成分)。我们正是通过对目标颜色和源颜色进行不同的组合操作,来实现颜色混合的功能的。启用混合功能:
     glEnable(GL_BLEND);
     当混合功能被启用时,源颜色和目标颜色的组合方式是由混合方程式来控制的。在默认情况下,使用的混合方程式如下所示:
     
     
     其中,Cf是最终计算产生的颜色,Cs是源颜色,Cd是目标颜色。S是源混合因子,D是目标混合因子。这两个混合因子可以通过下面的这个函数进行设置:
     glBlendFunc(GLenum S, GLenum D);
     可以看出,形参S和D都是枚举值,而不是可以直接指定的实际值。只谈概念有些模糊,让我们通过一个常见的混合函数示例来说明上述概念的实际应用:
     // 设置源混合因子和目标混合因子
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     根据上面的混合函数,如果颜色缓冲区中的目标颜色为红色(1.0f,0.0f, 0.0f, 0.0f);源颜色为一种蓝色(0.0f, 0.0f, 1.0, 0.6f),它的alpha值为0.6,那么计算得出的最终颜色为:
     Cd = 目标颜色 = (1.0f,0.0f, 0.0f, 0.0f)
     Cs = 源颜色 = (0.0f, 0.0f, 1.0, 0.6f)
     S = 源颜色alpha值 = 0.6
     D = 1 - 源颜色alpha值 = 0.4
     所以,根据混合方程式:
     
     相当于:Cf = (蓝 * 0.6)+ (红 * 0.4)     
     最终产生的颜色是目标颜色红色与源颜色蓝色进行缩放后的组合,并且源颜色的alpha值越高,添加的源颜色成分就越多,目标颜色所保留的成分就越少。这个混合函数经常用于在一些不透明的物体前面绘制透明物体的效果。这种技巧在实现时需要首先绘制背景物体,然后再绘制经过混合的透明物体。它的效果会令你惊讶,如图所示:
     
     让我们通过代码,来看一下Reflection示例程序的制作思路:
     void RenderScene()
     {
     // 清空颜色缓冲区和深度缓冲区
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     // ----------------------- 首先绘制地板下方的球体 --------------------
     // 保存矩阵状态
     glPushMatrix();
     // 将光源0的位置摆放到地板下方
     glLightfv(GL_LIGHT0, GL_POSITION, fLightPosMirror);
     // 保存矩阵状态
     glPushMatrix();
     // 设置顺时针环绕的一面为多边形的正面,对多边形进行镜像
     glFrontFace(GL_CW);         
     // 在Y轴使用-1的缩放因子来反转Y轴
     glScalef(1.0f, -1.0f, 1.0f);
     // 绘制地板下方的球体
     DrawSphere();
     // 设置逆时针环绕的一面为多边形的正面
     glFrontFace(GL_CCW);
     // 恢复矩阵状态
     glPopMatrix();
     // ----------------- 通过对地板设置透明的颜色混合效果,来实现反射的幻觉 -----------------
     // 关闭光照计算
     glDisable(GL_LIGHTING);
     // 打开颜色混合
     glEnable(GL_BLEND);
     // 设置混合因子
     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     // 绘制地板
     DrawGround();
     // 关闭颜色混合
     glDisable(GL_BLEND);
     // 打开光照计算
     glEnable(GL_LIGHTING);
     // -------------------- 最后绘制地板上方的球体 ---------------------------
     // 将光源0的位置摆放到地板上面
     glLightfv(GL_LIGHT0, GL_POSITION, fLightPos);
     // 绘制地板上方的球体
     DrawSphere();
     // 恢复矩阵状态
     glPopMatrix();
     // 执行缓冲区的交换
     glutSwapBuffers();
     }
     我们在进行场景的绘制时,首先以上下颠倒的方式,最先绘制地板下方的球体;然后打开混合,在球体的上面绘制一层透明的地板;最后恢复颠倒后的坐标系,绘制地板上方的球体。这三部分完成后,一幅地板反射球体的幻觉画面就完成了,如图所示:
 
                
     这一部分的示例程序完整代码已经放到了GitHub上,有需要的朋友可以参考一下(https://github.com/dxm3dp/OpenGL-06-Reflection点击打开链接)。
     本文出自杜晓萌的博客,请勿用于任何商业用途,转载请保持完整性并标明出处:http://blog.csdn.net/haohan_meng

OpenGL中的颜色混合功能(一)相关推荐

  1. 在OpenGL中实现Extrude 造型

    在Opengl中实现Extrude功能,通过glu库实现,当前问题在启用材质的存在缺陷.继续努力中 <code begin> /* Text3d by Robert J. Doyle, J ...

  2. OpenGL中的混色问题(Alpha通道)

    混合是一种常用的技巧,通常可以用来实现半透明.但其实它也是十分灵活的,你可以通过不同的设置得到不同的混合结果,产生一些有趣或者奇怪的图象. 混合是什么呢?混合就是把两种颜色混在一起.具体一点,就是把某 ...

  3. OPenGL中的缓冲区对象

    引自:http://blog.csdn.net/mzyang272/article/details/7655464 在许多OpenGL操作中,我们都向OpenGL发送一大块数据,例如向它传递需要处理的 ...

  4. Boost:在OpenCL并将图像渲染为OpenGL中的纹理

    Boost:在OpenCL并将图像渲染为OpenGL中的纹理 实现功能 C++实现代码 实现功能 Boost的compute模块,在OpenCL并将图像渲染为OpenGL中的纹理 C++实现代码 #i ...

  5. (转)OpenGL中位图的操作(glReadPixels,glDrawPixels和glCopyPixels应用举例)

    (一)BMP文件格式简单介绍 BMP文件是一种像素文件,它保存了一幅图象中所有的像素.这种文件格式可以保存单色位图.16色或256色索引模式像素图.24位真彩色图象,每种模式种单一像素的大小分别为1/ ...

  6. OpenGL中的上下文 理解整理

    OpenGL中的上下文(Context) OpenGL状态机与上下文 OpenGL是一个状态机,它拥有非常多的状态变量,并且每个状态变量都有默认值. OpenGL在渲染的时候需要一个Context来记 ...

  7. 【GPU编程】The Cg Runtime:OpenGL中调用Cg程序

    原文:<The Cg Tutorial>(Cg手册):Appendix B:The Cg Runtime,Page195 很多地方可能翻译得不好,还请大家见谅.指教! 注意:我省略了其中的 ...

  8. (zt)OpenGL中的Alpha测试,深度测试,模板测试,裁减测试

    转自http://www.cppblog.com/flashboy/archive/2009/09/01/94974.html 大家好.现在因为参加工作的关系,又是长时间没有更新.趁着国庆的空闲,总算 ...

  9. Learn OpenGL(七)——OpenGL中使用着色器的基本步骤及GLSL渲染简单示例

    OpenGL着色语言(OpenGL Shading Language,GLSL)是用来在OpenGL中着色编程的语言,是一种具有C/C++风格的高级过程语言,同样也以main函数开始,只不过执行过程是 ...

最新文章

  1. watch TV online for free
  2. 删除ctrl alt del更改密码
  3. Java网络编程——9.服务器Socket
  4. 芯灵思Sinlinx A64开发板 Linux内核等待队列p
  5. 软件官网与memcached介绍
  6. EM算法和GMM(下)
  7. 2017年8个最流行的Web编程趋势
  8. recovery编译问题汇总
  9. oracle建库及plsql建表空间的用法
  10. 实战手记:让百万级数据瞬间导入SQL Server
  11. 从土地利用规划到国土空间规划的一些思考
  12. 审车按月还是日期_大额存单,应该选择按月付息还是到期一次性还本付息?
  13. 【linux】常用网络操作
  14. 怎样用eclipse新建一个android项目?用eclipse新建android项目出错?请看下面
  15. 组态王bitset用法_组态王使用问题解答6
  16. echarts 曲线面积对比图
  17. Windows内核原理与实现之Windows设备驱动程序
  18. 2010Excel分列操作的一些问题进行分享
  19. 汇编实现数字的输入与输出
  20. 网络安全初创企业Illumio融资1.25亿美元 摩根领投

热门文章

  1. NFV落地开花,CT厂商渐获运营商青睐
  2. Intel SGX开发者参考书(四)—— Enclave开发基础(三)
  3. Android中TextView的SetText()方法注意事项
  4. 云堡垒机和传统堡垒机对比
  5. 知乎热议!谷歌员工,在家办工要降薪25%?
  6. Java实现图片上传到服务器
  7. mysql查询条件为不等于某个值时,null 查询不到?
  8. TQ2440 mifi驱动及开机自动连接wifi全过程
  9. linux内核Kmalloc - GFP_ATOMIC - GFP_KERNEL - GFP_USER
  10. 将波旁威士忌的整洁Mixins提升到新的水平