背景:3D图形渲染的时候,需要决定哪些部分是对观察者可见的,哪些部分对观察者是不可见的,对不可见的部分,应该丢弃。
这个过程叫做隐藏面消除(hidden surface elimination)。
1.0油画算法
先绘制场景中距离观察者较远的物体,再绘制场景中离观察者较近的物体。
1.1油画算法的抬杠场景见图,三个物体互相叠加的过程就显现出来油画算法的弊端。
2.0正背面剔除 Face culling
OpenGL不去渲染视角看不到的面
OPenGL可以做到检查正面朝着观察者的面,丢弃背向的面,节约片元着色器的性能。
2.1确定绘制图图形正面的方法是根据观察者的位置和三角形顶点顺序来实现。
正背面的区分:按照逆时针顶点连接顺序的面为正面。
3.0正背面提出基本代码
3.1开启表面剔除(默认背面剔除)
glEnable(GL_CULL_FACE);
3.2关闭正背面剔除功能
glDisable(GL_CULL_FACE);
3.3用户选择剔除哪个面,默认背面
glCullFace(GL_BACK);
3.4改变正背面定义
glFrontFace(GL_CCW);默认是CCW
4.0深度是描述像素点的,表示该像素点在3D世界中距离摄像机的距离,Z值。
4.1深度缓冲区,是描述一块内存区域,专门存储每个像素点(绘制在屏幕上的深度值),深度值(Z值)越大,像素点离相机越远。
4.2在不使用深度测试的时候,当出现后绘制的图形离比先绘制的图形远的时候,会出现后绘制的图形遮挡先绘制图形的情况,不符合实际。有了深度缓冲区之后,绘制物体的顺序就不那么重要了。只要有深度缓冲区,OpenGL就会把像素点的深度值写入到缓冲区中。
4.4深度测试
深度缓冲区(DepthBuffer)和颜色缓冲区(ColorBuffer)是对应的。深度缓冲区存储像素的深度信息,颜色缓冲区存储像素的颜色信息。在决定是否绘制一个物体表面时候,首先要将物体表面的像素的深度值和当前深度缓冲区中的数据进行比较,如果大于深度缓冲区中的深度,就丢弃物体表面的颜色值和深度值,如果小于就使用物体表面的颜色值,并更新这个像素的深度值和颜色值。这个过程叫做深度测试。
5.0深度测试的实际应用
5.1深度缓冲区,一般由窗口管理系统GLFW创建。深度值一般由16位,24位,32位组成,位数越高,深度精确度越好。
5.3开启深度测试
glEnable(GL_DEPTH_TEST);
5.4绘制场景前,清除颜色缓冲区,深度缓冲区
glClear(0.0f,0.0f,0.0f,1.0f)
glCLear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
清除深度缓冲区的时候,默认值是1.范围是(0-1) 之间,值越小,表示越靠近观察者。
5.5指定深度测试判断模式
glDepthFunc(GLEnum mode);
//默认使用GL_LESS
//当前深度值小于深度缓冲区中的深度值,测试通过
类型快查
5.6打开或者阻断深度缓冲区的写入
glDepthMask(GL_TRUE)//开启
6.0深度测试的闪烁问题zFighting
6.1开启深度测试后OpenGL就不会绘制模型被挡住的部分。深度缓冲区的精度限制对于现实中精度相差较小的情况,当出现不能正确判断两者深度值的时候,如果进行多次绘制,当深度测试结果不可预测时候,会出现闪烁问题。
6.2闪烁问题的解决
启用polygon offset,让深度之间产生一个间隔,如果两个图形之间有间隔,将间隔值略微增加,让重叠的两个图形与之前的有所区分。
glEnable(GL_POYGON_OFFSET_FILL)
6.3参数列表
GL_POYGON_OFFSET_POINT 对应光栅化模式GL_POINT
GL_POYGON_OFFSET_LINE 对应光栅化模式GL_LINE
GL_POYGON_OFFSET_FILL 对应光栅化模式GL_FILL
6.4指定偏移量
每个片元(Fragment)的深度值都会增加一些偏移量
m多边形深度斜率最大值
r常量,窗口坐标系能分辨的最小差值
Depth offset = (m * factor) + (r * units)
offset是负值将使z值距离我们更近。一般都设置成-1 -1.factor和units.
glPolygonOffset(GLFloat factor,GLFloat units);
6.5解决闪烁问题了之后就关闭偏移用法???
glDisable(GL_POLYGON_OFFSET_FILL)
6.6.0 zFighting闪烁预防
6.6.1不要将两个物体离的太近
6.6.2将近裁剪面设置的离观察者远一点
6.6.3使用高位数的深度缓冲区
7.0 OpenGL裁剪
7.1 在OpneGL中提高渲染的一种方式,只刷新屏幕上发生变化的部分。限制渲染区域,通过裁剪方式可以在屏幕上指定一个矩形区域。启动裁剪测试后,不在此区域中的片元会被丢弃。达到的效果是,在屏幕上开一个小窗口,可以在其中对指定内容的绘制。
7.2开启裁剪测试
glEnable(GL_SCISSOR_TEST);
7.3关闭裁剪测试
glDisable(GL_SCISSOR_TEST);
7.4指定裁剪窗口
glScissor(GLint x,GLint y,GLSize width,GLSize height)
//x,y指定裁剪框左下角位置
//width,height裁剪框尺寸
7.5窗口-显示界面
7.6视口-显示图形的矩形区域-通过glViewPort()设置
7.7裁剪区域(平行投影)- 视口矩形区域最小最大x坐标,视口矩形区域最小最大Y坐标。通过glOrtho()函数设置,这个函数还需指定最近最远z坐标,形成一个立体裁剪区。???
8.0混合
当深度缓冲区被关闭的时候,新的颜色将简单的覆盖原来的颜色缓存区存在的颜色值。
当深度缓冲弄区再次被打开时候,新的颜色片段只有当离原来的值更接近裁剪平面时候才会替换原来的颜色片段。????
glEnable(GL_BLEND)
8.1
目标颜色:已经存储在颜色缓存区的颜色
源颜色:作为当前渲染命令结果,进入颜色缓存区的颜色
最终颜色的计算是由颜色混合方程式决定的
8.2混合方程式
//默认混合方程式
Cf = (Cs * S) + (Cd * D)
//混合方程式的使用
glbBlendEquation(GLenum mode);
Cf :最终的参数颜色
Cs :源颜色
Cd :目标颜色
S :源混合因子
D: 目标混合因子
混合方程式快查
8.3混合因子计算结果用法
glBlendFunc(GLenum S,GLenum D)
S源混合因子
D目标混合因子
C表示常量颜色,黑色
混合因子计算方法快查
混合函数经常用于实现在其他一些不透明物体前绘制一个透明物体的效果。