Unity URP中如何为自定义Shader添加纹理实例化属性?
纹理实例化属性实现方案
1. Shader内的声明与采样实现
首先在Shader的Properties块中声明纹理占位(即使是实例化属性,也需要这个关联后续的采样器),然后在实例化缓冲区中添加纹理和对应的缩放偏移属性:
Properties { // 保留你原有的属性... [HideInInspector]_CustomPatternTex("Custom Pattern", 2D) = "white" {} } CGPROGRAM // 确保开启实例化编译指令 #pragma multi_compile_instancing // 其他URP相关编译指令... struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID // 必须添加以支持实例化属性访问 }; struct v2f { float2 uv : TEXCOORD0; float4 pos : SV_POSITION; UNITY_VERTEX_OUTPUT_STEREO }; // 实例化缓冲区 UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(half, _Injury) UNITY_DEFINE_INSTANCED_PROP(half4, _Custom1) UNITY_DEFINE_INSTANCED_PROP(half4, _Custom2) // 声明实例化纹理采样器 UNITY_DEFINE_INSTANCED_PROP(sampler2D, _CustomPatternTex) // 对应纹理的缩放偏移属性,必须一起声明 UNITY_DEFINE_INSTANCED_PROP(float4, _CustomPatternTex_ST) UNITY_INSTANCING_BUFFER_END(Props) v2f vert(appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); // 初始化实例ID UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); o.pos = TransformObjectToHClip(v.vertex); o.uv = v.uv; return o; } half4 frag(v2f i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); // 片元函数中初始化实例ID // 获取当前实例的纹理和ST参数 sampler2D patternTex = UNITY_ACCESS_INSTANCED_PROP(Props, _CustomPatternTex); float4 patternST = UNITY_ACCESS_INSTANCED_PROP(Props, _CustomPatternTex_ST); float2 adjustedUV = TRANSFORM_TEX(i.uv, _CustomPatternTex); // 采样纹理 half4 patternColor = tex2D(patternTex, adjustedUV); // 结合原有逻辑(示例:混合自定义颜色与受伤等级) half4 baseColor = UNITY_ACCESS_INSTANCED_PROP(Props, _Custom1); half injury = UNITY_ACCESS_INSTANCED_PROP(Props, _Injury); baseColor = lerp(baseColor, half4(1,0,0,1), injury); // 混合图案颜色 half4 finalColor = baseColor * patternColor; return finalColor; } ENDCG
2. C#脚本设置实例化纹理
通过MaterialPropertyBlock给单个对象设置实例化纹理,不会影响其他使用同一材质的对象:
using UnityEngine; public class AssignInstanceTexture : MonoBehaviour { [SerializeField] private Texture2D customPattern; [SerializeField] private Vector2 textureScale = Vector2.one; [SerializeField] private Vector2 textureOffset = Vector2.zero; private void Awake() { var renderer = GetComponent<Renderer>(); var propertyBlock = new MaterialPropertyBlock(); // 先读取当前对象已有的属性,避免覆盖其他实例化参数 renderer.GetPropertyBlock(propertyBlock); // 设置实例化纹理 propertyBlock.SetTexture("_CustomPatternTex", customPattern); // 可选:单独设置纹理的缩放和偏移 propertyBlock.SetVector("_CustomPatternTex_ST", new Vector4(textureScale.x, textureScale.y, textureOffset.x, textureOffset.y)); // 应用属性块 renderer.SetPropertyBlock(propertyBlock); } }
关键注意事项
- 必须在Shader的Pass中添加
#pragma multi_compile_instancing指令,同时在顶点/片元函数中添加UNITY_SETUP_INSTANCE_ID初始化实例ID,否则无法正确访问实例化属性。 - 实例化纹理的采样器必须和对应的
_ST偏移缩放属性一起声明,TRANSFORM_TEX宏依赖这个参数计算正确的UV。 - 确保Renderer组件开启了GPU Instancing(URP下默认启用,可在Inspector面板确认)。
- 不同平台对实例化缓冲区的大小有限制,建议控制实例化纹理的数量(一般不超过4个)。
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

