自发光: c e m i s s i v e c_{emissive} cemissive
高光发射: c s p e c u l a r c_{specular} cspecular
漫反射: c d i f f u s e c_{diffuse} cdiffuse
环境光: c a m b i e n t c_{ambient} cambient
一、漫反射
1.1 兰伯特模型
c d i f f u s e = ( c l i g h t ⋅ m d i f f u s e ) m a x ( 0 , n ^ ⋅ l ^ ) c_{diffuse}=(c_{light}\cdot m_{diffuse})max(0,\widehat{n}\cdot \widehat{l}) cdiffuse=(clight⋅mdiffuse)max(0,n
⋅l
)
其中, c l i g h t c_{light} clight是光源颜色和强度, m d i f f u s e m_{diffuse} mdiffuse是漫反射系数, n ^ \widehat{n} n
是表面法线, l ^ \widehat{l} l
是指向光源的单位矢向量。
m a x max max函数可以用 s a t u r a t e ( x ) saturate(x) saturate(x)函数实现。
实践
逐顶点:
Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex-Level" {
Properties {
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
}
SubShader {
Pass {
//光照模式
Tags {
"LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
struct a2v {
float4 vertex : POSITION;
//顶点法线
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
fixed3 color : COLOR;
};
v2f vert(a2v v) {
v2f o;
// Transform the vertex from object space to projection space
o.pos = UnityObjectToClipPos(v.vertex);
// Get ambient term
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// Transform the normal from object space to world space
//因为法线直接用变换矩阵不能保证变换后垂直,所以用原变换矩阵的逆转置矩阵
fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
// Get the light direction in world space
//_WorldSpaceLightPos0是假设只有一个光源且是平行光
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
// Compute diffuse term
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal