我们在绘制3D场景的时候,需要决定哪些部分是对观察者可见的,哪些是对观察者不可见的,只对可见的部分进行渲染,此时OpenGL的渲染性能即可提高超过50%,这种情况叫做隐藏面消除。
解决问题: 如何知道某个面在观察者的视野中不会出现?
)
任何平面都有2个面,正面/背面,意味着观察者一个时刻只能看到其中一个面,而OpenGL可以通过分析顶点数据的顺序检测到所有此时面向观察者的面并渲染他们,从而丢弃背面的渲染,这样可以节约片元着色器的性能。
怎样分析顶点数据的顺序
- 正面:按照逆时针顶点连接顺序的三角形面
- 背面:按照顺时针顶点连接顺序的三角形面
分析立方体中的正背面
- 当观察者在右侧时,则右侧的三角形方向为逆时针方向则为正面,左侧的三角形为顺时针为背面
- 当观察者在左侧时,则左侧的三角形方向为逆时针方向为正面,右侧的三角形为顺时针为背面
- 正面和背面是由三角形的顶点定义顺序和观察者的方向共同决定的,随着观察者的角度方向改变,正面背面也会跟着改变
开关正背面剔除和用户指定逆时针/顺时针为正面的代码实现
//开启表面剔除(默认是背面剔除)
void glEnable(GL_CULL_FACE)
//关闭表面剔除
void glDisable(GL_CULL_FACE)
//用户选择剔除哪个面(正面/背面)
void glCullFace(<#GLenum mode#>)
model参数为:GL_FRONT_AND_BACK,GL_FRONT,GL_BACK
//用户指定逆时针/顺时针为正面,默认为逆时针
void glFrontFace(<#GLenum mode#>)
model参数为:GL_CW,GL_CCW(默认值)
解决完正背面剔除后出现的深度问题
什么是深度和深度缓冲区
- 深度就是该像素点在世界坐标系中距离观察者的距离,Z值
- 深度缓冲区就是一块内存区域,专门存储着每个像素点(绘制在平面上的)深度值,深度值越大,则离摄像机就越远
- 深度缓冲区和颜色缓存区是对应的,颜色缓存区存储着像素的颜色信息,深度缓冲区存储像素的深度信息。在决定是否绘制一个物体表面时,首先会将该物体对应的像素深度值与当前深度缓冲区的值进行比较,如果大于缓冲区的值,则丢弃这部分,否则利用这个像素对应的深度值和颜色值,分别更新深度缓冲区和颜色缓存区,这个过程称为深度测试
深度测试使用
//开启深度测试
void glEnable(GL_DEPTH_TEST)
//关闭深度测试
void glDisable(GL_DEPTH_TEST)
//绘制场景前,要清空颜色缓存区和深度缓冲区
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
ZFighting闪烁问题
因为开启深度测试后,OpenGL就不会再去绘制模型被遮挡的部分,这样实现的显示更加真实,但是由于深度缓冲区精度的限制对于深度相差非常小的情况下,OpenGL就可能出现不能正确判断两者的深度值,导致结果不可预测,显示出来的现象是交错闪烁的,2个画面交错出现。启用Polygon Offset(多边形偏移)解决
1.启用启用Polygon Offset,让深度值之间产生间隔,如果2个图形之间有间隔,意味着就不会产生干涉,可以理解为在执行深度测试前将立方体的深度值做一些细微的增加
2.指定偏移量
3.关闭Polygon Offset
//开启多边形偏移
glEnable(<#GLenum cap#>)
//参数类标
GL_POLYGON_OFFSET_FILL,GL_POLYGON_OFFSET_LINE,GL_POLYGON_OFFSET_POINT
//指定s偏移量
glPolygonOffset(<#GLfloat factor#>, <#GLfloat units#>)
//关闭多边形偏移
glDisable(<#GLenum cap#>)