OpenGL 渲染技巧:正背面剔除
2020-07-13 本文已影响0人
打碟的DJ
背景
当我们在绘制一个 3D 图形时,比如甜甜圈,当我们在转动物体的时候,可以发现会出现显示的颜色会出现黑色。这种情况是,当我们设置了观察者后,视图中有些部分对于观察者是不可见的,而那些不可见的部分在绘制的时候就是黑色背景。而在图形转动的过程中,可见部分和不可见部分交替出现,而这时 OpenGL 不知道该绘制哪一面,所以就导致如下的情况。
甜甜圈.gif解决方案
对于不可见的部分,应及早丢弃。这种情况就叫做“隐藏面消除”。
油画算法
先绘制场景中离观察者较远的物体,在绘制较近的物体。
例如下面的图例:先绘制红色部分,在绘制黄色部分,最后在绘制灰色部分,即可解决隐藏面消除的问题。
但是油画算法有如下的弊端。
- 1、我们必须对任何发生的图形重叠的地方的每个像素点进行多次的写操作,从而在存储其中的写操作时会使速度变慢
- 2、对独立三角形进行排序的开销过高
- 3、当我们无法分辨出物体的远近的时候,油画算法将无法进行处理;比如下图的情况:
所以由此引入了正背面剔除(Face Culling)
正背面剔除(Face Culling)
背景
当我们观察一个 3D 图形时,无论从哪一个方向观察,最多只能看到3个面,那我们看不到的那三个面根本不需要去绘制,我们以某种方式来丢弃这部分的数据,还可以在渲染的过程中使我们的性能提高 50%。
任何的平面都有两个面,正/反面。这意味着我们在同一时刻只能看到一面。所以我们可以让 OpenGL 检查所有正面朝向观察者的面,并渲染它们;从而丢弃背面朝向的面,这样可以节约偏远着色器的性能。
那么我们如何区分正/反面呢?
通过分析顶点数据:
GLfloat vertices[] = {
//顺时针
vertices[0], // vertex 1
vertices[1], // vertex 2
vertices[2], // vertex 3
// 逆时针
vertices[0], // vertex 1
vertices[2], // vertex 3
vertices[1] // vertex 2
};
正面:按照逆时针顶点连接顺序的三角形面
反面:按照顺时针顶点连接顺序的三角形面
常用 api
// 开启表面剔除(默认背面剔除)
void glEnable(GL_CULL_FACE);
// 关闭表面剔除(默认背面剔除)
void glDisable(GL_CULL_FACE);
// 用户选择剔除哪个面(正面/背面)
// model 参数为:GL_FRONT,GL_BACK,GL_FRONT_AND_BACK,默认GL_BACK
void glCullFace(GLEnum mode);
// 用户指定绕序哪个为正面
// mode参数为:GL_CW,GL_CCW,默认为GL_CCW
void glFrontFace(GLEnum mode);
// 例如,剔除正面实现1
glCullFace(GL_BACK);
glFrontFace(GL_CW);
// 剔除正面实现2
glCullFace(GL_FRONT);