【Unity Shader】三、漫反射Diffuse Shader例子
生活随笔
收集整理的這篇文章主要介紹了
【Unity Shader】三、漫反射Diffuse Shader例子
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
學習目標:
- 漫反射Diffuse Shader,逐頂點計算和逐像素計算。
- 半蘭伯特(HalfLambert)光照模型。
- 結合材質自身的色彩(Material Color)及環境光(Ambient)。
漫反射計算公式:
漫反射Diffuse顏色 = 直射光顏色 * max(0, cos(光源方向和法線方向夾角)) * 材質自身色彩
其中max(0, cos(光源方向和法線方向夾角))部分可以改用半蘭伯特光照模型以增強背光面的光照效果。
?逐頂點漫反射
Shader "Custom/04-Diffuse Vertex" { // 逐頂點漫反射 Properties{_Diffuse("Diffuse Color", Color) = (1,1,1,1) // 可在編輯器面板定義材質自身色彩 }SubShader{Pass {// 只有定義了正確的LightMode才能得到一些Unity的內置光照變量Tags{"LightMode" = "ForwardBase"}CGPROGRAM// 包含unity的內置的文件,才可以使用Unity內置的一些變量 #include "Lighting.cginc" // 取得第一個直射光的顏色_LightColor0 第一個直射光的位置_WorldSpaceLightPos0(即方向) #pragma vertex vert #pragma fragment fragfixed4 _Diffuse; // 使用屬性struct a2v{float4 vertex : POSITION; // 告訴Unity把模型空間下的頂點坐標填充給vertex屬性float3 normal : NORMAL; // 告訴Unity把模型空間下的法線方向填充給normal屬性float4 texcoord : TEXCOORD0; // 告訴Unity把第一套紋理坐標填充給texcoord屬性// POSITON、NORMAL、TEXCOORD0都是Unity內置的變量 };struct v2f{float4 position : SV_POSITION; // 聲明用來存儲頂點在裁剪空間下的坐標float3 color : COLOR; // 用于傳遞計算出來的漫反射顏色
// SV_POSITION、COLOR都是Unity內置的變量 };// 計算頂點坐標從模型坐標系轉換到裁剪面坐標系 v2f vert(a2v v){v2f f;f.position = mul(UNITY_MATRIX_MVP, v.vertex); // UNITY_MATRIX_MVP是內置矩陣。該步驟用來把一個坐標從模型空間轉換到剪裁空間// 環境光fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;// 法線方向。把法線方向從模型空間轉換到世界空間fixed normalDir = normalize(mul(v.normal, (float3x3)unity_WorldToObject)); // 反過來相乘就是從模型到世界,否則是從世界到模型// 光照方向fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 對于每個頂點來說,光的位置就是光的方向,因為光是平行光// 漫反射Diffuse顏色 = 直射光顏色 * max(0, cos(光源方向和法線方向夾角)) * 材質自身色彩fixed3 diffuse = _LightColor0 * max(0, dot(normalDir, lightDir)) * _Diffuse; // 融合材質自身色彩用乘法// 加上環境光f.color = diffuse + ambient; // 顏色疊加用加法(通常亮度會增加)return f;}// 計算每個像素點的顏色值 fixed4 frag(v2f f) : SV_Target {return fixed4(f.color, 1); // f.color是float3已經包含了三個數值 }ENDCG}}FallBack "Diffuse" }
如果去掉自定義的_Diffuse(材質自身色彩)屬性和環境光(Ambient),漫反射顏色值將僅由光源顏色來決定。白色光源的顯示效果如下:
現在想要融合材質自身的顏色值來顯示,編輯器面板選擇一個材質自身的色彩,顯示效果如下:
最后再加上環境光(UNITY_LIGHTMODEL_AMBIENT),能看到變白變亮了,效果如下:
逐像素漫反射
Shader "Custom/05-Diffuse Fragment" { // 逐像素漫反射 Properties{_Diffuse("Diffuse Color", Color) = (1,1,1,1) // 可在編輯器面板定義材質自身色彩 }SubShader{Pass {// 只有定義了正確的LightMode才能得到一些Unity的內置光照變量Tags{"LightMode" = "ForwardBase"}CGPROGRAM// 包含unity的內置的文件,才可以使用Unity內置的一些變量 #include "Lighting.cginc" // 取得第一個直射光的顏色_LightColor0 第一個直射光的位置_WorldSpaceLightPos0(即方向) #pragma vertex vert #pragma fragment fragfixed4 _Diffuse; // 使用屬性struct a2v{float4 vertex : POSITION; // 告訴Unity把模型空間下的頂點坐標填充給vertex屬性float3 normal : NORMAL; // 告訴Unity把模型空間下的法線方向填充給normal屬性float4 texcoord : TEXCOORD0;// 告訴Unity把第一套紋理坐標填充給texcoord屬性 };struct v2f{float4 position : SV_POSITION; // 聲明用來存儲頂點在裁剪空間下的坐標float3 worldNomalDir : COLOR; // 用于存儲世界空間下的法線方向 };// 計算頂點坐標從模型坐標系轉換到裁剪面坐標系 v2f vert(a2v v){v2f f;f.position = mul(UNITY_MATRIX_MVP, v.vertex); // UNITY_MATRIX_MVP是內置矩陣。該步驟用來把一個坐標從模型空間轉換到剪裁空間// 法線方向。把法線方向從模型空間轉換到世界空間f.worldNomalDir = (mul(v.normal, (float3x3)unity_WorldToObject)); // 反過來相乘就是從模型到世界,否則是從世界到模型return f;}// 計算每個像素點的顏色值 fixed4 frag(v2f f) : SV_Target {// 環境光fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;// 法線方向。fixed normalDir = normalize(f.worldNomalDir); // 單位向量// 光照方向。fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 對于每個頂點來說,光的位置就是光的方向,因為光是平行光// 漫反射Diffuse顏色 = 直射光顏色 * max(0, cos(光源方向和法線方向夾角)) * 材質自身色彩fixed3 diffuse = _LightColor0 * max(0, dot(normalDir, lightDir)) * _Diffuse; // 顏色融合用乘法// 加上環境光fixed3 tempColor = diffuse + ambient; // 顏色疊加用加法(亮度通常會增加)return fixed4(tempColor, 1); // tempColor是float3已經包含了三個數值 }ENDCG}}FallBack "Diffuse" }?如下圖,左邊逐像素計算,右邊逐頂點計算,在觀察背光面陰影邊緣時能看出明顯差別,逐頂點計算的陰影過度呈塊狀的。
?半蘭伯特(HalfLambert)光照模型
- http://www.cnblogs.com/2Yous/p/4206959.htm
直接修改上面frag函數中漫反射Diffuse顏色的計算公式。
// 計算每個像素點的顏色值 fixed4 frag(v2f f) : SV_Target {// 環境光fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;// 法線方向。fixed normalDir = normalize(f.worldNomalDir); // 單位向量// 光照方向。fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 對于每個頂點來說,光的位置就是光的方向,因為光是平行光// 半蘭伯特光照float3 halfLambert = dot(normalDir, lightDir) * 0.5 + 0.5; // 使得背光面不至于為0全黑// 漫反射Diffuse顏色 = 直射光顏色 * max(0, cos(光源方向和法線方向夾角)) * 材質自身色彩fixed3 diffuse = _LightColor0 * halfLambert * _Diffuse; // 顏色融合用乘法// 加上環境光fixed3 tempColor = diffuse + ambient; // 顏色疊加用加法(亮度通常會增加)return fixed4(tempColor, 1); // tempColor是float3已經包含了三個數值}可以看到在背光面也有了少量光照,明顯沒有旁邊的對照組那么黑。
?注意點:
- 顏色融合是相乘,顏色疊加是相加(通常亮度會增加)。
- 逐像素計算光照要比逐頂點計算光照更加消耗性能。
學習資料:
- http://www.sikiedu.com/course/37/task/441/show#
?
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的【Unity Shader】三、漫反射Diffuse Shader例子的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shell中的函数、shell中的数组、
- 下一篇: 安卓toast文字提示