openGL 深度测试与透明度设置
深度缓冲区原理
深度缓冲区原理就是把一个距离观察平面(近裁剪面)的深度值(或距离)与窗口中的每个像素相关联。
首先,使用glClear(GL_DEPTH_BUFFER_BIT),把所有像素的深度值设置为最大值(一般是远裁剪面)。
然后,在场景中以任意次序绘制所有物体。硬件或者软件所执行的图形计算把每一个绘制表面转换为窗口上一些像素的集合,此时并不考虑是否被其他物体遮挡。
其次,OpenGL会计算这些表面和观察平面的距离。如果启用了深度缓冲区,在绘制每个像素之前,OpenGL会把它的深度值和已经存储在这个像素的深度值进行比较。新像素深度值<原先像素深度值,则新像素值会取代原先的;反之,新像素值被遮挡,他颜色值和深度将被丢弃。
为了启动深度缓冲区,必须先启动它,即glEnable(GL_DEPTH_TEST)。每次绘制场景之前,需要先清除深度缓冲区,即glClear(GL_DEPTH_BUFFER_BIT),然后以任意次序绘制场景中的物体。
openGL里常出现深度测试,一直不清楚。今天就来弄清楚。
(1)什么是深度?
深度其实就是该象素点在3d世界中距离摄象机的距离(绘制坐标),深度缓存中存储着每个象素点(绘制在屏幕上的)的深度值!
深度值(Z值)越大,则离摄像机越远。
深度值是存贮在深度缓存里面的,我们用深度缓存的位数来衡量深度缓存的精度。深度缓存位数越高,则精确度越高,目前的显卡一般都可支持16位的Z Buffer,一些高级的显卡已经可以支持32位的Z Buffer,但一般用24位Z Buffer就已经足够了。
(2)为什么需要深度?
在不使用深度测试的时候,如果我们先绘制一个距离较近的物体,再绘制距离较远的物体,则距离远的物体因为后绘制,会把距离近的物体覆盖掉,这样的效果并不是我们所希望的。而有了深度缓冲以后,绘制物体的顺序就不那么重要了,都能按照远近(Z值)正常显示,这很关键。
实际上,只要存在深度缓冲区,无论是否启用深度测试,OpenGL在像素被绘制时都会尝试将深度数据写入到缓冲区内,除非调用了glDepthMask(GL_FALSE)来禁止写入。这些深度数据除了用于常规的测试外,还可以有一些有趣的用途,比如绘制阴影等等。
(2)启用深度测试
使用 glEnable(GL_DEPTH_TEST);
在默认情况是将需要绘制的新像素的z值与深度缓冲区中对应位置的z值进行比较,如果比深度缓存中的值小,那么用新像素的颜色值更新帧缓存中对应像素的颜色值。
但是可以使用glDepthFunc(func)来对这种默认测试方式进行修改。
其中参数func的值可以为GL_NEVER(没有处理)、GL_ALWAYS(处理所有)、GL_LESS(小于)、GL_LEQUAL(小于等于)、GL_EQUAL(等于)、GL_GEQUAL(大于等于)、GL_GREATER(大于)或GL_NOTEQUAL(不等于),其中默认值是GL_LESS。
一般来将,使用glDepthFunc(GL_LEQUAL);来表达一般物体之间的遮挡关系。
(3)启用了深度测试,那么这就不适用于同时绘制不透明物体。
备注:
绘制半透明物体时,需注意:在绘制半透明物体时前,还需要利用glDepthMask(GL_FALSE)将深度缓冲区设置为只读形式,否则可能出现画面错误。为什么呢,因为画透明物体时,将使用混色,这时就不能继续使用深度模式,而是利用混色函数来进行混合。这一来,就可以使用混合函数绘制半透明物体了。
也许你迫不及待的想要绘制一个三维的带有半透明物体的场景了。但是现在恐怕还不行,还有一点是在进行三维场景的混合时必须注意的,那就是深度缓冲。
深度缓冲是这样一段数据,它记录了每一个像素距离观察者有多近。在启用深度缓冲测试的情况下,如果将要绘制的像素比原来的像素更近,则像素将被绘制。否则, 像素就会被忽略掉,不进行绘制。这在绘制不透明的物体时非常有用——不管是先绘制近的物体再绘制远的物体,还是先绘制远的物体再绘制近的物体,或者干脆以 混乱的顺序进行绘制,最后的显示结果总是近的物体遮住远的物体。
然而在你需要实现半透明效果时,发现一切都不是那么美好了。如果你绘制了一个近距离的半透明物体,则它在深度缓冲区内保留了一些信息,使得远处的物体将无法再被绘制出来。虽然半透明的物体仍然半透明,但透过它看到的却不是正确的内容了。
要 解决以上问题,需要在绘制半透明物体时将深度缓冲区设置为只读,这样一来,虽然半透明物体被绘制上去了,深度缓冲区还保持在原来的状态。如果再有一个物体 出现在半透明物体之后,在不透明物体之前,则它也可以被绘制(因为此时深度缓冲区中记录的是那个不透明物体的深度)。以后再要绘制不透明物体时,只需要再 将深度缓冲区设置为可读可写的形式即可。嗯?你问我怎么绘制一个一部分半透明一部分不透明的物体?这个好办,只需要把物体分为两个部分,一部分全是半透明 的,一部分全是不透明的,分别绘制就可以了。
即使使用了以上技巧,我们仍然不能随心所欲的按照混乱顺序来进行绘制。必须是先绘制不透明的物体,然 后绘制透明的物体。否则,假设背景为蓝色,近处一块红色玻璃,中间一个绿色物体。如果先绘制红色半透明玻璃的话,它先和蓝色背景进行混合,则以后绘制中间 的绿色物体时,想单独与红色玻璃混合已经不能实现了。
总结起来,绘制顺序就是:首先绘制所有不透明的物体。如果两个物体都是不透明的,则谁先谁后 都没有关系。然后,将深度缓冲区设置为只读。接下来,绘制所有半透明的物体。如果两个物体都是半透明的,则谁先谁后只需要根据自己的意愿(注意了,先绘制 的将成为“目标颜色”,后绘制的将成为“源颜色”,所以绘制的顺序将会对结果造成一些影响)。最后,将深度缓冲区设置为可读可写形式。
调用glDepthMask(GL_FALSE);可将深度缓冲区设置为只读形式。调用glDepthMask(GL_TRUE);可将深度缓冲区设置为可读可写形式。
一 些网上的教程,包括大名鼎鼎的NeHe教程,都在使用三维混合时直接将深度缓冲区禁用,即调用glDisable(GL_DEPTH_TEST);。这样 做并不正确。如果先绘制一个不透明的物体,再在其背后绘制半透明物体,本来后面的半透明物体将不会被显示(被不透明的物体遮住了),但如果禁用深度缓冲, 则它仍然将会显示,并进行混合。NeHe提到某些显卡在使用glDepthMask函数时可能存在一些问题,但可能是由于我的阅历有限,并没有发现这样的 情况。
那么,实际的演示一下吧。我们来绘制一些半透明和不透明的球体。假设有三个球体,一个红色不透明的,一个绿色半透明的,一个蓝色半透明的。红色最远,绿色 在中间,蓝色最近。根据前面所讲述的内容,红色不透明球体必须首先绘制,而绿色和蓝色则可以随意修改顺序。这里为了演示不注意设置深度缓冲的危害,我们故 意先绘制最近的蓝色球体,再绘制绿色球体。
openGL 深度测试与透明度设置相关推荐
- 如果将OpenGL的MVP矩阵设置为单位阵
如果将OpenGL的MVP矩阵设置为单位阵,会发生什么? opengl的几个坐标空间: object space-> eye space-> clip space -> NDC -& ...
- OpenGL 深度测试depth test 的实例
OpenGL 深度测试depth test 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #includ ...
- android自定义view背景透明度,Android 背景透明度设置总结
一.写在前面的 在需求上遇到背景设置透明度还是比较常见的,设置透明度有几种方式,但是不同的场景应用下,不同的方式可能会出现一些问题.针对开发过程中的需求做以下总结. 二.先看效果图 图1. 图2. 图 ...
- Unity-Live2d(模型参数设置,当前参数保存与恢复所保存参数, 部分位置透明度设置,自动眨眼)
Unity-Live2D 概述:这是我学习Unity中Live2d的相关操作的一个笔记,欢迎各位同好和大牛的指点.(参考siki学院出的视频学的) 模型参数设置 先来说一下这个模型参数是个什么东西,之 ...
- CSS中的透明度设置
CSS3中透明度设置 1.两种设置方式 语法 background-color:rgba(r,g,b,a):r:红 g:绿 b:蓝 a:透明度 background-color:rgb(r,g,b) ...
- cocos 设置canvas透明导致 正常节点透明度设置效果异常
cocos 设置canvas透明导致 正常节点透明度设置效果异常 根据论坛回答记录 1.图片 必须用 one,one minus src alpha,否则 web 端的贴图渲染时会莫名其妙和 canv ...
- windows10任务栏透明度设置
windows10任务栏透明度设置 win+i,打开Windows设置,点击个性化,点击颜色,将透明效果打开. win+R,输入[regedit],打开注册表 路径改成: 计算机 \HKEY_CURR ...
- html中透明度100是,CSS 透明度设置方法及常见问题解析
你对 CSS 中的半透明颜色可能已经有了基础的了解,CSS透明算得上是一种相当流行的技术,但在跨浏览器支持上,对于开发者来说,可以说是一件令人头疼的事情.目前还没有一个通用方法,以确保透明度设置可以在 ...
- css透明度设置--背景透明但文字不透明
1.问题提出:很多情况下,我们可能需要给页面上的某些元素添加一个背景,然后通过虚化背景实现有个透明层的效果.需要达到的效果如下: 2.预想的处理方式:在景点卡的div元素设置一个白色背景,并设置白色背 ...
- 兔子--背景透明度设置
背景透明度设置:ee是透明度 android:background="#ee6c6c6c"
最新文章
- 电话双音频拨码信号采集
- 做好FPGA设计的五项基本功 (Z)
- covid 19如何重塑美国科技公司的工作文化
- 包管理工具conda极简教程
- HDOJ HDU 2088 Box of Bricks ACM 2088 IN HDU
- python能做什么项目-适合Python 新手的5大练手项目,你练了么?
- 自己把握系统安全,Windows自启动程序的十大藏身之所
- 英特尔宣布CEO换帅,消息一出股价大涨
- 计算机播放音乐自录,怎么录制电脑上正在播放的视频音频
- SpringCloud版本Hoxton SR5 --- 第二讲:eureka 、eureka与zookeeper的区别与使用场景。
- Parameter 1 of constructor in com.xxx.controller.Xxx required a bean of type
- 青少年编程平台系统设计与实现
- Rust权威指南 全书笔记
- 生长算法实现点集的三角剖分(Python(Tkinter模块))
- 求素数/质数 简单Java算法
- 华为fusion超融合虚拟服务器,华为FusionCube超融合:满足客户未来一切云化所需...
- 苹果AR/VR设备或定价2000美元 或命名Apple Vision
- 号称下一代监控系统,到底有多牛逼!
- pageoffice 骑缝章_PageOffice V4.0
- html中table标签及其它标签居中