颜色的混合在现实世界中非常常见,例如隔着有色玻璃观看物体,此时在观察者严重呈现出来物体的颜色就是玻璃的颜色和物体的颜色的混合。

OpenGL在RGBA颜色模式下使用函数glenable(GL_BLEND)开启混色功能,使用glDisable(GL_BLEDN)关闭混色功能。混色功能开启之后,最终显示的颜色的RGBA分量是两个颜色各自的RGBA分量共同决定的。

源因子和目标因子

需要混合的两个颜色一个称为源颜色,一个称为目标颜色,而定义一个颜色是源颜色还是目标颜色的唯一依据是:先绘制的颜色是“目标颜色”,后绘制的是“源颜色”,跟物体的深度无关。

混色运算的实现是源颜色和目标颜色分别乘上一个“源因子”和“目标因子”后经过算术运算实现的。使用函数glBlenFunc来设置源因子和目标因子。函数原型是:

void   glBlendFunc (GLenum sfactor, GLenum dfactor);

第一个参数用于设置源因子,第二个参数用于设置目标因子,这两个参数可以是多种值,下边是一些比较常用的设置:

  • GL_ZERO:表示使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算。
  • GL_ONE:  表示使用1.0作为因子,实际上相当于完全的使用了这种颜色参与混合运算。
  • GL_SRC_ALPHA:表示使用源颜色的alpha值来作为因子。
  • GL_DST_ALPHA:表示使用目标颜色的alpha值来作为因子。
  • GL_ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。
  • GL_ONE_MINUS_DST_ALPHA:表示用1.0减去目标颜色的alpha值来作为因子。

如果不对源因子和目标因子进行设置,默认情况是采用设置glBlendFunc(GL_ONE,GL_ZERO),即完全使用源颜色,覆盖目标颜色。

最常用的设置是glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);这种情况表示源颜色乘以自身的Alpha值,目标颜色乘以1.0减去源颜色的Alpha值,这样一来,源颜色的Alpha值越大,则产生的新颜色中源颜色所占比例就越大,而目标颜色所占比例则减少。这种情况相当于使用源颜色Alpha的数值大小简单模拟玻璃(源颜色)的不透明度。

深度缓存

深度缓存记录了每一个像素距离观察点的距离,启用深度缓存功能之后,程序会忠实的执行只绘制最上层像素点,覆盖比最上层像素点深度更深的像素点,而颜色透明度则被忽略。

要解决这一问题,需要在绘制半透明模型之前“冻结”深度缓存区,将深度缓存区设置为只读的,这样一来,虽然半透明物体被绘制上去了,深度缓存区还保持在原来的状态,即当前绘制的模型的深度不会影响到深度缓冲区的状态。等绘制完所有需要混色的模型之后,再把深度缓存区设置为可读可写状态。

调用glDepthMask(GL_FALSE),可以把深度缓存区设置为只读形式,使用glDepthMask(GL_TRUE)将深度缓存区设置为可读可写形式。

示例

以下程序的功能是在三维空间中绘制3个平面,颜色分别是RGB,R在最下边,G在中间,B在最上层,实现3个颜色的混色,可以看到,RGB三者重合的区域混合出了白色:

   

   

程序代码:

#include <glut.h> 

GLfloat angle = 0.0f;

void myDisplay(void)
{
//List 1 定义模型视图矩阵
if(!glIsList((GLuint)1))
{
glNewList(1,GL_COMPILE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60,1,2,50); glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,-10,10,0,0,0,0,1,0);
glEndList();
} glEnable(GL_DEPTH_TEST); //深度缓存
glEnable(GL_BLEND); //开启混色 //设置源因子和目标因子
glBlendFunc(GL_ONE,GL_ONE); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glCallList(1);
glDepthMask(GL_FALSE); //设置深度缓冲区为只读模式
glRotatef(angle,1,0,0);
glRotatef(angle,0,1,0);
glRotatef(angle,1,0,1); glBegin(GL_QUADS);
//最底层的面 先绘制的是目标,红色框
glColor4f(1,0,0,0.5);
glVertex3f(-2,-5,-5);
glVertex3f(8,-5,-5);
glVertex3f(8,5,-5);
glVertex3f(-2,5,-5); //中间的面,第二绘制的源1 绿色框
glColor4f(0,1,0,0.5);
glVertex3f(-4.5,-5,-2);
glVertex3f(5.5,-5,-2);
glVertex3f(5.5,5,-2);
glVertex3f(-4.5,5,-2); //顶层的面,第三绘制的源2 蓝色框
glColor4f(0,0,1,0.5);
glVertex3f(-7,-5,1);
glVertex3f(3,-5,1);
glVertex3f(3,5,1);
glVertex3f(-7,5,1); glEnd();
glDepthMask(GL_TRUE); //恢复深度缓冲区读写
glutSwapBuffers();
} void myIdle(void)
{
angle+=0.2f;
if( angle >= 360.0f )
angle = 0.0f;
myDisplay();
} int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowPosition(200, 200);
glutInitWindowSize(400, 400);
glutCreateWindow("OpenGL");
glutDisplayFunc(&myDisplay);
glutIdleFunc(&myIdle);
glutMainLoop();
return 0;
}

OpenGL(九) 三维混色和深度缓存设置的更多相关文章

  1. OpenGL透明与混色效果

    一.理论讲解 在OpenGL中,物体透明技术通常被叫做混合(Blending). 透明是物体(或物体的一部分)非纯色而是混合色,这种颜色来自于不同浓度的自身颜色和它后面的物体颜色. 一个有色玻璃窗就是 ...

  2. 基于OpenGL的三维曲面动态显示实现

    在使用Visual C++的MFC AppWizard建立应用程序框架后,生成了多个类,与OpenGL编程相关的类是视图类,主要的显示任务都在其中完成. 1.基于OpenGL绘图的基本设置 1.1 设 ...

  3. 前端每日实战:114# 视频演示如何用纯 CSS 和混色模式创作一个 loader 动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/MqYroW 可交互视频 此视频是可 ...

  4. OpenGL之抗锯齿 以及 线宽的设置

    转自原文 OpenGL之抗锯齿 以及 线宽的设置 抗锯齿 1.线的抗锯齿 glEnable(GL_LINE_SMOOTH); //启用 glHint(GL_LINE_SMOOTH,GL_NICEST) ...

  5. PHP imagealphablending - 设定图像的混色模式

    imagealphablending — 设定图像的混色模式.高佣联盟 www.cgewang.com 语法 bool imagealphablending ( resource $image , b ...

  6. 基于图形学混色问题OpenGl的收获

    void myDisplay(void) {glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_B ...

  7. QT OpenGL绘制三维图形(立方体、圆柱体、圆锥、球体、圆环等等)

    本文使用QGLWidget来绘制各种三维基本图形,包括立方体.圆柱体.圆锥.球体.圆环等等,涉及包括基本绘制以及上色.纹理.旋转等操作. 使用的软件版本:QT5.12 + QT Creater4.8. ...

  8. opengl绘制三维人物luweiqi

    素材中有四个.bmp格式的纹理文件和一个.txt的模型参数文件 文件格式说明: 纹理文件数量 纹理文件1(字符串)//.bmp 纹理文件2(字符串) 纹理文件3(字符串) . . . 材质数量 amb ...

  9. OPenGL中三维图形的矩阵变换

    对于二维的图形开发,拿简单的图片显示来说,我们主要的目的:就是在一块显示buffer中,不停的把每个像素进行着色,然后就可以绘制出来了.为了速度,很多其他的加速方法,但原理基本上就是这样了. 很直观, ...

随机推荐

  1. 随手可得的Application对象

    在Android的开发其中,Application和Context对象应该是我们接触最多的对象了,特别是Context对象. 当我们在某个Activity或者Service其中时,因为它们本身就是Co ...

  2. 【转】HTML5移动端最新兼容问题解决方案

    1.安卓浏览器看背景图片,有些设备会模糊. 用同等比例的图片在PC机上很清楚,但是手机上很模糊,原因是什么呢? 经过研究,是devicePixelRatio作怪,因为手机分辨率太小,如果按照分辨率来显 ...

  3. GitHub的repository的相关操作

    原文地址 https://www.jianshu.com/p/038e8ba10e45 1.准备工作 a.有自己的GitHub账号(https://github.com/)b.在自己本地有安装git软 ...

  4. redis文档翻译_key设置过期时间

    Available since 1.0.0.    使用開始版本号1.01 Time complexity: O(1)  时间复杂度O(1) 出处:http://blog.csdn.net/colum ...

  5. android SQLite 使用实例

    Android作为眼下主流的移动操作系统,全然符合SQLite占用资源少的优势,故在Android平台上,集成了一个嵌入式关系型数据库-SQLite.假设想要开发 Android 应用程序,须要在 A ...

  6. Java NIO学习笔记之基本概念

    一.缓冲区操作 缓冲区,以及缓冲区如何工作,是所有 I/O 的基础.所谓"输入/输出"讲的无非就是把数据移进或移出缓冲区. 进程使用 read( )系统调用,要求其缓冲区被填满.内 ...

  7. Windows环境搭建Web自己主动化測试框架Watir(基于Ruby)

    web自己主动化測试一直是一个比較迫切的问题 图1-1 须要安装的工具 http://railsinstaller.org/ 由于安装Ruby还须要用到其它的一些开发工具集.所以建议从站点http:/ ...

  8. [Angular Directive] 3. Handle Events with Angular 2 Directives

    A @Directive can also listen to events on their host element using @HostListener. This allows you to ...

  9. dot-- 资源汇总

    http://graphviz.org/doc/info/attrs.htmlhttp://graphs.grevian.org/http://graphs.grevian.org/exampleht ...

  10. JBoss AS 7之初步了解(The Return Of The King)

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvam9obl9mX2xhdQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...