好长时间没更新博客了,究其原因,是我想尝试Wiki这种形式来整理知识。总体来说,它还是不错的,不过不适合我。所以,还是回归博客吧。
ShaderLab 是Unity3d自己封装的一个调用CG/HLSL/GLSL的接口。相关信息可以参考:圣典翻译的新手
shaderLab 代码一般遵循以下格式:
Shader "MyShader/ShaderName"
{
Properties {
_Color ("Main Color", Color) = (1,1,1,0.5)
_MainTex ("Texture", 2D) = "white" { }
}
SubShader
{
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
//--snip--
struct v2f {
float4 pos :SV_POSITION;
float3 color : COLOR0;
};
v2f lv1(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.color = v.normal * 0.5 +0.5;
return o;
}
half4 lv2(v2f i) : COLOR
{
return half4(i.color,1);
}
ENDCG
}
}
FallBack "VertexLit"
}
Properties {
`InnerName` ( `showName`,`type`) = `defaultValue`
}
其中类型与默认值对应如下:
以下内容详细可以参考此处
使用 #pragma surface
这个指令可用编写表面着色器。
#pragma surface surfaceFunction lightModel [optionalparams]
所需参数:
surfaceFunction - 表示Cg函数中有表面着色器(surface shader)代码。这个函数的格式应该是这样:
void surf (Input IN,inout SurfaceOutput o)
Input是你自己定义的结构。Input结构中应该包含所有纹理坐标(texture coordinates)和和表面函数(surfaceFunction)所需要的额外的必需变量。
lightModel -在光照模式中使用。内置的是Lambert (diffuse)和 BlinnPhong (specular)。如果想编写自己的光照模式,请参考:自定义光照模式。
对于预定义的宏和函数,Unity将她们放进了许多包含文件中。在Mac上,它的目录为 Contents/CGIncludes/xxx.cginc 例如常用的:UnityCG.cginc, lighting.cginc 等。当然我们也可以自己编写。将文件后缀更改成.cginc
然后在shader中使用#include "YourCGInclude.cginc"
即可。
Input 这个输入结构通常拥有着色器需要的所有纹理坐标(texture coordinates)。纹理坐标(Texture coordinates)必须被命名为“uv”后接纹理(texture)名字。(或者uv2开始,使用第二纹理坐标集)
例如:
Properties {
_MainTex ("Texture", 2D) = "white" {}
_BumpMap ("Bumpmap", 2D) = "bump" {}
}
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
};
sampler2D _MainTex;
sampler2D _BumpMap;
struct SurfaceOutput {
half3 Albedo; //反射率
half3 Normal; //法线
half3 Emission; //自发光,用于增强物体自身的亮度,使之看起来好像可以自己发光
half Specular; //镜面
half Gloss; //光泽
half Alpha; //透明
};
使用Tags可以为subshader指定属性:
Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
详细的属性使用可以参考Unity手册中 subshader tags章节。
在脚本中可以动态设置shader的值,例如:
[ExecuteInEditMode]
public class caller : MonoBehaviour {
public Color diffColor;
void Update()
{
renderer.sharedMaterial.SetColor("_color",diffColor);
}
}
其中,shader中有名为_color的uniform变量 例如:
Shader "Learn/ColorShader" {
Properties {
}
SubShader {
Tags { "Queue"= "Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Pass{
CGPROGRAM
#pragma vertex v2f
#pragma fragment frag
#include "UnityCG.cginc"
uniform fixed4 _color;
struct InputVertex
{
float4 pos : POSITION;
} ;
struct Output
{
float4 pos :SV_POSITION;
float4 col :COLOR0;
} ;
Output v2f(InputVertex input)
{
Output o;
o.pos = mul(UNITY_MATRIX_MVP,input.pos);
o.col = _color;
return o;
}
half4 frag(Output o): COLOR
{
// return half4(1.0,0.4,0.4,1);
return o.col;
}
ENDCG
}
}
FallBack "Diffuse"
}
#pragma surface surf `FuncName`
FuncName
(SurfaceOutput s, half3 lightDir, half atten) {}FuncName
(SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {}FuncName
(SurfaceOutput s, half4 light) {}