隐藏⾯消除
Snip20190516_5.png其实很直接的解释就是在绘制3D场景的时候,需要决定那部分是观察者能够看到的,那部分是观察者看不到的,对于不可见的部分,应该及时或则及早的丢弃,比如在一个不透明的大物体后面,就不应该被渲染,这种情况就叫做'隐藏面消除'(Hidden surface elimination).
隐藏面消除的解决方案有哪些呢
1:油画算法
2:正背面剔除
3:深度测试(Z-buffer⽅法)
油画算法
Snip20190516_2.png 上面这个幅图的绘制顺序就是先绘制红色部分,再绘制黄色部分,最后再绘制灰色部分,这样就能达到解决隐藏面消除的问题先绘制场景中的离观察者较远的物体,再绘制较近的物体
油画算法的弊端
使⽤用油画算法,只要将场景按照物理理距离观察者的距离远近排序,由远及近的绘制即可.那么会出现 什什么问题? 如果三个三⻆角形是叠加的情况,油画算法将⽆无法处理理
正背面剔除(Face Culling)
首先我们思考一些问题
1:尝试相信⼀个3D图形,你从任何⼀个方向去观察,最多可以看到⼏个⾯?
2:答案是,最多3面. 从一个⽴方体的任意位置和⽅向上看,你用过不可能看到多于3个⾯.
3:那么思考? 我们为何要多余的去绘制那根本看不到的3个⾯面?
4:如果我们能以某种⽅式去丢弃这部分数据,OpenGL 在渲染的性能即可提⾼超过50%.
那么问题又来了
1:如何知道某个面在观察者的视野中不会出现呢?
答: 1:任何平面都有2个⾯,正⾯/背⾯.意味着你⼀个时刻只能看到⼀⾯
2:OpenGL 可以做到检查所有正⾯朝向观察者的⾯,并渲染它们.从⽽丢 弃背⾯朝向的⾯. 这样可以 节约片元着⾊器的性能
2:如何告诉OpenGL你绘制的图形,那个是正面,那个是背面?
答:通过分析顶点数据的顺序
正背面
其实正面背面也不是固定的,他其实不光跟定点连接顺序有关,还跟观察者的位置有关,所以正面和背面是由观察者和三角形定义顺序共同决定的
开启表⾯剔除(默认背⾯剔除)
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
用户指定环绕那个为正面
void glFrontFace(GLenum mode);
mode参数为: GL_CW,GL_CCW,默认值:GL_CCW
例如,剔除正⾯实现
glCullFace(GL_BACK);
glFrontFace(GL_CW);
正背面消除法是解决了隐藏⾯消除问题,但是新的问题又产生了
深度
1:什么是深度
深度其实就是该像素点在3D世界中距离摄像机的距离,Z值
2:什么是深度缓冲区
深度缓存区,就是⼀块内存区域,专⻔存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越⼤, 则离摄像机就越远
3:为什么需要深度缓冲区?
在不使⽤用深度测试的时候,如果我们先绘制⼀个距离⽐较近的物理,再绘制距离较远的物理,则距离 远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么 要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写⼊到缓冲区中. 除⾮调⽤用glDepthMask(GL_FALSE).来禁⽌写⼊
Z-buffer⽅方法(深度缓冲区Depth-buffer)
深度测试
深度缓冲区(DepthBuffer)和颜⾊缓存区(ColorBuffer)是对应的.颜色缓存区存储像素的颜⾊信息,⽽深度缓冲区存储像素的深度信息. 在决定是否绘制⼀个物体表⾯时, ⾸先要将表⾯对应的像素的深度值与当前深度缓冲区中的值进行⽐较. 如果⼤于深度缓冲区中的值,则丢弃这部分.否则 利用这个像素对应的深度值和颜⾊值.分别更新深度缓冲区和颜⾊色缓存区. 这个过程称为”深度测试”
深度缓冲区,一般由窗⼝管理系统,GLFW创建.深度值一般由16位,24位,32位值表示. 通常是24位.位
数越高,深度精确度更好.
开启深度测试
glEnable(GL_DEPTH_TEST);
在绘制场景前,清除颜⾊缓存区,深度缓冲 glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
清除深度缓冲区默认值为1.0,表示最⼤大的深度值,深度值的范围为(0,1)之间. 值越⼩小表示越靠近观察者,值越⼤大表示 越远离观察者
网友评论