漫反射计算公式(兰伯特光照)
Cdiffuse=(Clight*Mdiffuse)*saturate(dot(n,l));
dot(a,b)点积计算公式
Clight:入射光顏色和強度
Mdiffuse:材質漫反射係數
n:單位法線向量
l:單位光源向量
saturate:取最大值函數,防止點積結果為負,即小於零時(背向)不計算
用到的Unity内置函数和变量
UnityObjectToClipPos:把頂點從模型空間轉換到齊次裁剪空間下
UNITY_LIGHTMODEL_AMBIENT:環境光
unity_WorldToObject:世界到模型空間轉換矩陣
_WorldSpaceLightPos0:光源方向
_LightColor0:入射光顏色和強度
代码
//命名
Shader "Test"{
//聲明屬性
Properties{
_Diffuse("Diffuse",Color)=(1,1,1,1)
}
//根據平台選擇可以運行的subshader,一個shader代碼中可以有多個Subshader
SubShader{
pass{//一次頂點和片元函數的處理即一次繪製
Tags{"LightMode"="ForwardBase"}//tags用於定義該pass在渲染中的角色
//定義 LightMode 用於獲取Unity的內置光照變量
CGPROGRAM //同ENDCG組合定義代碼片段,shader格式
//定義頂點函數名字
#pragma vertex vert
//定義片元函數名字
#pragma fragment frag
//引入Unity內置文件,為了使用Unity內置變量
#include "Lighting.cginc"
fixed4 _Diffuse;//在Properties中定義的屬性在此要有對應的變量,名稱要一致
//Application To Vertex
struct a2v{
// 定義變量,後面是對變量的作用的定義
float4 vertex :POSITION;
float4 normal:NORMAL;
};
struct v2f{
float4 pos:SV_POSITION;
fixed3 color:COLOR;
};
//頂點函數(a2v v)表明v是從應用層傳來的信息
v2f vert(a2v v){
v2f o;
//UnityObjectToClipPos把頂點從模型空間轉換到齊次裁剪空間下
o.pos=UnityObjectToClipPos(v.vertex);
//獲取環境光
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
//unity_WorldToObject世界到模型空間轉換矩陣,放在mul(a,b)b的位置意味著從模型空間到世界空間的轉換
//獲取法線的單位向量
fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject));
//獲取光源方向,此時只有一個平行光(若為其他光源類型或多個光源則不適用)
fixed3 worldLight=normalize(_WorldSpaceLightPos0.xyz);
//計算漫反射
fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLight));
//加上環境光
o.color=ambient+diffuse;
return o;
}
//片元函數 SV_TARGET定義函數返回的fixed4為下一渲染步驟所使用的
fixed4 frag(v2f i):SV_TARGET{
return fixed4(i.color,1.0);
}
ENDCG
}
}
//如果其他Subshader皆不可用,調用Unity內置“Diffuse”shader
Fallback "Diffuse"
}``
效果图
1为标准材质球,2为漫反射逐顶点材质(无阴影)