OpenGL(九) 三维混色和深度缓存设置
颜色的混合在现实世界中非常常见,例如隔着有色玻璃观看物体,此时在观察者严重呈现出来物体的颜色就是玻璃的颜色和物体的颜色的混合。
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(九) 三维混色和深度缓存设置的更多相关文章
- OpenGL透明与混色效果
一.理论讲解 在OpenGL中,物体透明技术通常被叫做混合(Blending). 透明是物体(或物体的一部分)非纯色而是混合色,这种颜色来自于不同浓度的自身颜色和它后面的物体颜色. 一个有色玻璃窗就是 ...
- 基于OpenGL的三维曲面动态显示实现
在使用Visual C++的MFC AppWizard建立应用程序框架后,生成了多个类,与OpenGL编程相关的类是视图类,主要的显示任务都在其中完成. 1.基于OpenGL绘图的基本设置 1.1 设 ...
- 前端每日实战:114# 视频演示如何用纯 CSS 和混色模式创作一个 loader 动画
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/MqYroW 可交互视频 此视频是可 ...
- OpenGL之抗锯齿 以及 线宽的设置
转自原文 OpenGL之抗锯齿 以及 线宽的设置 抗锯齿 1.线的抗锯齿 glEnable(GL_LINE_SMOOTH); //启用 glHint(GL_LINE_SMOOTH,GL_NICEST) ...
- PHP imagealphablending - 设定图像的混色模式
imagealphablending — 设定图像的混色模式.高佣联盟 www.cgewang.com 语法 bool imagealphablending ( resource $image , b ...
- 基于图形学混色问题OpenGl的收获
void myDisplay(void) {glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_B ...
- QT OpenGL绘制三维图形(立方体、圆柱体、圆锥、球体、圆环等等)
本文使用QGLWidget来绘制各种三维基本图形,包括立方体.圆柱体.圆锥.球体.圆环等等,涉及包括基本绘制以及上色.纹理.旋转等操作. 使用的软件版本:QT5.12 + QT Creater4.8. ...
- opengl绘制三维人物luweiqi
素材中有四个.bmp格式的纹理文件和一个.txt的模型参数文件 文件格式说明: 纹理文件数量 纹理文件1(字符串)//.bmp 纹理文件2(字符串) 纹理文件3(字符串) . . . 材质数量 amb ...
- OPenGL中三维图形的矩阵变换
对于二维的图形开发,拿简单的图片显示来说,我们主要的目的:就是在一块显示buffer中,不停的把每个像素进行着色,然后就可以绘制出来了.为了速度,很多其他的加速方法,但原理基本上就是这样了. 很直观, ...
随机推荐
- ping localhost 没反应解决方式
今天在搭建导师公司的spark的集群的时候须要有一台机器须要ssh 到自己.可是运行以下两条命令后发现没有反应 ping localhost ping 127.0.0.1 之后问了下别人,发现是/et ...
- js进阶 11-19 jquery如何查找选择器的第一个父亲元素和第一个定位的父元素
js进阶 11-19 jquery如何查找选择器的第一个父亲元素和第一个定位的父元素 一.总结 一句话总结:closest()方法获得匹配选择器的第一个祖先元素,从当前元素开始沿 DOM 树向上.of ...
- Android多线程研究(5)——线程之间共享数据
一.如果是每个线程都执行相同的代码,则可以使用同一个Runnable来实现共享 public class MultiThreadShareData { public static void main( ...
- php 图片加水印文字水印
/*给图片加文字水印的方法*/ $dst_path = 'http://f4.topitme.com/4/15/11/1166351597fe111154l.jpg';//保证路径正确 $dst = ...
- WP8.1开发:简单的天气预报应用
今天小梦给大家分享一个简单的天气预报应用源码:调用的是百度API.整个应用都没有什么难点.只是一个简单的网络请求和json数据处理.在WP8.1有小娜的情况下,天气预报应用还有意义吗?我认为还是有点意 ...
- ArcEngine创建IElement简单例子
转自IT-GIS终结者原文ArcEngine创建IElement简单例子 代码下载地址:http://files.cnblogs.com/ogis/MapControlApplication2.rar ...
- PHP移动互联网开发笔记(5)——基础函数库
一.数学函数库 ● floor 舍一取整(向下取整) float floor (float $value); <?php echo(floor(0.60)."<br>&qu ...
- Android 三种方式实现自定义圆形进度条ProgressBar
一.通过动画实现 定义res/anim/loading.xml如下: <?xml version="1.0" encoding="UTF-8"?> ...
- [iOS]iOS开发人员账号申请与注冊流程
郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意.重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...
- angularjs1.6 制作流程图,启动流程,流程设置
话不多说,我们先来看一下效果图: 点击添加按扭要增加一个,可以叠加 代码如下: server.server().addprojectrooml({ type: , processName: $scop ...