目录
一、如何使用属性
例子
ShaderLab中的属性的类型和Cg中的变量的类型之间的匹配关系
二、Unity提供的内置文件和变量
内置的包含文件
内置的变量
一、如何使用属性
在一开始我们提到过,材质和UnityShader之间有着密切的练习,我们可以通过材质面板调节属性来达到我们需要的效果,而这些属性就需要写在Properties语义块中。
例子
在上一节的例子基础上,现在我们有这样一个需求,需要在材质面板中显示一个颜色拾取器来调节模型在屏幕上显示的颜色,我们修改上一节的代买如下:
Shader "Unity Shaders Book/Simple Shader"{
Properties{
//声明一个Color类型的属性
_Color("Color Tint",Color)=(1.0,1.0,1.0,1.0)
}
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//在Cg代码中我们需要定义一个与属性名称和类型都匹配的变量
fixed4 _Color;
//使用一个结构体来定义顶点着色器的输入
struct a2v {
//POSITION语义告诉Unity用模型空间的顶点坐标填充vertex变量
float4 vertex:POSITION;
//NORMAL语义告诉Unity用模型空间的法线方向填充normal变量
float3 normal:NORMAL;
//TEXCOORF0语义告诉Unity用模型的第一套纹理坐标填充texcoord变量
float4 texcoord:TEXCOORD0;
};
//使用一个结构体来定义顶点着色器的输入
struct v2f{
//SV_POSITION语义告诉Unity,pos里包含了顶点在裁剪空间中的位置信息
float4 pos:SV_POSITION;
//COLOR0语义可以用于存储颜色信息
fixed3 color:COLOR0;
};
v2f vert(a2v v){
//声明输出结构
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
//v.normal包含了顶点的法线方向,其分量范围在【-1.0,1.0】
//下面的代码把分量范围映射到了[0.0,1.0]
//存储到o.color中传递给片元着色器
o.color=v.normal*0.5+fixed3(0.5,0.5,0.5);
return o;
}
float4 frag(v2f i):SV_Target{
fixed3 c=i.color;
//使用_Color属性来控制输出颜色
c*=_Color.rgb;
return fixed4(c,1.0);
}
ENDCG
}
}
}
效果:
代码解释:
在上面的代码中,我们先添加了Properties语义块,在里面声明了一个属性_Color,它的类型是Color类型,默认值是(1.0,1.0,1.0,1.0),即为白色。为了在Cg代码中访问它,我们还需要在Cg代码片段中提前定义一个新的变量,这个变量的名称和类型必须与Properties语义块中的属性定义相匹配。
ShaderLab中的属性的类型和Cg中的变量的类型之间的匹配关系
ShaderLab属性类型 | Cg变量类型 |
Color,Vector | float4,half4,fixed4 |
Range,Float | float,half,fixed |
2D | sampler2D |
Cube | samplerCube |
3D | sampler3D |
有时候Cg变量前面会有一个uniform关键字,如:
uniform fixed4 _Color;
uniform关键字是Cg中修饰变量和参数的一种修饰词,它仅仅用于提供一些关于该变量的初始值是如何指定和存储相关信息,在UnityShader中它可以省略。
二、Unity提供的内置文件和变量
顶点/片元着色的复杂之处在于很多事情需要我们自己动手,例如我们需要自己转换法线方向,自己处理光照、阴影等,为了便利开发,Unity内置了很多文件,这些文件包含了很多提前定义好的变量、函数和宏等。
内置的包含文件
包含文件(include file),这是类似于C++中头文件的一种文件。在Unity中,它们的后缀是.cginc。在编写Shader时,我们可以使用#include指令把这些文件包含进来,这样就可以使用Unity为我们提供的一些非常有用的变量和帮助函数。
如:
CGPROGRAM
//...
#include "UnityCG.cginc"
//...
ENDCG
内置的变量
之前在坐标变换中给出的一些内置变量(点击查看),同样也有一些摄像机参数的内置变量,后续遇到时会进行讲解。