文章

OpenGL复习(MRT、泛光、延迟渲染)

多渲染目标(Multiple Render Targets)MRT

  • 帧缓冲可以附加多个颜色纹理附件,一次drawcall输出多张纹理图片

泛光

  • 模拟光源向四周发散出光晕,使得渲染的场景看起来更亮更真实
  • 实现方式:
    • 对渲染的纹理提取超出一定亮度的片段,可以使用MRT多渲染目标技术,使用2个颜色纹理附件,在fs中指定两个颜色输出,一个为正常的场景渲染到缓冲1,另一个将超过一定亮度的颜色保留到颜色缓冲2
    • 对新的纹理模糊,可以使用高斯模糊
    • 两个纹理叠加,颜色相加再转换

延迟渲染

  • early_z可以极大减少不必要的fs计算,但由于渲染顺序原因仍有一部分片元进行不必要的fs,当场景有大量光源时,这种性能消耗将变的非常巨大,想象数千个光源对每个通过early_z的片元做计算
  • 两个处理阶段(Pass)
    • 几何处理阶段(Geometry Pass),fs不做光照计算,获取对象的各种几何信息(片段世界空间的(光照计算在世界空间中) 位置,漫反射纹理颜色,法线,深度……),存储在G缓冲即帧缓冲中,利用MRT技术,所有的数据像素插值结果输出为纹理图像
    • 光照处理阶段(Lighting Pass),使用G-buffer输出的纹理,执行光照计算,由于上个pass所有数据都是经过深度测试保留下来的,即最前面片段对应的数据,排除了不必要的光照计算
  • 延迟渲染缺陷
    • 消耗显存,因为要存储大量几何数据
    • 不支持不同的光照算法(blinn_phong,PBR……)
    • 不支持半透明物体的颜色混合,颜色混合重要的事情是对物体排序,以便后面的物体更新的颜色,和前面的物体混合,但Pass2时仅有最前面的片段数据,后面片段被丢弃掉了没办法混合,本质就是缺少数据,我们解决这个问题将这些数据保留,但消耗的内存是庞大的
    • 不支持抗锯齿,采样法的抗锯齿涵盖在光栅化所有阶段,每个采样点的数据需要保留到下个pass,如果用SSAA内存消耗是巨大的,如果用MSAA,依旧要大量消耗内存,每次被图元覆盖都需要对像素着色,以便之后拷贝给对应采样点,可我们只有最顶层的片段,哪些采样点需要做着色计算,计算拷贝给哪些采样点(属于同一图元)……
  • 解决缺陷
    • 使用不同光照算法的物体使用不同的pass渲染,深度测试需要使用上一次的深度缓冲
    • 如果渲染透明物体,需要在延迟渲染后进行正向渲染,因为要先渲染不透明物体,才有可混合的颜色
    • 抗锯齿使用FXAA后处理技术
  • 延迟渲染 vs 正向渲染
    • 延迟渲染不容易支持一些功能
    • 在较小场景光源较少时,延迟渲染可能更慢,因为两次pass的消耗,并且有更大的时间和内存消耗

光体积

  • 虽然延迟渲染是一个很大的优化,但仍不能支持非常大量的光源, 因为仍然需要为每一个光源n对每一个像素m做光照计算,m*n,这仍是非常庞大的
  • 原理:计算光源的半径,只对在光体积内的像素光照计算,不在光体积的片元就不必fs计算
  • 技术方案
    • 光球体数据准备阶段:依次遍历光源,求半径, 为光创建实际球体,球体中心放在光源位置
      • 求半径
        • 利用衰减方程,将完全黑暗0颜色带入公式左边,但由于衰减方程永远不会==0,只会趋近于0,所以使用近似黑暗5/256颜色值
        • 通过移项形成一元二次方程,可以通过求根公式解
    • 几何处理阶段:为场景生成G_Buffer
    • 光照处理阶段:渲染每个光球体,光栅化生成球体对应的片元,对这些片元采样G_Buffer的数据fs计算,这样不在光体积内的由于未通过覆盖性测试,不会产生片元,就不会fs
    • 如果多个光源重叠,将计算的颜色值混合处理
本文由作者按照 CC BY 4.0 进行授权
本页总访问量