渲染过程中可能产生的问题
在绘制3D场景的时候,我们需要决定哪些部分是对观察者可见的,或者哪些部分是对观察者不可⻅的。对于不可⻅的部分,应该及早丢弃。例如在⼀个不透明的墙壁后,就不应该渲染。这种情况叫做“隐藏面消除”(Hidden surface elimination).
解决方案一:油画算法
- 先绘制场景中离观察者较远的物体,再绘制较近的物体。
- 例如下面的图例,先绘制红色部分,再绘制黄色部分,最后再绘制灰色部分,即可解决隐藏面消除的问题。
弊端
- 如果三个三角形是叠加的情况,油画算法将无法处理。
解决方案二:正背面剔除
背景
想象一个3D图形,从任何一个方向观察,总是会有看不到的面,那么我们为何要多此一举去绘制那些根本看不到的面呢,如果我们能以某种方式去丢弃这部分看不到的数据,OpenGL渲染性能即可提升超过50%。
如何知道某个面在观察者的视野中会不会出现?
- 任何平面都有2个面,正面/背面。意味着你一个时刻只能看到一面。
- OpenGL可以做到检查所有正面朝向观察者的面并渲染它们,从而丢弃背面,这样可以节约片元着色器性能。
如何告诉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
};
- 正面:按照逆时针顶点连接顺序的三角形面
- 背面:按照顺时针顶点连接顺序的三角形面
分析立方体中的正背面
- 左侧三角形顶点顺序为:1 -> 2 -> 3;右侧三角形的顶点顺序为1 -> 2 -> 3
- 当观察者在右侧时,则右边的三角形方向为逆时针方向则为正面,而左侧的三角形为顺时针则为背面。
- 当观察者在左侧时,则左边的三角形为逆时针方向判定为正面,右侧的三角形为顺时针判定为背面。
总结
正面和背面是由三角形的顶点定义顺序和观察者方向共同决定的,随着观察者的角度方向的改变,正面背面也会跟着改变。
实际代码操作
- 开启表面剔除(默认背面剔除)
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
- 用户指定OpenGL环境正面的三角形顶点环绕顺序
void glFrontFace(GLenum mode);
mode参数为:GL_CW(顺时针),GL_CCW(逆时针),默认值为GL_CCW
- 例:剔除正面实现(1)
glCullFace(GL_BACK);
glFrontFace(GL_CW);
- 例:剔除正面实现(2)
glCullFace(GL_FRONT);