美文网首页OpenGL
06-OpenGL 渲染技巧-正背面剔除&深度测试

06-OpenGL 渲染技巧-正背面剔除&深度测试

作者: SPIREJ | 来源:发表于2019-05-22 15:28 被阅读0次
    • 渲染过程产生的问题
    • 正&背面剔除法
    • 深度测试

    一、在渲染过程中可能产生的问题

    1. 原因

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

    2. 示例

    渲染过程中可能存在的问题

    二、解决方案

    I. 正背面剔除(Face Culling)

    1. 原理

    OpenGL 检查所有正面朝向观察者的面,并渲染它们,丢弃背面朝向的面

    2. 正背面区分

    OpenGL 渲染基础中提到过

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

    正面背面区分

    总结:正面和背面是由三角形的顶点定义顺序和观察者方向共同决定的。随着观察者角度方向的改变,正面背面也会跟着改变。

    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
    
    • 用户指定哪个饶序方向为正面,默认逆时针方向,最好别去改变
    void glFrontFace(GLenum mode);
    mode参数为: GL_CW,GL_CCW, 默认值:GL_CCW
    
    例如,剔除正面实现(1)
    glCullFace(GL_BACK); //选择剔除背面
    glFrontFace(GL_CW);  //指定顺时针为正面,故背面变正面
    
    例如,剔除正面实现(2) 
    glCullFace(GL_FRONT);
    

    II. 深度缓冲区

    • 1. 什么是深度?
      深度其实就是该像素点在3D世界中距离摄像机的距离,Z值

    • 2. 什么是深度缓冲区?
      深度缓存区,就是一块内存区域,专门存储着每个像素点(绘制在屏幕上的)深度值.深度值(Z值)越大,则离摄像机就越远.

    • 3.为什么需要深度缓冲区?
      防止在绘制的时候,较近的物体先绘制,较远的物体后绘制挡住较近物体的问题.

      有了深度缓冲区后,绘制物体的顺序就不那么􏰁重要了.

      实际上,只要存在深度缓冲区,OpenGL 都会把像素的深度值写⼊到缓冲区中. 除非调⽤glDepthMask(GL_FALSE)来禁止写⼊.

    1. 深度测试

    深度缓冲区(DepthBuffer)和颜色缓存区(ColorBuffer)是对应的.
    颜色缓存区存储像素的颜色信息,而深度缓冲区存储像素的深度信息.
    在决定是否绘制一个物体表面时, 首先要将表⾯对应的像素的深度值与当前深度缓冲区中的值进⾏比较. 如果大于深度缓冲区中的值,则丢弃这部分.否则利⽤这个像素对应的深度值和颜色值.分别更新深度缓冲区和颜⾊缓存区. 这个过程称为深度测试

    2. 使用深度测试

    • 开启深度测试
    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)之间. 值越小表示越靠近观察者,值越大表示越远离观察者

    3. 指定深度测试判断式

    //指定深度测试判断模式
    void glDepthFunc(GLEnum mode);
    
    mode 值 说明
    GL_LESS 在当前深度值 < 存储的深度值时通过
    GL_EQUAL 在当前深度值 = 存储的深度值时通过
    GL_LEQUAL 在当前深度值 <= 存储的深度值时通过
    GL_GREATER 在当前深度值 > 存储的深度值时通过
    GL_NOTEQUAL 在当前深度值 != 存储的深度值时通过
    GL_GEQUAL 在当前深度值 >= 存储的深度值时通过
    GL_ALWAYS 总是通过测试
    GL_NEVER 总是不通过测试

    4. 打开/阻断 深度缓存区写入

    void glDepthMask(GLBool value);
    value : GL_TURE 开启深度缓冲区写入; GL_FALSE 关闭深度缓冲区写⼊
    

    这部分内容的案例见 07-正背面剔除&深度测试-绘制甜甜圈

    相关文章

      网友评论

        本文标题:06-OpenGL 渲染技巧-正背面剔除&深度测试

        本文链接:https://www.haomeiwen.com/subject/ylzjzqtx.html