OpenGL

OpenGL正背面剔除和深度测试

2020-07-09  本文已影响0人  MonKey_Money

我们画一个甜甜圈来解决正背面剔除和深度测试

OpenGL 基本图形的绘制,大致步骤都一样,本次重复代码就不在复述了,如果有疑问请看demo

SetupRC关键代码

    //3.将相机向后移动7个单元:肉眼到物体之间的距离
    viewFrame.MoveForward(7.0);
    
    //4.创建一个甜甜圈
    //void gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
    //参数1:GLTriangleBatch 容器帮助类
    //参数2:外边缘半径
    //参数3:内边缘半径
    //参数4、5:主半径和从半径的细分单元数量
    gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);

之前我们的顶点数据都是自己创建的,在甜甜圈中有提供gltMakeTorus,为我们自动构造数据模型。

SpecialKeys函数关键代码

    //1.判断方向
    if(key == GLUT_KEY_UP)
        //2.根据方向调整观察者位置
        viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);
    
    if(key == GLUT_KEY_DOWN)
        viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);
    
    if(key == GLUT_KEY_LEFT)
        viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);
    
    if(key == GLUT_KEY_RIGHT)
        viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);

这次画甜甜圈,我们调整观察者的位置,实现甜甜圈的旋转。

RenderScene关键代码

   //使用默认光源着色器
    //通过光源、阴影效果跟提现立体效果
    //参数1:GLT_SHADER_DEFAULT_LIGHT 默认光源着色器
    //参数2:模型视图矩阵
    //参数3:投影矩阵
    //参数4:基本颜色值
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);

显示效果

image.png

出现这个问题的原因是隐藏面消除

隐藏面消除

在绘制3D场景的时候,我们需要决定哪些部分是对观察者可见的,或者哪些部分是对观察者不可见的。对于不可见的部分,应该及早丢弃。例如:在一个不透明的墙壁后,就不不应该渲染。这种情况叫做“隐藏面消除“(Hidden surface elimination)。
解决方案:油画算法

油画算法

1.先绘制场景中的离观察者较远的物体,再绘制较近的物体。
2.例如下面的我们先画红色,再画黄色部分,最后画灰色部分,这样就可以解决隐藏面消除。

PaintingDiagram.png

但是交叉的图层就无法处理

image.png

使用油画算法只是将场景按照物理距离观察者的距离远近排序,由远及近的绘制即可,对于上图的叠加情况,无法处理

正面或者背面剔除

所有平面都有两个面,正面和背面,我们在一个时刻只能看到其中一个面。而看不到的面,我们是不是可以不绘制观察者看到的面。来提高我们的渲染性能那。OpenGL 可以做到检查所有正面朝向观察者的面,并渲染它们.从而丢弃背面朝向的⾯. 这样可以 节约片元着⾊器的性能

正面/背面区分

正面:按照逆时针顶点连接顺序的三角形面
背面:按照顺时针顶点连接顺序的三角形面


frontback.png

立体图形的正背面

image.png

左侧三⻆角形顶点顺序为: 1—> 2—> 3 ; 右侧三⻆角形的顶点顺序为: 1—> 2—> 3 .
当观察者在右侧时,则右边的三⻆角形⽅方向为逆时针⽅方向则为正面,而左侧的三角形为顺时针则为背面。
当观察者在左侧时,则左边的三角形为逆时针方向判定为正面,而右侧的三角形为顺时针判定为背面
正面和背面不是绝对的,它是有观察者和三角形的顶点定义顺序共同决定的,当观察者的角度方向改变,正面和背面也会跟着改变。

开启正背面消除

glEnable(GL_CULL_FACE); //没有设置背面和正面,会默认背面

关闭正面背面消除

glDisable(GL_CULL_FACE);

设置消除面是哪面

glCullFace(GLenum mode);

GL_FRONT 指消除正面,GL_BACK指消除背面,GL_FRONT_AND_BACK指正面和背面都消除。

项目中设置glEnable(GL_CULL_FACE);

image.png

开启正背面消除后还是有问题,这是因为没有开启深度测试导致的

深度测试

1.深度是指在像素点在3D世界里距离观察者(相机的)距离,如果观察者在Z轴正方向,值越大越靠近观察者,同理,观察者在Z轴负方向值越小,越靠近观察者。
2.深度缓存区:就是一块内存区域,专门存储每个像素点的深度值,值越大,距离越远。
3.为什么需要深度缓存
在不使用深度测试的时候,如果我们先绘制一个距离比较近的物体,再绘制距离较远的物体,则距离 远的位图因为后绘制,会把距离近的物体覆盖掉. 有了深度缓冲区后,绘制物体的顺序就不那么重􏰂 要的. 实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写入到缓冲区中. 除非调用 glDepthMask(GL_FALSE)来禁⽌写入.
开启深度测试

    glEnable(GL_DEPTH_TEST);
image.png
上一篇 下一篇

猜你喜欢

热点阅读