为Shader提供属性(也可以认为是变量),可以把控制权交给非程序员。在Unity中,这些属性会显示在Unity的材质球的inspector面板上。
属性类型
数字和Slider
name ("display name", Range (min, max)) = number
name ("display name", Float) = number
name ("display name", Int) = number
颜色和向量
name ("display name", Color) = (number,number,number,number)
name ("display name", Vector) = (number,number,number,number)
图片
name ("display name", 2D) = "defaulttexture" {}
name ("display name", Cube) = "defaulttexture" {}
name ("display name", 3D) = "defaulttexture" {}
详解
- 在Unity中name为shader脚本以及C#脚本可调用的变量,一般约定以_开头。
- display name为inspector面板中展示的名字。
- 对于2D类型图片,defaulttexture可以是空字符串,也可以是内置的默认图片,如:
"white"
(RGBA:1,1,1,1),"black"
(RGBA:0,0,0,)"gray"
(RGBA:0.5,0.5,0.5,0.5)"bump"
(RGBA:0.5,0.5,1,0.5)"red"
(RGBA:1,0,0,0)。 - 对于non-2D图片(Cube,3D,2DArray),默认值是空字符串。当一个材质球没有设置CubeMap/3D/ArrayTexture,一个灰色的会被默认使用。
在固定功能单元(fixed function),属性值可以通过中括号加属性名字的方式:[name]
。
比如你通过声明两个整形变量_SrcBlend和_DstBlend,以达到灵活控制混合模式的目地。然后使用它们的名字设置混合命令:Blend [_SrcBlend] [_DstBlend]
attributes
shader属性可以被attributes修饰,从而控制其在material inspector上的绘制方式。以下为Unity支持的的attributes:
[HideInInspector]
不把属性显示在material inspector上。[NoScaleOffset]
对于shader的texture类型属性,material inspector不再显示texture的tiling和offset区域。[Normal]
表明这里的texture需要的是一个法线贴图[HDR]
表明该texture需要一个high-dynamic range(HDR)贴图[Gamma]
表明一个float或者vector类型的属性需要指定一个sRGB值[PerRendererData]
表明一个texture来自于per-renderer数据(形式为MaterialPropertyBlock)。
TexGen
在Unity5之前,texture属性可以有TexGen CubeReflect
等选项。但是在5.0之后被移除。更多请参考:Implementing Fixed Function TexGen in Shaders
Shader结构
Properties定义在SubShader前,结构:
Properties{
//property1
//property2
}
在SubShader的Pass中,需要使用格式uniform+数据类型+name;
再次声明一次。然后在vertex shader和fragment shader中便可以恣意调用了。
Demo
继上文统一坐标系的shader,改成如下:
Shader "My/ShaderInWorldSpacePlus"
{
Properties{
_Point("a point in world space",Vector)=(0.,0.,0.,1.0)
_DistanceNear("threshold distance",Float)=5.0
_ColorNear("color near to point",Color)=(0.0,1.0,0.0,1.0)
_ColorFar("color far to point",Color)=(0.4,0.1,0.1,1.0)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//uniforms corresponding to properties
uniform float4 _Point;
uniform float _DistanceNear;
uniform float4 _ColorNear;
uniform float4 _ColorFar;
struct vertexInput{
float4 vertex:POSITION;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float4 posWorldSpace:TEXCOORD0;
};
vertexOutput vert (vertexInput input)
{
vertexOutput output;
output.pos=UnityObjectToClipPos(input.vertex);
output.posWorldSpace=mul(unity_ObjectToWorld,input.vertex);
return output;
}
fixed4 frag (vertexOutput input) : COLOR
{
float dis=distance(input.posWorldSpace,_Point);
if(dis<_DistanceNear)
{
return _ColorNear;
}
else
{
return _ColorFar;
}
}
ENDCG
}
}
}
c#脚本调用shader属性
GetComponent<Renderer>().sharedMaterial.SetVector("_Point", new Vector4(1.0f, 0.0f, 0.0f, 1.0f));
GetComponent<Renderer>().sharedMaterial.SetFloat("_DistanceNear", 10.0f);
GetComponent<Renderer>().sharedMaterial.SetColor("_ColorNear", new Color(1.0f, 0.0f, 0.0f));
GetComponent<Renderer>().sharedMaterial.SetColor("_ColorFar", new Color(1.0f, 1.0f, 1.0f));