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

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. <h2>1. mongodb介绍</h2>

    1. mongodb介绍 2. ppt下载地址 http://download.csdn.net/detail/u014285882/7807105 阅读全文 本文已收录于下面专栏: mongodb使 ...

  2. Android自定义组件系列【11】——实现3D立体旋转效果

    今天在网上看到一篇文章写关于Android实现3D旋转(http://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt2/inde ...

  3. 中小研发团队架构实践之分布式协调器.Net版ZooKeeper

    原文:中小研发团队架构实践之分布式协调器.Net版ZooKeeper 一.ZooKeeper是什么  Apache ZooKeeper是由Apache Hadoop的子项目发展而来,于2010年11月 ...

  4. Android JNI编程(五)——C语言的静态内存分配、动态内存分配、动态创建数组

    版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:什么是静态内存什么又是动态内存呢? 静态内存:是指在程序开始运行时由编译 ...

  5. Uncaught SyntaxError: Invalid regular expression flags(看页面源代码)

    Uncaught SyntaxError: Invalid regular expression flags(看页面源代码) 一.总结 js或者jquery方面的错误看页面源代码,一下子错误就很清晰了 ...

  6. http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误)

    http500:服务器内部错误案例详解(服务器代码语法错误或者逻辑错误) 一.总结 服务器内部错误可能是服务器中代码运行的时候的语法错误或者逻辑错误 二.http500:服务器内部错误案例详解 只是一 ...

  7. Ubuntu,右键->在终端中打开(apt-install,或者手动增加右键菜单)

    方法一: sudo apt-get install nautilus-open-terminal 然后重启 方法二: Ubuntu中,默认右键菜单中没有“在终端中打开”.要想添加此菜单,可以在主目录中 ...

  8. mysqlsla slow-query常用用法

    mysqlsla -lt slow /data/mysql/testdb2-slow.log -sf -top 20 -sort t_sum > /data/mysql/my_testdb2-s ...

  9. Git恢复删除或修改的文件 ls-files

    一.git ls-files -d 查看删除了的文件 1.查看当前状态可以看到删除了一个index.js: git status image.png 2.查看当前项目中删除了的文件 git ls-fi ...

  10. [Node.js] Identify memory leaks with nodejs-dashboard

    In this lesson, I introduce a memory leak into our node.js application and show you how to identify ...