如何建立一個購物網(wǎng)站360網(wǎng)站排名優(yōu)化
目錄
一、本節(jié)介紹
1 上集回顧
2 本節(jié)介紹
二、什么是漫反射材質(zhì)球
三、 漫反射進(jìn)化史
1 三種算法結(jié)果的區(qū)別
2 具體算法
2.1?蘭伯特逐頂點(diǎn)算法
a.本小節(jié)使用的unity自帶結(jié)構(gòu)體。
b.蘭伯特逐頂點(diǎn)算法公式
c.代碼實(shí)現(xiàn)——蘭伯特逐頂點(diǎn)算法
2.2 代碼實(shí)現(xiàn)——蘭伯特逐像素算法
a.像素和頂點(diǎn)算法的區(qū)別
b.實(shí)現(xiàn)代碼
?2.3?代碼實(shí)現(xiàn)——半蘭伯特算法
a.為什么會出現(xiàn)半蘭伯特
b.半蘭伯特公式
c.代碼實(shí)現(xiàn)
四、下集介紹
一、本節(jié)介紹
1 上集回顧
本集講了如何讓圖片和外部顏色疊加顯示。
2 本節(jié)介紹
如何做一個漫反射材質(zhì)球。
二、什么是漫反射材質(zhì)球
1 之前的顏色材質(zhì)球
我們目前只學(xué)過直接上色的材質(zhì)球(如圖1所示),還有上節(jié)課的顏色和圖片疊加的材質(zhì)球。

2 現(xiàn)實(shí)的光照下的球
現(xiàn)實(shí)光照下的大部分材質(zhì)球并不是純色且全亮的,而是(如圖2所示)。

?這種模擬大部分現(xiàn)實(shí)世界物體發(fā)光的狀態(tài),就是漫反射材質(zhì)球。
備注:
反射有兩種:鏡面反射和漫反射。像鏡子的反光,非常光滑的物體反光(比如金屬),屬于鏡面反射,其他大部分是漫反射。具體區(qū)別詳見初中物理~自己百度哦o(* ̄︶ ̄*)o
三、 漫反射進(jìn)化史
我們算到最后,對屏幕來說,僅僅想知道,我這個點(diǎn)應(yīng)該用什么顏色。
所以,對這個顏色的計算出現(xiàn)了三種解法。
- 蘭伯特逐頂點(diǎn)算法
- 蘭伯特逐像素算法
- 半蘭伯特算法
備注:蘭伯特是個人,他和別人一起研究出來了以上三個定律。
1 三種算法結(jié)果的區(qū)別
蘭伯特逐頂點(diǎn)算法(白色和黑色交界處有些方塊塊的感覺、照不到的地方全黑)
蘭伯特逐像素算法(白色和黑色交界處平滑過渡、照不到的地方全黑)
半蘭伯特算法(白色和黑色交界處平滑過渡、照不到的地方不是全黑)
內(nèi)容參考(侵權(quán)立刪):
Unity Shader 漫反射(Lambert、Half Lambert) - 知乎

2 具體算法
2.1?蘭伯特逐頂點(diǎn)算法
a.本小節(jié)使用的unity自帶結(jié)構(gòu)體。
struct appdata_full {float4 vertex : POSITION; //頂點(diǎn)坐標(biāo)float4 tangent : TANGENT; //切線float3 normal : NORMAL; //法線float4 texcoord : TEXCOORD0; //第一紋理坐標(biāo)float4 texcoord1 : TEXCOORD1;//第二紋理坐標(biāo)float4 texcoord2 : TEXCOORD2;//第三紋理坐標(biāo)float4 texcoord3 : TEXCOORD3;//第四紋理坐標(biāo)fixed4 color : COLOR; //頂點(diǎn)顏色UNITY_VERTEX_INPUT_INSTANCE_ID //ID信息
};
b.蘭伯特逐頂點(diǎn)算法公式
公式解釋:
屏幕上對應(yīng)點(diǎn)的顏色 = (光的顏色*物體的顏色)*max(0,該點(diǎn)的法向量*該點(diǎn)的光照方向)
備注(max函數(shù)解釋):
max(a,b),如果這里面a大,答案就是a
如果b大,答案就是b。
例:
max(5,20)=20
max(8,-9)=8
此處的作用:
因?yàn)轭伾珱]有負(fù)數(shù),如果n*l算出來小于0的時候,就直接為0,其他時候就是n*l的值。
其實(shí)就是起一個“一刀切”掉負(fù)數(shù)的作用。
得出結(jié)論:我們想計算漫反射的時候屏幕顯示什么顏色,我們需要光的顏色、物體的顏色、該點(diǎn)的法向量(單位向量)、該點(diǎn)的光照方向(單位向量)。
備注:公式里的字母上帶^就是單位向量的意思。
c.代碼實(shí)現(xiàn)——蘭伯特逐頂點(diǎn)算法
計算注意事項(xiàng):
在計算n*l時,注意:該點(diǎn)的法向量(往往直接獲取的是物體本地坐標(biāo)),該點(diǎn)的光照方向(往往獲取的是世界坐標(biāo))
這樣是不能乘的,所以需要把他們都換算到一個坐標(biāo)系,這里換算到世界坐標(biāo)下。
會用到的方法:
UnityObjectToWorldNormal() //把物體的法線坐標(biāo),換算到世界坐標(biāo)下
normalize() //把任何一個向量變成單位向量
dot() //點(diǎn)乘
max() //上文講過_WorldSpaceLightPos0 //世界坐標(biāo)下的光線坐標(biāo)//但是要引用#include "Lighting.cginc"才能找到
?實(shí)現(xiàn)的代碼:
SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"//新的引用#include "Lighting.cginc"//返回結(jié)構(gòu)體 //引用結(jié)構(gòu)體appdata_full vert (appdata_full v){ //模型頂點(diǎn)坐標(biāo)轉(zhuǎn)屏幕坐標(biāo)v.vertex = UnityObjectToClipPos(v.vertex);//獲取法線坐標(biāo)并轉(zhuǎn)換成世界坐標(biāo)下的法線坐標(biāo)float3 worldNormal = UnityObjectToWorldNormal(v.normal);//世界坐標(biāo)下的光線坐標(biāo) //單位化坐標(biāo) //獲取世界坐標(biāo)下的光線坐標(biāo)float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);//上面的公式float3 diffuse =_LightColor0.rgb * v.color.rgb * max(0,dot(worldNormal,worldLight));//算出的值給顏色v.color = float4(diffuse,1);return v;}float4 frag (appdata_full v) : SV_Target{ //輸出顏色 return float4(v.color,1) ;}ENDCG}}
2.2 代碼實(shí)現(xiàn)——蘭伯特逐像素算法
a.像素和頂點(diǎn)算法的區(qū)別
- 從寫法角度來看,頂點(diǎn)算法是在頂點(diǎn)著色器中寫的,像素算法是在片元著色器中寫的。
- 從原理角度來說,因?yàn)轫旤c(diǎn)是初始值,經(jīng)過一系列計算后,數(shù)據(jù)就會和我們想要的有些偏差。
例:讓你拿筆寫一個字,你可能就寫了,但是讓你拿竹竿上面綁個中性筆寫字,你就寫不準(zhǔn)了,肯定是離畫出來的地方越近,畫出來越是自己想要的。
結(jié)論:像素著色器離最后的顯示比較近,所以出來的結(jié)果和我們想要的更一致。
b.實(shí)現(xiàn)代碼
Shader "Unlit/005_1"
{SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"appdata_full vert (appdata_full v){ v.vertex = UnityObjectToClipPos(v.vertex);//把法線轉(zhuǎn)換成世界坐標(biāo),傳進(jìn)去v.normal = UnityObjectToWorldNormal(v.normal);return v;}float4 frag (appdata_full v) : SV_Target{//法線世界坐標(biāo)float3 worldNormal = v.normal;//光線世界坐標(biāo)float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);//計算顏色float3 diffuse =_LightColor0.rgb * v.color.rgb * max(0,dot(worldNormal,worldLight));//把顏色傳進(jìn)去return float4(diffuse,1) ;}ENDCG}}
}
?2.3?代碼實(shí)現(xiàn)——半蘭伯特算法
a.為什么會出現(xiàn)半蘭伯特
蘭伯特的兩個算法,得到的球,在沒有光線照射的時候都是黑色的,但玩游戲的時候往往希望,雖然光線無法照到,但我們可以看見。
數(shù)學(xué)知識:公式中的n*l值的范圍是【-1,1】之間,我們希望把這個區(qū)間改成【0,1】(前面的課學(xué)過),【-1,1】*0.5+0.5,就可以轉(zhuǎn)成【0,1】,0的時候就是之前光照模型中黑色部分,越靠近1越亮。
因?yàn)槲覀儗?shí)際上并不是需要它看不見,只是需要它要明暗變化,所以我們在環(huán)境光的基礎(chǔ)上加上蘭伯特公式計算出的值,就有了明暗變化。
于是就出現(xiàn)了第三種,半蘭伯特。
b.半蘭伯特公式
在上圖基礎(chǔ)上:
最終顏色??= 環(huán)境光+Cdiffuse
c.代碼實(shí)現(xiàn)
這里其他代碼都沒有變,只更改了上圖0.5的部分。最后輸出前,再加入環(huán)境光。
備注:
獲取環(huán)境光強(qiáng)度的方法:UNITY_LIGHTMODEL_AMBIENT.xyz
Shader "Unlit/005_2"
{SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#include "Lighting.cginc"appdata_full vert (appdata_full v){v.vertex = UnityObjectToClipPos(v.vertex);v.normal = UnityObjectToWorldNormal(v.normal);return v;}float4 frag (appdata_full v) : SV_Target{float3 worldNormal = v.normal;float3 worldLight = normalize(_WorldSpaceLightPos0.xyz);//本節(jié)變動//獲取環(huán)境光float3 anbient = UNITY_LIGHTMODEL_AMBIENT.xyz;//計算范圍float halfLamient = dot(worldNormal,worldLight)*0.5+0.5;//計算反射強(qiáng)度float3 diffuse =_LightColor0.rgb * v.color.rgb *halfLamient;//反射光加光照強(qiáng)度float3 c = anbient + diffuse;return float4(c,1) ;}ENDCG}}
}
四、下集介紹
本集講了3種計算反射光的方法。
下集講光照計算,高光反射。(最晚更新日期,1月7日)