(这里需要先完成demo5)
深度缓冲(Depth buffer)
深度缓冲
,也被叫做Z-缓冲
,是用来存储图形所有片段的深度信息,在进行3D图形的绘制时,每当计算一个图形片段,GLEW便会自动生成一个深度
作为这个片段的Z值(深度)
,而当这个片段将要被渲染时,OpenGL会将这个片段的深度与Z-深度
进行比较,通过比较,如果这个片段在其他片段的后面,那么这个片段将会被丢弃,不再渲染,也就不会再出现在屏幕上,反之,则渲染在屏幕上。
上述的这个过程称之为深度测试(Depth Testing)
(话说外国人的取名思路真是新奇 0.0)
深度测试(Depth Testing)
在OpenGL中,深度测试
是默认关闭的(即在上下文
中深度测试
是关闭的属性),如果想要使用深度测试的功能,需要瘦瘦去打开它
glEnable(GL_DEPTH_TEST);
也正因为开启了深度测试,所以在重新渲染其他图形之前,我们需要清空深度缓冲区
中间的数据,不然后续的深度测试
会有影响.
glClear(GL_DEPTH_BUFFER_BIT);
深度缓冲区
中的每一个缓冲都是有有精度的,通常,深度缓冲
的精度以16、24、32位的float形式进行存储,一般情况下,都是以24位的精度进行存储的。在早期的游戏中,是以16位的精度进行存储的,这样会产生一个问题,当画面数据过于庞大时,深度缓冲区
中的缓存值会存在相同的数据(数据特别大的时候),这时候OpenGL就不再能分辨正面
和背面
,而产生类似于穿模
的状况,这时候提升精度就解决这个问题了。
但是并不是精度越高就越好,精度越高,单个深度缓冲占据的空间就越大,处理起来就越复杂,对配置的要求就越高
深度测试函数
(在深度测试启用时,深度测试函数才会起效果。)
OpenGL在进行深度测试
时,会通过特定的深度测试函数
来进行数据的运算并更新深度缓冲
,我们可以调用glDepthFunc
函数来设置比较运算符(或者说深度函数(Depth Function)
)
//GL_ALWAYS 深度函数
glDepthFunc(GL_ALWAYS);
深度函数
可以改为下表中的函数(实际上每个深度函数都是一系列的计函数计算)
深度值精度
深度缓冲
是由一系列0.0-1.0的深度值所构成的,这个值可以是投影平截头体的近平面(Near)和远平面(Far)之间的任何值,通过片段自身的z坐标与near和far,可以粗略的计算出这个片段的深度值
,基于OpenGL,这个值位于0.0-1.0之间,,这里的near和far是之前设置投影矩阵的时候设置的。
但是这个公式是线性的,实际上几乎永远不会使用这样的数学模型,因为我们需要的是,在z离的很近的时候要提供足够的精度以供OpenGL渲染视图,在z离的很远的时候只需要很小的精度用于判断是否需要抹去,也就是需要设置为 的数学模型,因此,可以考虑将深度值
的计算模型替换为 ,这样就能够满足我们的条件了。
深度冲突
深度冲突(Z-fighting)
是指两个平面或三角形很紧密的平行排列在一起时(理解为重合吧),深度精度不足以去判断它们的深度,所以深度测试并不能判断哪个应该显示,哪个应该抹去,所表现出来的结果是,两个片段不断的重复交替出现消失(玩CS的小伙伴应该遇到过很多次了),这种现象并不能够完全的避免,就算是提高了精度值,在数据量足够庞大的时候依然有可能会出现这样的问题(就算1080的不够,还有2K,4K,甚至未来的8K,16K的游戏呢 =。=),对于这种情况,有一些技巧可以防止其产生。
- 在放置物体时,不要讲物体放置的太靠近
- 适量的去调整近平面的位置
- 使用更更高的精度(但会对性能产生影响,毕竟计算的开销更大)
基本上,将上面的三种方式结合起来使用,也能够解决目前的深度冲突
问题了,以后技术更新了,自然会有其他的方式来解决这个问题~
网友评论