上一篇是关于Unity全局光照系统的介绍和使用方法,但是用于测试效果的场景物体都是使用了Standard材质。大部分的builtin-shader都能够支持Unity的全局光照系统,和Lightmap和Light Probe配合工作。而使用surface shader编写的自定义shader不需要做任何额外处理也同样能够支持,这是因为Unity在通过surface shader生成vertex&fragment shader时替我们做了这些处理。但是今天要讨论的是使用vertex&fragment shader编写自定义shader时,如何让我们的shader支持Unity的全局光照系统。
从一个简单的Diffuse Shader开始
我们从一个简单的Diffuse Shader开始,逐步为它加添加代码让它能够支持全局光照。Shader如下:
Shader "Custom/Diffuse"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
_Color("Color Tint", Color) = (0.0, 0.0, 0.0, 0.0)
[HDR]_Emission("Emission", Color) = (0.0, 0.0, 0.0, 0.0)
}
SubShader
{
Tags { "RenderType" = "Opaque" }
// forward base pass
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float4 _Emission;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;// main texture uv
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float3 worldNormal : TEXCOORD2;
SHADOW_COORDS(3)
};
v2f vert(appdata v)
{
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
TRANSFER_SHADOW(o);
return o;
}
float4 frag(v2f i) : SV_Target
{
float4 albedo = tex2D(_MainTex, i.uv) * _Color;
// calculate direct diffuse lighting (Lambert)
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLight = normalize(UnityWorldSpaceLightDir(i.worldPos));
float3 direct = _LightColor0.rgb * saturate(dot(worldNormal, worldLight));
// calculate light attenuation and shadow
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
return float4(_Emission + albedo * direct * atten, 1.0);
}
ENDCG
}
// forward add pass
Pass
{
Tags{ "LightMode" = "ForwardAdd" }
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd_fullshadows
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;// main texture uv
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldPos : TEXCOO