文章目录
- 前言
- 一、优化前是对使用了相同材质球的不同物体间shader分别设置,比较消耗性能
- 二、使用[PerRendererData]标签,可以在脚本中使用SetPropertyBlock()对使用同一材质球的不同物体进行修改其Shader属性
前言
Unity中Shader特性PerRendererData
一、优化前是对使用了相同材质球的不同物体间shader分别设置,比较消耗性能
这里在shader中使用一个Color属性进行测试
Shader"MyShader/P1_1_3"
{
Properties
{
//命名要按标准来,这个属性才可以和Unity组件中的属性产生关联
//比如说,在更改 Image 的源图片时,同时更改这个
[PerRendererData]_MainTex("MainTex",2D) = "white"{}
[PerRendererData]_Color("Color",color) = (1,1,1,1)
}
SubShader
{
//更改渲染队列(UI的渲染队列一般是半透明层的)
Tags {"Queue" = "TransParent"}
//混合模式
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
//存储 应用程序输入到顶点着色器的信息
struct appdata
{
//顶点信息
float4 vertex:POSITION;
float2 uv : TEXCOORD;
};
//存储 顶点着色器输入到片元着色器的信息
struct v2f
{
//裁剪空间下的位置信息
float4 pos:SV_POSITION;
float2 uv : TEXCOORD;
};
sampler2D _MainTex;
fixed4 _Color;
v2f vert(appdata v)
{
v2f o;
//把顶点信息转化到裁剪坐标下
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 mainTex = tex2D(_MainTex,i.uv);
return mainTex * _Color;
}
ENDCG
}
}
}
测试脚本
public class ShaderMaterialPropertyBlockTest : MonoBehaviour
{
[Header("生成的对象")] public GameObject gameObj;
[Header("生成数量")] public int count = 100;
[Header("生成范围")] public float range = 10;
private GameObject [] gameObjects;
private MaterialPropertyBlock prop;
void Start()
{
gameObjects = new GameObject[count];
prop = new MaterialPropertyBlock();
for (int i = 0;i < count;i++)
{
//随机位置并生成对象
Vector2 pos = Random.insideUnitCircle * range;
GameObject go = Instantiate(gameObj, new Vector3(pos.x, 0, pos.y),Quaternion.identity);
gameObjects[i] = go;
}
}
void Update()
{
//优化前,直接修改Shader中暴露的属性
for (int i = 0;i < gameObjects.Length;i++)
{
float r = Random.Range(0f,1f);
float g = Random.Range(0f,1f);
float b = Random.Range(0f,1f);
Color newColor = new Color(r, g, b, 1);
gameObjects[i].GetComponentInChildren<MeshRenderer>().material.SetColor("_Color",newColor);
}
}
}
效果(window->Analysis->Profilte):
二、使用[PerRendererData]标签,可以在脚本中使用SetPropertyBlock()对使用同一材质球的不同物体进行修改其Shader属性
测试脚本
public class ShaderMaterialPropertyBlockTest : MonoBehaviour
{
[Header("生成的对象")] public GameObject gameObj;
[Header("生成数量")] public int count = 100;
[Header("生成范围")] public float range = 10;
private GameObject [] gameObjects;
private MaterialPropertyBlock prop;
void Start()
{
gameObjects = new GameObject[count];
prop = new MaterialPropertyBlock();
for (int i = 0;i < count;i++)
{
//随机位置并生成对象
Vector2 pos = Random.insideUnitCircle * range;
GameObject go = Instantiate(gameObj, new Vector3(pos.x, 0, pos.y),Quaternion.identity);
gameObjects[i] = go;
}
}
void Update()
{
//优化前,直接修改Shader中暴露的属性
/*for (int i = 0;i < gameObjects.Length;i++)
{
float r = Random.Range(0f,1f);
float g = Random.Range(0f,1f);
float b = Random.Range(0f,1f);
Color newColor = new Color(r, g, b, 1);
gameObjects[i].GetComponentInChildren<MeshRenderer>().material.SetColor("_Color",newColor);
}*/
//优化后,使用MaterialPropertyBlock方案
//该方案需要在Shader暴露属性中加上 [PerRendererData] 标签
//这个是配合 SetPropertyBlock(prop);来使用的
//这个可以用来更改同样材质球,都是不同物体的Shader属性
for (int i = 0;i < gameObjects.Length;i++)
{
float r = Random.Range(0f,1f);
float g = Random.Range(0f,1f);
float b = Random.Range(0f,1f);
Color newColor = new Color(r, g, b, 1);
var mr = gameObjects[i].GetComponentInChildren<MeshRenderer>();
mr.GetPropertyBlock(prop);
prop.SetColor("_Color",newColor);
mr.SetPropertyBlock(prop);
}
}
}
优化后效果: