Phong光照模型的Shader實現
阿新 • • 發佈:2017-10-05
nor text normalize graph www img 由於 2.0 平行四邊形
計算反射向量
Phong用到的是反射向量,計算反射向量的公式是 R = 2*N(dot(N, L)) - L 這個公式是根據向量的投影公式以及平行四邊形法則推導出來的 詳細步驟請看這篇文章,講的非常好 http://www.cnblogs.com/graphics/archive/2013/02/21/2920627.htmlShader "Phong"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Specular("Specular", Range(1, 20)) = 1
_SpecColor("SpecColor", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 normal : TEXCOORD1;
float3 lightDir : TEXCOORD2;
float4 objPos : TEXCOORD3;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _LightColor0;
float _Specular;
float4 _SpecColor;
v2f vert (appdata_full v)
{
v2f o;
o.objPos = v.vertex;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.normal = v.normal;
o.lightDir = ObjSpaceLightDir(v.vertex);//把光向量從世界空間轉成模型空間
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 L = normalize(i.lightDir);
float3 N = normalize(i.normal);
float3 viewDir = normalize(ObjSpaceViewDir(i.objPos));//計算出視線
float diff = saturate(dot(L, N));
float3 reflection = normalize(2.0 * N * diff - L);//反射向量
float spec = pow(max(0, dot(reflection, viewDir)), _Specular);
float3 finalSpec = _SpecColor.rgb * spec;
//漫反射+鏡面高光+環境光
float3 finalLight = diff * _LightColor0 + finalSpec + UNITY_LIGHTMODEL_AMBIENT;
fixed4 col = tex2D(_MainTex, i.uv);
return col * float4(finalLight, 1);
}
ENDCG
}
}
}
Blinn-phong光照模型
blinn是一個人的名字,他叫吉姆·布林,圖形學界的大牛,他發現了使用半角向量代替反射向量的計算方式 原理是通過視線向量跟光向量的半角向量代替反射向量 halfVector = normalize( L + V ); http://blog.csdn.net/herox25000/article/details/50491483
求反射向量
在圖形學中,計算光照模型時,經常需要求取反射向量,一般的shader函數庫都提供計算反射向量的方法,下面介紹一下如何手動計算反射向量。
給定入射光線向量I和平面法向量N,求反射向量R,如下圖。為了方便計算,這裏假定I和N都是單位向量(模為1,編程時可先將I和N單位化)
方法一
設入射光線向量I和反射平面的法向量N之間的夾角為theta。連接I的始端和R的末端,則有
R = 2P - I (1)
現在問題變成了如何求取P,設入射點0到P與N的交點的向量為S,那麽有
P = I + S (2)
現在問題變成了如何求取向量S,向量S即向量-N(註意,這裏是-N,因為S和N的方向相反。)在向量N上的投影,根據向量的投影公式有
因為N是單位向量,簡化一下得到
將S代入公式(2),再將P代入公式(1)得到
方法二
將R平移一下,與向量N的延長線相交。
由於入射角和反射角相等,且I和R的長度也相等,所以三角形ION是等腰三角形。故有
ON = 2S
所以有
R = I + 2S
而S是-I在N上的投影,所以有
由於N是單位向量,簡化一下得到
所以
貌似方法二更直觀些。
Phong光照模型的Shader實現