光照模型
基本光照模型中高光反射部分的計算公式
Mgloss 光澤度,反光度,控制高光區域的大小,值越大,亮點越小
Mspecular 材質的高光反射顏色,它用於控制該材質對於高光反射的強度和顏色
Clight 光源顏色和強度
v 是視角方向
r 是反射方向,可以通過計算反射方向的函數
r = reflect(I,n)
I,入射方向(要求由光源指向交點處)
n 法線方向
r = 2 (n * I)* n - I 菱形
Blinn-Phong 模型的公式
h = normalize(v + I)
實現
逐頂點光照
缺點:高光部分明顯不平滑。主要原因是,高光反射部分的計算是非線性的,而在頂點着色器中計算光照再進行插值的過程是線性的,破壞了原計算的非線性關係,就會出現較大的視覺問題,因此,我們需要使用逐像素的方法來計算高光反射。
Shader "Custom/Shader6_1_sepular_v"
{
// 高光反射,逐頂點光照
// 基礎高光放射模型 Csepular = (Clight * Msepular)max(0, n*r)Mgloss
Properties
{
_Diffuse("Diffuse",color)=(1,1,1,1)
_Sepular("Sepular",color)=(1,1,1,1)
_Gloss("Gloss",Range(0,256))=128
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Sepular;
float _Gloss;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
fixed3 color:COLOR;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.position);
// 環境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// 漫反射
fixed3 worldNormal = normalize(mul(v.normal, (fixed3x3)unity_WorldToObject));
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// 半蘭伯特公式
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (0.5 * dot(worldNormal, worldLightDir) + 0.5);
// 高光反射
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
fixed3 sepular = _LightColor0.rgb * _Sepular.rgb * pow(saturate(dot(worldLightDir, reflectDir)), _Gloss);
o.color = ambient + diffuse + sepular;
return o;
}
fixed4 frag(v2f v):SV_Target
{
return fixed4(v.color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
逐像素光照
使用逐像素的方式處理可以得到更加平滑的高光效果。
Shader "Custom/Shader6_1_sepular_f"
{
// 逐像素光照
Properties
{
_Diffuse("Diffuse",color) = (1,1,1,1)
_Sepular("Sepular",color) = (1,1,1,1)
_Gloss("Gloss",Range(0, 8)) = 4
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Sepular;
float _Gloss;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float3 worldNor:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.position);
o.worldNor = mul(v.normal, (fixed3x3)unity_WorldToObject);
o.worldPos = mul(unity_ObjectToWorld,v.position).xyz;
return o;
}
fixed4 frag(v2f v):SV_Target
{
// 環境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(v.worldNor);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// 漫反射
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (0.5 * (dot(worldNormal, worldLightDir)) + 0.5);
// 反射方向
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
// 視覺方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - v.worldPos.xyz);
// 高光反色
fixed3 sepular = _LightColor0.rgb * _Sepular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
fixed3 c = ambient + diffuse + sepular;
return fixed4(c, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
Blinn-Phong 模型
Blinn-Phong 光照模型的高光反射部分看起來更大、更亮一些。
Shader "Custom/Shader6_2_sep_bp"
{
Properties
{
_Diffuse("Diffuse",color)=(1,1,1,1)
_Specular("Specular",color)=(1,1,1,1)
_Gloss("Gloss",Range(0,20))=10
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float3 worldNor:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.position);
o.worldNor = mul(v.normal, (fixed3x3)unity_WorldToObject);
o.worldPos = mul(unity_ObjectToWorld, v.position).xyz;
return o;
}
fixed4 frag(v2f v):SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNor = normalize(v.worldNor);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNor, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - v.worldPos);
fixed3 h = normalize(viewDir + worldLightDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNor, h)), _Gloss);
return fixed4(ambient + diffuse + specular, 1);
}
ENDCG
}
}
FallBack "Diffuse"
}