关于DrawCall及渲染流程的认识总结

      

 首先了解一下渲染流水线,当一个object要被渲染时,分为CPU和GPU两个阶段:

      CPU阶段

            1.cpu首先从硬盘收集需要的网格信息(包括顶点的位置信息,法线方向,顶点颜色等)和纹理信息,把这些信息加载到内存(RAM)中,然后再加载到显卡的显存(VRAM)中。

            2.设置好渲染状态(比如透明不透明,lightmode,双面单面,使用定点着色器还是片元着色等),等到GPU阶段时,就按照这个规矩渲染就行了.....

            3.就是DrawCall了,经过上边两个步骤,CPU就对GPU说:”兄弟,开始工作了!”  Draw Call就是一条命令,告诉GPU可以按照上边的步骤渲染object了

    GPU阶段:

         一.输入顶点信息

          二.几何阶段

                1.顶点着色器处理顶点信息,通过与各种转换矩阵相乘,把顶点的位置信息和法线信息,从模型空间>世界空间>摄像机空间>裁剪空间   (完全可编程)

               2.曲面细分着色器:用于细分图元   (可选)

               3.几何着色器:执行逐图元的着色操作,或者被用于产生更多的图元    (可选)                                                                                              

                4.裁剪:裁剪掉那些不在摄像机视野内的定点,并提出某些三角图元的面片   (可配置:例如自定 义裁剪平面来配置裁剪区域,还可以通过指令控制裁剪三角图元 的正面或反面等)                            

                5.屏幕映射:把每个图元的坐标转换到屏幕坐标系中       (不可配置和编程)

          三.光栅化阶段

                   1.三角形设置:上个阶段输出的都是三角网格的顶点,即三角网格每条边的两个顶点。如果要得到整个三角网格对像素的覆盖情况,我们就必须要计算每条边上 的像 素坐标。为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表达式。这样一个计算三角网格表示数据的过程叫三角形设置。

                     2.三角形遍历:检查每个像素是否被一个三角形网格所覆盖。如果被覆盖,就会生产一个片元Fragment),注:一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色。

                   3.片元着色器完成很多重要的渲染技术,例如:纹理采样等         (完全可编程)

                   4.逐片元操作:对片元进行测试工作,如深度测试,模板测试等,通过测试的片元可以把他身上的颜色值与已经存储在颜色缓冲区的颜色混合,最后再写入颜色缓冲区中                                       (可高度配置)

           四.输出屏幕图像         渲染流程结束!!

 


过多的DrawCall会造成CPU的性能瓶颈:

        记住CPU最耗时的动作就是读写内存。但当计算量超大时,就需要用空间来换时间,例如静态批处理,LOD等。

       大量时间消耗在DrawCall准备工作上(除了上文的准备工作外还有比如脏属性的检查以减少传输量,比如渲染状态的正确性和一致性检查等等,一般来说GPU命令的生成也可以放在这里完成)。


一个优化方向就是:尽量把小的DrawCall合并到一个大的DrawCall中,这就是批处理的思想。下面是一些具体实施方案:

  1. 合并的网格会在一次渲染任务中进行绘制,他们的渲染数据,渲染状态和shader都是一样的,因此合并的条件至少是:同材质、同贴图(可在作图软件中合并)、同shader。最好网格顶点格式也一致。
  2. 尽量避免使用大量小的网格,当确实需要时,进行合并。
  3. 避免使用过多的材质,尽量共享材质。
  4. 合并本身有消耗,因此尽量在编辑器下进行合并
  5. 确实需要在运行时合并的,将静态的物体和动态的物体分开合并:静态的合并一次就可以,动态的只要有物体发生变换就要重新合并。
  6. 参考 http://www.newbieol.com/information/1501.html


你可能感兴趣的:(Unity)