好长时间没更新博客了,究其原因,是我想尝试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) {}