关于深度测试和正背面剔除

在绘制3D场景时,为了尽可能的逼真需要有近大远小的效果,而且可能会出现互相遮盖的情况。例如上图前面甜点会遮住后面的一部分,这种情况下为了提高渲染性能我们就不应该渲染被遮住的那部分,那如何处理呢?

正背面剔除

以常见的正方体为例,在任何一个角度方向上可见的最多3个面。如果以我们看见的角度为正面,看不见的为背面,也就是说我们只要渲染看见的那部分就可以了。

OpenGL可以做到检查所有正面朝向观察者的面,并渲染它们,背后朝向的面则不再渲染,从而节约片元着色器的性能。

1. 首先,我们需要告诉OpenGL那个面为正面

OpenGL是通过分析顶点顺序来区分正背面的,默认情况下是按照逆时针顶点连接顺序的三⻆形⾯为正面,按照顺时针顶点连接顺序的三角形⾯为背面。

需要注意的是,正背面是由顶点定义顺序和观察者方向共同决定的,随着观察者角度方向的改变,正背面也可能改变。

2. 正背面剔除相关代码

开启表面剔除(默认背面剔除)

void glEnable(GL_CULL_FACE);

关闭表面剔除(默认背面剔除)

void glDisable(GL_CULL_FACE);

用户选择剔除哪个面(正面/背面) 

void glCullFace(GLenum mode);

mode参数为: GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默 认GL_BACK

用户指定绕序哪个为正⾯

glFrontFace(GL_CW);

mode参数为: GL_CW,GL_CCW,默认值:GL_CCW

例如,剔除正面实现(1)

glCullFace(GL_BACK); 

glFrontFace(GL_CW);

例如,剔除正⾯面实现(2) 

glCullFace(GL_FRONT);

如果是封面图的情况下,正背面剔除还远远不够用,接下来还需要加入深度测试哦。

深度测试

所谓深度,就是该像素点在3D世界中距离摄像机的距离,z值。也可以说是三维坐标系中的Z轴距离。

深度测试,深度缓冲区(DepthBuffer)和颜色缓冲区(ColorBuffer)是对应的。颜色缓冲区存储像素的颜色信息,而深度缓冲区存储像素的深度信息。在决定是否绘制一个物体表面时,首先要将表面对应的像素的深度值与当前深度缓冲区中的值进行比较。如果大于深度缓冲区中的值,则丢弃这部分,否则利用这个像素对应的深度值和颜色值,分别更新深度缓冲区和颜色缓冲区,这个过程就是“深度测试”。

深度缓冲区,就是一块内存区域(一般由窗口管理系统,GLFW创建),专门存储绘制在屏幕上的每个像素点的深度值,深度值越大距离摄像机越远。只要存在深度缓冲区,OpenGL就会把像素的深度值写入缓冲区中,可以调用glDepthMask(GL_FALSE)来禁止写入。

补充信息

深度值计算,深度值一般由16位,24位或者32位值表示,通常是24位。位数越高,深度值越精确。深度值范围在[0,1]之间,值越小越小越靠近观察者,反之亦然。

视图空间中的z值可以在投影平头截体的近平面和远平面之间的任何值。因此我们需要一些方法把这些视图空间z值转换到[0,1]的范围内,下面的线性方程把z值转换为0.0和1.0之间的值:

 注:far和near是提供到投影矩阵设置可见视图截锥的远近值


使用深度测试

开启深度测试

glEnable(GL_DEPTH_TEST);

在绘制场景前,最好清除颜色缓冲区和深度缓冲区

gl_Clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

还可以指定深度测试判断模式

void gl_Depth_Func(GLEnum mode);

ZFighting闪烁问题

开启深度测试之后确实可以帮助我们节约很多性能,但是也会有一些令人头疼的问题ZFighting闪烁。由于深度缓冲区精度的限制,对于深度相差非常小的情况下OpenGL 就无法正确判断出两者的深度值,会导致渲染的结果无法预测,显示出来的图像交错闪烁(时而渲染出绿色,时而渲染出红色,无法确定,交错闪烁)。

一. 启用Polygon Offset 方式解决

解决方法:让深度值之间产生间隔,避免干涉。就是在执行深度测试之前对物体的深度值做一些细微的增加。

开启Polygon Offset

glEnable(GL_POLYGON_OFFSET_FILL)

参数:

对应光栅化模式 GL_POINT:

GL_POLYGON_OFFSET_POINT 

对应光栅化模式 GL_LINE:

GL_POINTGL_POLYGON_OFFSET_LINE

对应光栅化模式 GL_FILL:

GL_POLYGON_OFFSET_FILL

二. 指定偏移量

void glPolygonOffset(Glfloat factor,Glfloat units);

一般将factor和units设置为-1.0

每个Fragment 的深度值都会增加如下所示的偏移量:

Offset = ( m * factor ) + ( r * units);

m : 多边形的深度的斜率的最大值,理解⼀个多边形越是与近裁剪⾯平行,m 就越接近于0.

r : 能产生于窗⼝坐标系的深度值中可分辨的差异最小值.r 是由具体OpenGL平台指定的一个常量.

一个⼤于0的Offset 会把模型推到离你(摄像机)更更远的位置,相应的一个⼩小于0的Offset 会把模型拉近

三. 关闭Polygon Offset

glDisable(GL_POLYGON_OFFSET_FILL);

只要glEnable开启过,就需要glDisable关闭


最后,不要将两个物体靠的太近,避免渲染时三角形叠在⼀起。这种⽅式要求对场景中物体插入一个少量的偏移,那么就可能避免ZFighting现象;

尽可能将近裁剪面设置得离观察者远⼀些,在近裁剪平面附近,深度的精确度是很高的,因此尽可能让近裁剪面远一些的话,会使整个裁剪范围内的精确度变高一些。但是这种⽅式会使离观察者较近的物体被裁减掉,因此需要调试好裁剪⾯面参数;

使⽤更高位数的深度缓冲区,通常使⽤的深度缓冲区是24位的,现在有一些硬件使⽤32位的缓冲区,使精确度得到提⾼。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350