1.前言
Unity shader开发中需要用C#给shader代码传值,我使用全局给shader传值的时候发现并没有起作用,这里记录了容易忽视的问题。
2.Shader传递参数
unity中C#向Shader传递参数的方式有以下两种:
1、面向具体Material的SetFloatXXX系列(这个是实例方法)
2、面向全部Shader的SetFloatXXX系列(这个是静态方法)
我这里用的是第二种方法。
3.问题还原
1.首先我为了测试,写了一个简单的改变透明度的shader例子,使用透明度_AlphaScale的值来做传递的参数。代码如下:
Shader "PointCloud" {
Properties{
_AlphaScale("Alpha Scale", Range(0, 1)) = 1 //控制整体的透明度
}
SubShader{
Tags {"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
Pass{
Tags { "LightMode" = "ForwardBase" }
ZWrite Off //关闭深度写入
Blend SrcAlpha OneMinusSrcAlpha //设置混合模式,为普通的方式
LOD 200
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed _AlphaScale; //有默认的uniform
struct VertexInput {
float4 v : POSITION;
float4 color: COLOR;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};
VertexOutput vert(VertexInput v) {
VertexOutput o;
o.pos = UnityObjectToClipPos(v.v);
o.col = v.color;
return o;
}
float4 frag(VertexOutput o) : COLOR{
return o.col* _AlphaScale;
}
ENDCG
}
}
}
2.在Unity中创建一个cube,在创建一个新的材质,将这个Shader赋给这个材质,再将这个材质替换cube本身的材质球。
3.在Unity中创建Slider组件,用Slider组件来控制透明度的值。新建C#脚本,把脚本拖拽到Slider组件上。代码如下:
private Slider slider;
private void Awake()
{
slider = GetComponent<Slider>();
}
private void Start()
{
slider.onValueChanged.AddListener(SliderClick);
}
private void SliderClick(float value)
{
Shader.SetGlobalFloat("_AlphaScale", value);
}
4.运行后,拖拽Slider发现cube的透明度并没有发生变化。
4.解决问题
首先slider传值到shader是没有问题的,问题在于_AlphaScale在Properties中被定义了,这就需要在材质面板上去修改了,相当于我传递的参数全局修改和材质属性修改冲突了,而Properties结构里参数是由CPU传给GPU的,里面的参数在shader代码是没法修改的。所以办法就是把Properties里的_AlphaScale删除或者注释掉。
Properties{
//_AlphaScale("Alpha Scale", Range(0, 1)) = 1 //控制整体的透明度
}
这样就能用slider正确的改变透明度了。