OpenGL 渲染技巧:正背面剔除

2020-07-13  本文已影响0人  打碟的DJ

背景

当我们在绘制一个 3D 图形时,比如甜甜圈,当我们在转动物体的时候,可以发现会出现显示的颜色会出现黑色。这种情况是,当我们设置了观察者后,视图中有些部分对于观察者是不可见的,而那些不可见的部分在绘制的时候就是黑色背景。而在图形转动的过程中,可见部分和不可见部分交替出现,而这时 OpenGL 不知道该绘制哪一面,所以就导致如下的情况。

甜甜圈.gif

解决方案

对于不可见的部分,应及早丢弃。这种情况就叫做“隐藏面消除”。

油画算法

先绘制场景中离观察者较远的物体,在绘制较近的物体。
例如下面的图例:先绘制红色部分,在绘制黄色部分,最后在绘制灰色部分,即可解决隐藏面消除的问题。

但是油画算法有如下的弊端。

所以由此引入了正背面剔除(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);

OpenGL Demo链接

上一篇下一篇

猜你喜欢

热点阅读