Unity multi_compile_instancing

对于大量相同模型的性能优化,在shader方法,可以用gpu instancing方式。

例如这个简单阴影计算的pass,注意里面有很多UNITY_开头的命令

//投影的计算Pass
Pass
{
	Name "Shadow"

	Stencil
	{
		Ref 0
		Comp equal
		Pass incrWrap
		Fail keep
		ZFail keep
	}

	Blend SrcAlpha OneMinusSrcAlpha
	ZWrite Off
	Offset -1, 0

	CGPROGRAM
	#pragma vertex vert
	#pragma fragment frag
	#pragma multi_compile_instancing
	#pragma multi_compile ROOTON_BLENDOFF ROOTON_BLENDON_CROSSFADEROOTON ROOTON_BLENDON_CROSSFADEROOTOFF ROOTOFF_BLENDOFF ROOTOFF_BLENDON_CROSSFADEROOTON ROOTOFF_BLENDON_CROSSFADEROOTOFF

	#include "UnityCG.cginc"
	#include "GPUSkinningInclude.cginc"
	#include "Lighting.cginc"

	struct appdata
	{
		float4 vertex : POSITION;
		//阴影计算的Pass不需要通过UV来采样贴图,所以不需要
		//float2 uv : TEXCOORD0;
		//TEXCOORD1和TEXCOORD2需要通过skin2方法来解析贴图中存放的数据信息,顺序必须对应
		float4 uv2 : TEXCOORD1;
		float4 uv3 : TEXCOORD2;
		UNITY_VERTEX_INPUT_INSTANCE_ID
	};

	struct v2f
	{
		float4 pos : SV_POSITION;
		fixed4 color : COLOR;
		//float2 uv : TEXCOORD0;
	};

	// float4 _LightDir;
	float4 _ShadowColor;
	// fixed _ShadowFalloff;

	UNITY_INSTANCING_BUFFER_START(Prop)
	UNITY_DEFINE_INSTANCED_PROP(float, _shadowY)
	UNITY_INSTANCING_BUFFER_END(Prop)

	float3 ShadowProjectPos(float4 vertPos)
	{
		float3 shadowPos;
		float3 worldPos = mul(unity_ObjectToWorld, vertPos).xyz;
		float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

		float y = UNITY_ACCESS_INSTANCED_PROP(Prop,_shadowY);
		shadowPos.y = min(worldPos.y, y);
		shadowPos.xz = worldPos.xz - lightDir.xz * max(0, worldPos.y - y) / lightDir.y;
		return shadowPos;
	}

	v2f vert(appdata v)
	{
		UNITY_SETUP_INSTANCE_ID(v);
		v2f o;
		//通过skin2得到顶点在物体自身坐标系的位置信息
		float4 position = skin4(v.vertex, v.uv2, v.uv3);
		float3 shadowPos = ShadowProjectPos(position);
		o.pos = UnityWorldToClipPos(shadowPos);

		// float3 center = float3(unity_ObjectToWorld[0].w, _LightDir.w, unity_ObjectToWorld[2].w);
		// shadowPos.y=0;
		// fixed falloff = 1 - saturate(distance(shadowPos, center) * _ShadowFalloff);

		o.color = _ShadowColor;
		// o.color.a *= falloff;

		return o;
	}

	fixed4 frag(v2f i) : SV_Target
	{
		return i.color;
	}
	ENDCG
}

第一要添加 #pragma multi_compile_instancing 编译参数

其次,在appdata中最下面加上 UNITY_VERTEX_INPUT_INSTANCE_ID

第三,在顶点计算里面,最上面加 UNITY_SETUP_INSTANCE_ID(v);

 

如果你还有一些你自己定义的参数,可以这样定义参数
    UNITY_INSTANCING_BUFFER_START(Prop)
    UNITY_DEFINE_INSTANCED_PROP(float, _shadowY)
    UNITY_INSTANCING_BUFFER_END(Prop)

里面的Prop表示这个Buffer的名字,你也可以换成其他

然后你用这个_shadowY的时候,需要这样调用:UNITY_ACCESS_INSTANCED_PROP(Prop,_shadowY);来获取_shadowY的值;

最后最重要的是外部 c#程序怎么设置这个_shadowY参数,最普通的设置是通过Renderer的material去调用setFloat来设置它,但是这种会造成pass增加,达不到我们想要的性能。

所以应该用MaterialPropertyBlock方式来设置_shadowY参数。

 

就算你的shader中有多个pass,有很多个相同的3d模型,drawCall也不会增加。当然drawCall增加可能是用了SkinnedMeshRenderer的原因,你想办法转成MeshRenderer,这不是这篇文章的重点,具体可以搜索GPUSkinning。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ENABLE_UNITY_COLLECTIONS_CHECKS是Unity中的一个编译器宏定义,用于启用Unity Collections库中的线程和处置安全检查。这个宏定义可以确保在使用Unity Collections库时,对于线程安全和资源释放的问题进行检查,以避免潜在的错误。\[1\] Unity Collections库提供了一些关键的类数组类型,如NativeArray和NativeSlice,以及一些数据结构,如NativeList和NativeQueue,这些都受到ENABLE_UNITY_COLLECTIONS_CHECKS宏定义的影响。\[2\] 但是需要注意的是,ENABLE_UNITY_COLLECTIONS_CHECKS主要用于单元测试框架中的断言,而不是用于生产代码的测试。因此,在生产代码中使用这个宏定义可能会导致性能下降,因为它会增加额外的检查和开销。\[3\] #### 引用[.reference_title] - *1* *3* [unity断言_Unity断言库](https://blog.csdn.net/culiao6493/article/details/108642656)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[Unity ECS] Unity Collections Package](https://blog.csdn.net/u013716859/article/details/122278432)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值