基于GPU的渲染优化 ?
一:GPU与CPU的分工
GPU(显卡):负责渲染整个游戏的显示工作。
CPU:负责运算,游戏中的AI等等,同时为GPU的渲染做准备工作。
二:LOD层级细节
LOD介绍:LOD技术是通过摄像机所捕捉的视野范围来改变模型的层级切换,从而根据视野距离减少模型顶点,面的个数来达到渲染性能优化。
案例演示:
1.例如我们有三个模型(细节不同,但都是木桶):
0号细节刻画较好
1号细节稍微次
2号几乎细节很低
GIF查看:
这时我们利用Lod Group添加这三个模型,根据摄像机捕捉视野范围进行切换该物体显示,在视野距离很远时使用2号物体,,在视野距离一般远时使用1号物体,在视野距离较近时使用0号物体,减少顶点渲染,同时Cast Shadow和ReceiveShadow可以移除根据情况,同时观察Stats面板的Batch数值;
2.Lod Group添加这三个模型:可见度100% 0号物体, 60% 1号物体 , 30% 2号物体
3.调整摄像机位置,注意观看Stats面板顶点Verts与面Tris的个数的变化。
4.关闭Cast Shadow和ReceiveShadow,注意观看Batches(与DrawCall同值)的个数,不难看出关闭Cast Shadow和ReceiveShadow能减少DrawCall。
三:遮挡剔除OcclusionCuling
视锥体剔除:
只渲染视锥体内物体,视锥体外不渲染。任何一个普通的camera都带有视锥体剔除的功能(系统默认),而且与物体是否static无关。
视锥体剔除能减少顶点Verts与面片Tris的个数,从而降低GPU的负担,和CPU的准备工作量,提高性能。
演示:注意看Statistics面板的数据改变
遮挡剔除:
近处大物体完全遮挡住远处的小物体,则对远处小物体的渲染是无用的,所以遮挡剔除远处小物体,这里要求物体static属性最少为Ocludder Static。
遮挡剔除步骤:
1.选中要渲染的物体,将其Static属性设置为Ocludder Static。
2.打开设置面板Window->Render->OcclusionCuling
3.选中面板的Visualzation,点击Bake.
4.选中Cameras,点击Bake
之后呢,我们视野中看到的大物体后面的小物体就会因为被遮挡而不被渲染,减少了渲染的顶点数,面数。
(由于我们设置了批处理,所以DrawCall的变化不明显,其实遮挡剔除也会影响DrawCall的)
四:光照贴图Lightmapping
光照贴图技术介绍:
使用静态烘焙光提前将光照信息制作成Lightmapping,减少因为实时光带来的drawcalls代价
以及所需渲染顶点的计算。
Lightmapping制作步骤:
1.首先确认渲染的物体,将其Static属性设置为LightMapStatic;
2.设置参与bake渲染光源mode为 baked;
3.window->lighting->点击Generate Lighting,生成光照贴图。
步骤GIF演示:
接下来我们发现DrawCall减少了,顶点以及面片渲染也少了。
五:Mesh合并
Mesh合并介绍:
Mesh合并是用于将一些拥有Mesh网格的物体进行合并为一个网格,会减少DrawCalls,减轻GPU负担,同时CPU对于GPU进行渲染前的准备工作也会减少(性能消耗减少)
Mesh合并步骤
1.将需要合并的物体统一放到一个空物体下
2.为空物体添加MeshRender与MeshFitter
3.编写脚本合并Mesh
4.合并成功后的网格赋予空物体,之后该空物体即是合并后的统一物体(可以直接删除合并网格的子物体)。
5.这时我们看到我们减少了近9个DrawCall
void Start()
{
ChildMeshCombiner();
}
private void ChildMeshCombiner() //子物体合并Mesh
{
MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combineInstances=new CombineInstance[meshFilters.Length-1];
for (int i = 1; i < meshFilters.Length; i++)
{
combineInstances[i-1].mesh = meshFilters[i].sharedMesh;
combineInstances[i-1].transform = meshFilters[i].transform.localToWorldMatrix;
}
var finalMater = meshFilters[1].gameObject.GetComponent<MeshRenderer>().material;
Mesh finalMesh=new Mesh();
finalMesh.CombineMeshes(combineInstances);
meshFilters[0].mesh = finalMesh;
GetComponent<MeshRenderer>().material = finalMater;
}
编写好代码后演示过程(同时注意观看DrawCall数量):
项目工程链接地址(GitHub)
求github小星星哈,谢谢啦?
Unity性能优化项目工程链接:https://github.com/HanxianshengGame/Unity-Optimize-Project
--------------------------------------------------------我是有底线的-------------------------------------------------------------
感谢能够观看博客的各位Unity开发爱好者们,有问题发表评论呐,★,°:.☆( ̄▽ ̄)/$:.°★ 。