《Unity Shader入门精要》读书笔记——渲染流水线

版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/MacYosef/article/details/79029146

读《Unity Shader入门精要》总结
  

概述

  
    渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏幕上看到的所有效果。
  
    渲染流程大体可以分为三个概念阶段:


CPU流水线

  • 应用阶段
      
    开发者具有这个阶段的绝对控制权。
    大致分为三个阶段:

    1. 把数据加载到显存中:
      这里写图片描述
      渲染所需的数据从硬盘最终加载到显存中。在渲染时,GPU可以快速访问这些数据

        
    2. 设置渲染状态
      渲染状态定义了场景中的网格是怎样被渲染的。例如,使用哪个顶点着色器/片元着色器、光源属性、材质等。
        
    3. 调用Draw Call
      Draw Call只是一个命令,从CPU发送向GPU。这个命令仅仅会指向一个需要被渲染的图元列表,并且不会包含任何材质信息。
      这里写图片描述

GPU流水线

这里写图片描述

GPU的渲染流水线实现。颜色表示了不同阶段的可配置性或可编程性:绿色表示该流水线阶段是完全可编程控制的,黄色表示该流水线阶段可以配置但不是可编程的,蓝色表示该流水线阶段是由GPU固定实现的,开发者没有任何控制权。实线表示该shader必须由开发者编程实现,虚线表示该Shader是可选的

  
GPU的渲染流水线接收顶点数据作为输入。这些顶点数据是由应用阶段加载到显存中,再由Draw Call指定的。
  

  • 几何阶段
      
    顶点着色器 是完全可编程的,它的处理单位是顶点。顶点着色器需要完成的工作主要有:坐标变换、逐顶点光照和输出后续阶段所需的数据。必须完成的一个工作是,把顶点坐标从模型空间转换到齐次裁剪空间。
      
    这里写图片描述

    顶点着色器会将模型顶点的位置变换到齐次裁剪坐标空间下,进行输出后再由硬件做透视除法得到NDC下的坐标

      
    裁剪 是为了不处理那些不在摄像机视野范围内的物体。这一步不可编程。裁剪过程:
    这里写图片描述

    只有在单位立方体的图元才需要被继续处理。因此,完全在单位立方体外部的图元(红色三角形)被舍弃,完全在单位立方体内部的图元(绿色三角形)将被保留。和单位立方体相交的图元(黄色三角形)会被裁剪,新的顶点会被生成,原来在外部的顶点会被舍弃

      
    屏幕映射 的任务是把每个图元的xy坐标转换到屏幕坐标系下。
    x、y 坐标从(-1,1)范围转换到屏幕坐标系中:
    这里写图片描述

    注意:屏幕坐标系在OpenGL和DiretX之间存在差异:
    这里写图片描述

      
  • 光栅化阶段
      
    三角形设置 阶段会计算光栅化一个三角形网格所需的数据。
      
    三角形遍历 阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖,会生成一个片元。片元是包含了很多状态的集合,这些状态包括屏幕坐标、深度信息、法线、纹理坐标等。三角形遍历过程:
    这里写图片描述

    根据几何阶段输出的顶点信息,最终得到该三角网格覆盖的像素位置。对应像素会生成一个片元,而片元中的状态是对三个顶点的信息进行插值得到的。

      
    片元着色器 是另一个非常重要的可编程着色器阶段。这一阶段可以完成很多重要的渲染技术,技术之一是纹理采样。在执行片元着色器时,它不能将自己的任何结果直接发送给它的邻居。这一阶段的输出是一个或多个颜色值。
      
    逐片元操作 这一阶段有几个主要任务:
      
    1. 决定每个片元的可见性。涉及许多测试工作:深度测试、模板测试等。
    2. 如果片元通过测试,需要把源颜色(通过测试的片元颜色)与目标颜色(颜色缓冲区中的颜色)进行混合。
        
      此阶段所做的操作:
      这里写图片描述

      只有通过了所有的测试后,新生成的片元才能和颜色缓冲区中已经存在的像素颜色进行混合,最后再写入颜色缓冲区中

        
      模板测试和深度测试简化流程图:
      这里写图片描述

      混合操作简化流程图:
      这里写图片描述

      Unity的渲染流水线中,深度测试是在片元着色器之前。
      屏幕显示的就是颜色缓冲区的值,为了避免看到正在进行光栅化的图元,GPU会使用双重缓冲:即对场景的渲染发生在后置缓冲中。

Draw Call

Draw Call本身的含义很简单,就是CPU调用图像编程接口,如OpelGL中的glDrawElements命令。
Draw Call中造成性能问题的元凶是CPU
  
CPU和GPU实现并行工作
  
让CPU和GPU可以并行工作,解决方法是使用一个命令缓冲区:

这里写图片描述

CPU通过图像编程接口向命令缓冲区中添加命令,而GPU从中读取命令并执行。黄色方框内的命令就是Draw Call,而红色方框内的命令用于改变渲染状态。我们使用红色方框来表示改变渲染状态的命令,
是因为这些命令往往更加耗时

Draw Call多了影响帧率

如果Draw Call的数量太多,CPU就会把大量时间花费在提交Draw Call上,造成CPU过载。

这里写图片描述

命令缓冲区中的虚线方框表示GPU已经完成的命令。此时,命令缓冲区中没有可以执行的命令了,GPU处于空闲状态,而CPU还没有准备好下一个渲染命令。

减少Draw Call

  1. 避免使用大量很小的网格。
  2. 避免使用过多的材质。

以便于Unity中利用批处理进行优化。

没有更多推荐了,返回首页