本文是视频课程《Unity技术美术TA:Shader篇》,算是对自己学习的总结,也希望分享下所学知识~~
Stats分析
在Game窗口,Toolbar上有个 Stats按钮,可以查看当前渲染的一些信息
Audio模块:
是音频相关的,可以先忽略
Graphics模块:
FPS(Fames Per Second):一秒内渲染多少帧
帧率越快画面越流畅,但是在手机上就会更费电之类的,所以手游一是30
ms = 1000/FPS
CPU:
main 主线程耗时 reder thread 渲染线程耗时
Batches:
Tris:三角面数 Verts:顶点数
(默认很大的是天空盒)
Screen:分辨率 + 内存占用大小
SetPass calls:
ShadowCaster:阴影相关的
Visbile skinned meshes:可见的蒙皮网格
渲染的三个指标:
1.DrawCall:CPU每次调用图形API命令GPU进行渲染的操作(CPU的消耗)
2.Batch:把需要渲染的数据加载到显存并设置好渲染状态,然后CPU调用GPU渲染的过程
3.SetpassCall:每次GPU切换一个Pass前,都会产生一次
如何降低 Batch?
三种方式
1.动态合批 Dynamic
a.材质相同,并且不是材质Instance
b.单个网格顶点最多300个,顶点属性最多900个
注意:
如果用到了 vertex+uv+normal,就可以有 900/3=300 个顶点
如果用到了 vertex+uv+normal+tangent+uv1,最多可以有 900/5=180 个顶点
一次动态合批,总顶点数最多32k
c.不能有负缩放(不一致可以)
d.只有非静态的 MeshRender 和 Particle 可以合批
不能合批一些图:
2.静态合批
a.相同材质
b.标记 batcing static
会自动生成 Combined Mesh,进行合批
(网格顶点数有最大限制,2^16)
缺点:有额外的网格数据,会造成包体+内存的增加
3.GPU实例化
要求网格是一样的
需要硬件API支持(OpenGL3.0以上
单个GPUInstance 对物体也有限制,最多500个左右
可以实现相同网格的大量不同对象进行合批,并且可以属性不一致
1.Shader内 定义常量寄存器
2.C#内,通过 MaterialPropertyBlock
设置属性
代码如下:
Shader "Custom/TA/GPUInstanceTest"
{
Properties
{
_Color("Color", color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//INSTANCING_ON
//内置宏定义,会让面板处开启开关
// #pragma multi_compile_instancing
#pragma multi_compile _ INSTANCING_ON
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
//生成实例id
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// fixed4 _Color;
//自定义属性放到常量寄存器内 prop是名字
UNITY_INSTANCING_BUFFER_START(prop)
// 定义属性 类型:fixed4 名称: _Color
UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
UNITY_INSTANCING_BUFFER_END(prop)
struct v2f
{
float4 pos : SV_POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
v2f vert (appdata v)
{
//需要放在最开始的地方
//1.会设置 unity_InstanceID,后面的函数会用到这个
//2.修改矩阵更新位置 UnitySetupCompoundMatrices
UNITY_SETUP_INSTANCE_ID(v);
v2f o;
//获取内置 instanceID
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//需要放在最开始的地方
//1.会设置 unity_InstanceID,后面的函数会用到这个
UNITY_SETUP_INSTANCE_ID(i);
fixed4 col = UNITY_ACCESS_INSTANCED_PROP(prop, _Color);
return col;
}
ENDCG
}
}
}
c#代码如下
var materialPropertyBlock = new MaterialPropertyBlock();
materialPropertyBlock.SetColor("_Color", new Color(Random.value,Random.value,Random.value,1f));
go.GetComponent<MeshRenderer>().SetPropertyBlock(materialPropertyBlock);
效果如图:(注意Batch为2)