7.Phong 和 BlinnPhong
Lambert漫反射光照模型,這是一個用來模擬粗糙表面對光線的漫反射現象的經驗模型,對于紙張、粗糙墻壁等等來說,這個模型或許夠用,但對于金屬這樣的光滑表面來說,我們就需要使用Phong模型來模擬光滑表面對光線的鏡面反射現象。同Lambert一樣,這個模型也是經驗模型,而且在程序中,我們經常同時使用Lambert和Phong兩個模型,因為在現實世界中,任何表面都會同時發生漫反射和鏡面反射兩種現象,因此我們就要使用兩種模型分別計算兩種反射后的光強(也就是頂點顏色值),是渲染的效果看起來真實一些。但要注意,這樣做并不會帶來真正真實的渲染效果,畢竟這兩種模型都是經驗模型,考慮的都是理想情況下。而Blinn-phong光照模型是基于Phong的修正模型。
設頂點的單位法向量為N,有公式:
R + L = (2N ? L)N ? (這里再次提醒一下,L的方向是由頂點指向光源的)
由這個可以推出:
R = (2N ? L)N - L
因此Phong的公式如下圖左圖所示。
Shader "Study/7_Phong" {Properties{_Color("Main Color", Color) = (1,1,1,1)_SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 1)// 高光顏色_Shininess("Shininess", Range(0.01, 1)) = 0.078125// 高光指數【光澤度】_MainTex("Base (RGB) Gloss (A)", 2D) = "white" {}}SubShader{Tags{ "RenderType" = "Opaque" }LOD 300CGPROGRAM #pragma surface surf BlinnPhongTest// 半角向量和BilnnPhong:使用入射光線和視線的中間平均值,即半角向量,然后使用該半角和法線計算出一個和視角相關的高光。// 相關參數:【lightDir點到光源單位向量】【viewDir點到攝像機單位向量】【atten衰減系數】【_LightColor0場景中平行光的顏色】float4 LightingBlinnPhongTest(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten){// 1.半角向量:求(點到光源+點到攝像機)的單位向量,他們的中間平均值float3 h = normalize(lightDir + viewDir);// 2.漫反射系數【點到光源單位向量與法線向量的余弦值】float diff = max(0, dot(s.Normal, lightDir));// 3.反射向量float3 r = 2 * dot(s.Normal, lightDir) * s.Normal - lightDir;// 4.高光底數【反射向量與視角向量的余弦值】float re = max(0, dot(r, viewDir));// 5.高光系數:根據高光低數和高光指數求得float spec = pow(re, s.Specular * 256) * s.Gloss;float4 c;// 6.最終光照rgb = 漫反射+半角高光c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;return c;}sampler2D _MainTex; // 主材質fixed4 _Color; // 主材質顏色half _Shininess; // 高光指數struct Input {float2 uv_MainTex; // 主材質的UV信息};void surf(Input IN, inout SurfaceOutput o) {// 取主紋理的對應當前像素點的值fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);// Albedo反照率,即物體反射光的數量與外來光數量的比值。// Albedo = 主紋理 x 主色調,反映了物體的基色,與任何光相關的信息(比如diffuse, shiness等)無關o.Albedo = tex.rgb * _Color.rgb; // 顏色紋理=主紋理*主材質顏色// Gloss光滑度[0, 1],用于控制反射的模糊程度,值越大,高光反射越清晰,反之則越模糊,0將無高光效果。// 光滑度的“滑”是面的概念,代表物體整體的光滑程度// 比如說,同樣一塊金屬,在它生銹的過程中,其反射就會慢慢變弱,可以通過Gloss值控制// 實際上它是針對高光計算結果的附加系數o.Gloss = tex.a;o.Alpha = tex.a * _Color.a; // 透明度// Shininess光澤度[0, 1],又叫高光指數或鏡面反射指數,注意,它在SurfaceOutput結構中的命名(Specular)很容易讓人誤解為它是高光強度,其實不然,它是高光指數// 光澤度的“澤”是點的概念,代表物體某個高光點的光澤程度o.Specular = _Shininess; // 越小光澤度越高,0為全白//o.Emission = tex.rgb;}ENDCG}Fallback "VertexLit" }
相比較Phong模型,Blinn-phong模型只適用N?H替換了V?R,但卻獲得了明顯的提高,它能提供比Phong更柔和、更平滑的高光,而且速度上也更快,因此成為很多CG軟件中默認的光照渲染方法,同時也被集成到大多數的圖形芯片中,而且在OpenGL和DirectX 3D的渲染管線中,它也是默認的光照模型。
?
由于這兩個光照模型公式基本相同,所以只解釋一下N?H:
N與前面相同,是頂點的單位法向量,而H則是入射光L和頂點到視點的單位向量的角平分線單位向量,通常也成為半角向量。其計算方法為:
H = (L + V) / (|L + V|)
Shader "Study/7_BlinnPhong" {Properties{_Color("Main Color", Color) = (1,1,1,1)_SpecColor("Specular Color", Color) = (0.5, 0.5, 0.5, 1)// 高光顏色_Shininess("Shininess", Range(0.01, 1)) = 0.078125// 高光指數【光澤度】_MainTex("Base (RGB) Gloss (A)", 2D) = "white" {}}SubShader{Tags{ "RenderType" = "Opaque" }LOD 300CGPROGRAM #pragma surface surf BlinnPhongTest// 半角向量和BilnnPhong:使用入射光線和視線的中間平均值,即半角向量,然后使用該半角和法線計算出一個和視角相關的高光。// 相關參數:【lightDir點到光源單位向量】【viewDir點到攝像機單位向量】【atten衰減系數】【_LightColor0場景中平行光的顏色】float4 LightingBlinnPhongTest(SurfaceOutput s, float3 lightDir, float3 viewDir, float atten){// 1.半角向量:求(點到光源+點到攝像機)的單位向量,他們的中間平均值float3 h = normalize(lightDir + viewDir);// 2.漫反射系數【點到光源單位向量與法線向量的余弦值】float diff = max(0, dot(s.Normal, lightDir));// 3.高光底數【半角向量與法線向量的余弦值】float nh = max(0, dot(s.Normal, h));// 4.高光系數:根據高光低數和高光指數求得float spec = pow(nh, s.Specular * 256) * s.Gloss;float4 c;// 5.最終光照rgb = 漫反射+半角高光c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten * 2);c.a = s.Alpha + _LightColor0.a * _SpecColor.a * spec * atten;return c;}sampler2D _MainTex; // 主材質fixed4 _Color; // 主材質顏色half _Shininess; // 高光指數struct Input {float2 uv_MainTex; // 主材質的UV信息};void surf(Input IN, inout SurfaceOutput o) {// 取主紋理的對應當前像素點的值fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);// Albedo反照率,即物體反射光的數量與外來光數量的比值。// Albedo = 主紋理 x 主色調,反映了物體的基色,與任何光相關的信息(比如diffuse, shiness等)無關o.Albedo = tex.rgb * _Color.rgb; // 顏色紋理=主紋理*主材質顏色// Gloss光滑度[0, 1],用于控制反射的模糊程度,值越大,高光反射越清晰,反之則越模糊,0將無高光效果。// 光滑度的“滑”是面的概念,代表物體整體的光滑程度// 比如說,同樣一塊金屬,在它生銹的過程中,其反射就會慢慢變弱,可以通過Gloss值控制// 實際上它是針對高光計算結果的附加系數o.Gloss = tex.a;o.Alpha = tex.a * _Color.a; // 透明度// Shininess光澤度[0, 1],又叫高光指數或鏡面反射指數,注意,它在SurfaceOutput結構中的命名(Specular)很容易讓人誤解為它是高光強度,其實不然,它是高光指數// 光澤度的“澤”是點的概念,代表物體某個高光點的光澤程度o.Specular = _Shininess; // 越小光澤度越高,0為全白//o.Emission = tex.rgb;}ENDCG}Fallback "VertexLit" }總結
以上是生活随笔為你收集整理的7.Phong 和 BlinnPhong的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大学生能申请信用卡吗?大学办信用卡全攻略
- 下一篇: 代办大额度信用卡靠谱吗?警惕三个套路远离