// 1.渲染相同材质,仅使用少量drawCalls,适用于重复的建筑,植被,石头等
// 2.每个实例,可以有不同的参数,如位置,缩放,颜色等等
// 3.需勾选材质上的EnableInstancing,并且使用相关的宏,此时内部会自动执行instancing
// 4.可以使用SetPropertyBlock设置相关属性,达到同材质不同的效果
// 5.可以使用Graphics.DrawMesh....创建对象,达到同材质不同的效果
// tips:
// 1.unity会优先处理static batching,如果处理过sb,unity会禁用instancing,系统会建议禁用sb,在设置界面
// 2.unity处理instancing的优先级高于dynamic batching,如果处理过instance,会禁用这个mesh的动态批处理
// 3.Graphics.DrawMeshInstanced
// 有些因素可能会阻止对象自动instanced,比如材质变化,深度排序等
// 使用Graphics.DrawMeshInstanced可以每帧强制GPU instancing绘制这些物体,最多1023个。
// 4.Graphics.DrawMeshInstancedIndirect
// 无限制,适合PC用
// 5.UnityObjectToClipPos
// 当写shader时用UnityObjectToClipPos(v.vertex)而不是mul(UNITY_MATRIX_MVP,v.vertex)
// 尽管可以继续在instanced Shaders中正常使用UNITY_MATRIX_MVP,
// 但是UnityObjectToClipPos是把顶点位置从对象空间(object sapce)转换到裁剪空间(clip space)的最高效的方式。
// 6.Surface Shaders默认开启instancing varianats,除非指定noinstancing,其他shader定义#pragma multi_compile_instancing
Shader "SimplestInstancedShader"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
[HDR]_EmissionColor ("EmissionColor", Color) = (0.0,0.0,0.0,0.0)
_EmissionSpeed("EmissionSpeed",float) = 0
_EmissionFadeIn("EmissionFadeIn",Range(0 , 1)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing // 使用设置unity生成instancing variants
#include "UnityCG.cginc"
// 假如_Color不作为instancing参数,一旦_Color值不一样时,就会构建新的drawcal
//float4 _Color;
struct appdata
{
float4 vertex : POSITION;
// 如果你想在【顶点函数】中使用实例化参数,则需要在这里定义实例化id
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
float4 color : TEXCOORD1;
// 如果你想在【像素函数】中使用实例化参数,则需要在这里定义实例化id
UNITY_VERTEX_INPUT_INSTANCE_ID
};
// 每一帧的实例属性必须定义在这两个宏中间
// 包装那些你想在不同实例中值不同的属性
UNITY_INSTANCING_BUFFER_START(Props)
// 指定类型和属性名,这些参数可以被外部修改
UNITY_DEFINE_INSTANCED_PROP(float4, _Color)
UNITY_DEFINE_INSTANCED_PROP(half, _EmissionFadeIn)
UNITY_DEFINE_INSTANCED_PROP(half, _EmissionSpeed)
UNITY_DEFINE_INSTANCED_PROP(half4, _EmissionColor)
UNITY_INSTANCING_BUFFER_END(Props)
v2f vert(appdata v)
{
v2f o;
// 如果你想在【顶点函数】中访问参数,则需要在这里使用UNITY_SETUP_INSTANCE_ID
UNITY_SETUP_INSTANCE_ID(v);
// 如果你想在【像素函数】中使用实例化参数,则需要在这里传输参数
UNITY_TRANSFER_INSTANCE_ID(v, o);
o.vertex = UnityObjectToClipPos(v.vertex);
// 在顶点阶段使用实例化参数
float _EmissionFadeIn_Instance = UNITY_ACCESS_INSTANCED_PROP(Props, _EmissionFadeIn);
float _EmissionSpeed_Instance = UNITY_ACCESS_INSTANCED_PROP(Props, _EmissionSpeed);
float4 _EmissionColor_Instance = UNITY_ACCESS_INSTANCED_PROP(Props, _EmissionColor);
o.color = ( _EmissionFadeIn_Instance + ( ( 1.0 - abs( sin( ( _Time.y * _EmissionSpeed_Instance ) ) ) ) * ( 1.0 - _EmissionFadeIn_Instance ) ) ) * _EmissionColor_Instance;
return o;
}
float4 frag(v2f i) : SV_Target
{
// 如果你想在【像素函数】中访问参数,则需要在这里使用UNITY_SETUP_INSTANCE_ID
UNITY_SETUP_INSTANCE_ID(i);
// 使用实例化id在实例化数据数组中访问参数
//float4 color = _Color;
float4 color = UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
float4 col = i.color * color;
return col;
}
ENDCG
}
}
}