【Unity优化】DrawCall与Batch

1、渲染一帧步骤

0-一、剔除:摄像机视锥体剔除、代码删除/隐藏Meshhtml

0-二、从硬盘HDD中加载纹理、Mesh到内存RAM,再将须要渲染的加载到VRAM[1]。编程

一、设置全局 Render State(Unity中对应SetpassCall),包含:顶点/片元着色器、纹理、材质、光照、透明度等性能

二、CPU发送一个DrawCall给GPU,指向VRAM中的一个Mesh(不包括材质,这是上一步的工做)。优化

三、GPU根据当前 Render State,以及CPU指向的顶点数据,经过代码生成像素并显示到屏幕。动画

若是后续Mesh使用相同的 Render State,那么重复二、3步骤;不然须要执行一次1步骤。htm

步骤3称为管线Pipeline。管线中从开始到结束,比较关键的模块有:顶点着色器、光栅化、片元着色器。顶点和片元着色器是可编程的,即常说的Shader。blog

[1] RAM、VRAM分别存储什么:https://www.reddit.com/r/gamedev/comments/camqq0/whats_stored_in_ram_and_vram/接口

https://forums.unrealengine.com/development-discussion/rendering/1651940-i-want-to-learn-more-about-how-vram-is-used-and-texture-object-optimizations游戏

(1)VRAM:GPU内存仅存储当前帧(DC)须要的资源,好比:纹理、mesh、shader、framebuffer、constant buffer、以及其余渲染场景所需的通用数据。处理完当前的DC后,就会清除数据,准备下次DC。图片

(2)RAM:RAM包含可执行代码、音频、游戏数据。通常不包含纹理、mesh这些已经在VRAM中的资源(CPU从HDD中读到RAM,传给VRAM,而后从RAM中清除。然而若是须要在CPU中检测碰撞,mesh信息就须要保留)。

(3)RAM、VRAM:动画、物体变换通常同时存在。一般在CPU中每帧更新,而后复制到VRAM中渲染。

2、优化概述

Render State、DrawCall属于CPU的工做,都比较耗时。优化方向:下降它们的执行次数。

减小 Render State:减小材质的种类

减小 DrawCall:不一样的Mesh尽可能使用同一个材质;对同种材质的Mesh作合批处理;使用GPU Instancing

其余优化:避免OverDraw(避免使用透明,错误示范:为了实现四角阴影,使用一张全屏图片)

3、优化细节

合批分为动态、静态。

【静态合批】:将相同材质的Mesh合并成一个大Mesh。

优势:下降DC,且只须要执行一次,能够是不一样Mesh;

缺点:占用内存,不能部分剔除。

适合:静态大Mesh。

【动态合批】:实时地将相同材质的Mesh合并成一个大Mesh。

优势:下降DC,能够是不一样Mesh,能够部分剔除。

缺点:每帧都要执行,消耗CPU,且占用内存。若是该步骤消耗的CPU,大于下降DC所带来的的提高,则反而影响性能。限制较多(非负缩放、没有光照贴图或使用相同的光照贴图位置、material单pass、不能接受实时阴影)

适用:动态的大量小Mesh。

【GPU Instancing】CPU只发送一次Mesh给GPU,GPU本身去复制实例化。为了让Mesh有不一样的状态,甚至播放动画,CPU须要同时提供一份额外数据(好比变换矩阵)。

优势:解放CPU。

缺点:须要是相同的Mesh,对平台和API有要求(Windows要求DirectX11以上、OpenGL Core 4.1+/ES 3.0+)

适用:大量相同的Mesh,好比植被

4、容易出错的地方

一、修改Render.material致使不能动态合批:

(1)Unity提供了两个获取Material的方法接口,分别是material及sharedMaterial。当对物体的material进行任何修改时,Unity会对Render里Materials列表第一个预设的Material进行实例化,并将返回实例。Unity这么作的目的是不影响其余物体,而仅仅修改这个实例。

(2)若是调用sharedMaterial,Unity就不会帮咱们实例化,直接返回本来的材质球。可是会让全部使用该sharedMaterial的模型响应相同的修改。若是这不是你想要的,能够建立两个材质球,根据不一样的状况替换材质。

Ref: [**记一次Dynamic Batching不生效的爬坑实例分析Unity]**

二、动态合并的限制是单个模型900顶点:

Unity文档中所说的动态合并的顶点限制是900,指的是单个模型,而不是合批的模型总和。合批的模型总和上限是65535[1]。同理,若是Shader使用了顶点坐标、法线、单个UV,那么限制是300个顶点;若是使用了顶点坐标、法线、UV0、UV1和切线,则限制是180个顶点。这两个限制针对的也是单个模型。

[1] https://forum.unity.com/threads/unity-5-3-static-batching-not-batch-draw-calls.372625/

相关文章
相关标签/搜索