• 【OpenGL】六、深度测试和模板测试


    深度测试和模板测试


    一、模板测试

    模板测试是在深度测试前的,片段着色器处理之后进行。

    模板缓冲

    模板缓冲区可以为屏幕上的每一个像素点保存一个无符号整数值(通常为8位int 0-255)。


    模板测试函数

    渲染过程中,可以用这个值与预先设定好的参考值作(ReferenceValue)比较,根据结果来决定是否更新相应的像素点的颜色值


    glStencilFunc

    glStencilFunc(GLenum func, GLint ref, GLuint mask)
    
    • 1
    • func:比较函数的选择参数
    • ref:模板测试的参考值
    • mask:掩码

    LearnOpenGL里写的不太详细。通过查询docs.gl可以知道:

    GL_LESS:
    if ( ref & mask ) < ( stencil & mask )

    GL_GREATER
    Passes if ( ref & mask ) > ( stencil & mask ).

    将ref值和mask值做&运算,结果为R,然后将模板缓冲中的中的值和mask做&运算结果为S,之后在比较测试S和R,比较的方法是用前面设置的func函数

    • 简述一下按位与&:全1为1,负责为0

    glStencilOp

    描述缓冲区如何更新

    glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)
    
    • 1
    • sfail:模板测试失败时采取的行为。
    • dpfail:模板测试通过,但深度测试失败时采取的行为。
    • dppass:模板测试和深度测试都通过时采取的行为。

    深度测试到底能干什么?

    描边如何使用:

    //启用模板测试
    glEnable(GL_DEPTH_TEST);
    //如果通过测试,就将模板缓冲中的值设置为指定的ref值。 可以不要
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);  
    
    
    //清除颜色缓冲和深度缓冲,模板缓冲清除为0
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
    
    
    //禁止模板缓冲写入
    glStencilMask(0x00); // 记得保证我们在绘制地板的时候不会更新模板缓冲
    normalShader.use();
    //画地板
    DrawFloor()  
    
    //全通过:在绘制箱子的地方,将模板缓冲的值设置为1,通过模板测试后就会更新模板值为1。
    glStencilFunc(GL_ALWAYS, 1, 0xFF); 
    //开启模板写入
    glStencilMask(0xFF); 
    //画两个方框
    DrawTwoContainers();
    //GL_NOTEQUAL:( ref & mask ) != ( stencil & mask ).
    
    
    //开始绘制边框:在模板缓冲值不为1的地方绘制
    glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
    //禁止模板缓冲写入
    glStencilMask(0x00); 
    //将深度测试禁用,是为了让边框不被地面所遮挡
    glDisable(GL_DEPTH_TEST);
    shaderSingleColor.use(); 
    DrawTwoScaledUpContainers();
    //这里是为了将模板缓冲清零,为下一次渲染做准备。
    glStencilMask(0xFF);
    glEnable(GL_DEPTH_TEST);  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    可能代码比较难懂:来简述

    1. 使用【禁止模板缓冲写入】绘制地板,但不写入模板缓冲,此时地板已经绘制,缓冲区全为0,
    2. 使用【开启模板缓冲写入】和【设置通过测试设为1】,此时cube渲染,缓冲区cube区域为1
    3. 再次使用【禁止模板缓冲写入】和【在模板缓冲值不为1的地方绘制】,此时再次绘制cube,源码里可以看到此处渲染时 float scale = 1.1f,所以大一点点。
    4. 诶嘿,此时对缓冲去内为1的地方的大一点点的为0的地方设置为1开始绘制,即为边界。

    二、深度测试

    太多概念LearnOpenGL有,不赘述。
    简而言之:判断场景中物体之间前后遮挡关系

    Z-Buffer (深度缓冲)和深度值

    可以理解为和颜色缓冲区一样的东西,有每个需要渲染的片段,只不过它存储的是深度值。
    摘录:

    • 模型一开始所在的模型空间:无深度
    • 通过M矩阵变换到世界空间,此时模型坐标已经变换到了齐次坐标(x,y,z,w):深度存在z分量
    • 通过V矩阵变换到视察空间(摄像机空间):深度存在z分量(线性)通过P矩阵变换到裁剪空间:深度缓冲中此空间的z/w中(已经变成了非线性的深度)
    • 最后通过一些投影映射变换到屏幕空间

    使用非线性主要是远近显示的精度需求不一样,不需要为低精度的花费更多的资源。


    深度测试函数 glDepthFunc

    glDepthFunc(GL_LESS);
    
    • 1

    这里其实没什么,就是系统的值去如何通过或丢弃一个片段。


    附录:
    LearnOpengl
    模板和深度测试
    glStencilFunc函数

  • 相关阅读:
    【光学】基于matlab模拟双孔干涉附matlab代码
    SpringMVC-18-异常机制
    Servlet规范之Requests与Servlets映射
    ES6 class静态属性 静态方法 私有方法 私有属性 实例属性 实例方法 静态私有属性 静态私有方法等
    nmake简介
    proxy实现链式编程
    什么是虚拟DOM(Virtual DOM)?它在前端框架中的作用是什么?
    Linux线程同步与互斥
    企业数据安全重要?私有化部署IM,保障信息安全无忧虑!
    如何做一个知识博主? 善用互联网检索
  • 原文地址:https://blog.csdn.net/qq_36674053/article/details/133999866