注册账号登录
Henry_磊
不想看到BUG的好男人
关注

OpenGL下隐藏面消除的解决方案

职业程序员创建于2020/12/2150次阅读

在OpenGL的渲染下,我们需要决定哪些部分是对观察者可见的,或者哪些部分不可见。对于不可见的部分我们需要进行一定的处理,不然就会出现以下情况。

所以我们给出以下方案:

1、油画算法:先绘制距离观察者远的物体(图片1),再绘制距离距离观察者近的物体(图片2)。如下图所示。

但是此方法存在一个弊端,如果图片的叠加是无序且错综复杂的,在绘制时就无法明确出正确的先后顺序!,如下图所示:

由此我们得到方法2。

2、正背面剔除

OpenGL 可以做到检查所有的正面朝向观察者的面,并且渲染它们,从而丢弃背面,可以解决片元着色器的性能。因此我们需要通过分析顶点数据的顺序来区分图形的正面和背面。

正面:按照逆时针顶点顺序连接的三角形面

背面:按照顺时针顶点顺序连接的三角形面

OpenGL方法:

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

void glEnable(GL_CULL_FACE);

• 关闭表面提出(默认背面剔除)

void glDisable(GL_CULL_Face);

• 用户选择剔除哪个面

void glCullFace(GLenum mode);

model参数:GL_FRONT,GL_BACK,GL_FRONT_AND_BACK ,默认GL_BACK⽤用户指           
定绕序那个为正⾯面    

使用正背面剔除后效果如下所示:

由上图可看出,我们已经解决了隐藏面导致显示异常的问题,但是我们出现了如上图的问题,这个效果是由于深度引起的相关显示问题。

1、什么是深度?

深度是指该像素点在3D世界中距离摄像机位置的Z值。

2、什么是深度缓冲区
这里有一个iOS交流圈:技术交流 可以一起交流学习。进群回复简书就好。

深度缓冲区是指一块内存区域,专门用来保存每个像素点在屏幕上的深度值。深度越大Z值越大。

3、深度缓冲区的意义

在不使用深度测试的时候,假如我们先绘制一个近距离的物体,在绘制一个远距离的物体,远距离物体因为后绘制,就会把近距离的物体覆盖掉,有了深度缓冲区,物体绘制的顺序就不那么重要了,实际上只要存在深度缓冲区,OpenGL都会把像素的深度值写入其中,除非掉用glDepthMask(GL FALSE)来禁止写入。

所以在我们开启深度测试的时候,首先要将表面对应的像素的深入值和当前深度缓冲区中的值进行比较,如果大于深入缓冲区中的值,则丢弃这部分,否者就利用该像素对应的深度值和颜色值分别更新深度缓冲区和颜色缓冲区。这个过程就是深度测试。(深入缓冲区和颜色缓冲区是一一对应的)。深入测试的判断是以像素点为单位,并非以当前绘制的图形为单位。

4、如何开启深度测试?

glEnable(GL_DEPTH_TEST).

在使用中我们需要注意如果项目中需要使用深度测试,我们在绘制前要对深度缓冲区进行清除。如果不清空颜色/深度缓冲区时,会造成数据的残留,导致绘制异常。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

开启深入测试后的效果图如下图所示:

但是在一些复杂场景中会出现遇到深度值都一样的情况,这样就会出现ZFighting 闪烁问题。

ZFighting 闪烁:即指OpenGL不能正确的判断同一平面的绘制的深度值,导致深入测试结果不可预测,显示出来的纹理交错闪烁),就需要进行如下处理多边形偏移让其深度值产生一些细微的变化,达到区分二者图形深度值的效果。 指定偏移量

void glPolygonOffet(Glfloat factor,Glfloat units);

一般来说,只需要将-1.0和-1这样简单赋值给glPolygonOffet基本就可以满足需求。这样我们就可以绘制出更逼真的场景了。

作者:林子的蜕变路
链接:https://juejin.cn/post/6896834505244409869

暂无评论
Henry_磊
不想看到BUG的好男人
关注私信
0
关注
1
粉丝
20
帖子