shader光照和陰影

一.標準光照模型
OpenGL與Direct3D提供了幾乎相同的固定功能光照模型。什么是固定功能光照模型?在過去只有固定繪制流水線的時候,該流水線被限制只能使用一個光照模型,也即是固定功能光照模型。該模型基于phong光照模型。在下面的這個例子里,我們使用一個“基本”模型對固定功能光照模型提供了簡化版本。這個基本模型的數學描述為高級公式為:
   surfaceColor = emissive + ambient + diffuse + specular
從式子可以看出:物體表面的顏色是自發光(放射 emissive)、環境反射(ambient)、漫反射(diffuse)和鏡面反射(specular)等光照作用的總和。每種光照作用取決于表面材質性質(例如亮度和材質顏色)和光源的性質(例如光的位置和顏色)。
下面對這個基本模型的各個部分進行講解,最后我們使用CG語言寫出該基本模型。

圖片1.png

    
1.)自發光(emissive)
自發光光照作用獨立于所有的光源。物體的自發光并不能照亮場景中的其他物體。換句話說,物體自發光不能照亮其他物體或者投下陰影。因此,一個放射性物體本身并不是一個光源。
另一個解釋放射項的方法:它是一種在計算完其他所有光照項后添加的顏色。
自發光的數學公式:emissive = Ke
其中Ke代表材質的放射光顏色

2.)環境光(ambient)
環境光來自于四面八方,故環境放射光照項并不依賴于光源的位置。
1.環境放射項依賴:1.材質的反射能力 2.照射到材質上的環境光的顏色。
2.用于環境放射項的數學公式:
ambient = Ka * globalAmbient
其中ka是材質的環境反射系數,globalAmbient是入射環境光的顏色。
ka= tex2D(_MainTex, i.uv.xy).rgb
globalAmbient=UNITY_LIGHTMODEL_AMBIENT.xyz

環境光.png

3.)漫反射項(diffuse)

圖片2.png

蘭伯特(Lambert )光照模型是目前最簡單通用的模擬漫反射的光照模型,定義如下:模型表面的明亮度直接取決于光線向量(light vector)和表面法線(normal)兩個向量夾角的余弦值。光線向量是指這個點到光從哪個方向射入,表面法線則定義了這個表面的朝向。

diffuse = kd * lightColor * max ( NL(點積) , 0 )
max ( N
L(點積) , 0 )
規范化的向量N和L的點積是兩個向量之間夾角的一個度量,夾角越小,P點受到更多的入射光照。而背向光源的表面將產生負數點積值,因此,公式*max ( NL(點積) , 0 )使得背向光源的表面的漫反射光為0,確保這些表面不會顯示漫反射光照。

_WorldSpaceLightPos0這是一個表示世界做表中的光源的位置矢量或者方向矢量;
如果_WorldSpaceLightPos0.w為0,則表示該光源為平行光,_WorldSpaceLightPos0.xyz為此平行光的方向向量;
反之_WorldSpaceLightPos0.w不為0,則表示光源為點光源,_WorldSpaceLightPos0.xyz為此點光源.

半蘭伯特光照模型
半蘭伯特光照模型,解了決光照無法到達的區域, 背光面更亮一些
diffuse = kd * lightColor * (N * L *0.5 +0.5)
cos的值是-1到1之間,乘上0.5再加0.5后,值域是(0,1)

4.)鏡面反射項(specular)

5366d0160924ab18b03b605431fae6cd7b890ba7.jpg

Phong光照模型:

圖片3.png

Ks:材質的鏡面反射顏色
facing的取值為0或1:當N* L大于0時為1,當N *L小于0時為0
R = reflect(-worldLightDir, worldNormal) ;

BlinnPhong光照模型
BlinnPhong光照模型混合和了Lambert的漫反射和標準的高光,渲染有時比Phong高光更柔和、更平滑,此外它的處理速度相當快,因此成為許多CG軟件中默認的光照渲染方法。
specular = KslightColor pow(( dot(N,H), shininess )
其中H = (L + V) / | L+V |,實際就是normalize(L + V) , 計算H比計算反射向量R更快速。

4.)UnityCG.cginc常用內置函數
float3 WorldSpaceViewDir(float4 v) 輸入一個模型空間中的頂點位置,返回世界空間中從該點到攝像機的觀察方向。
float3 UnityWorldSpaceViewDir(float4 v) 輸入一個世界空間中的頂點位置,返回世界空間中從該點到攝像機的觀察方向。
float3 ObjSpaceViewDir(float4 v) 輸入一個模型空間中的頂點位置,返回模型空間中從該點到攝像機的觀察方向。
float3 WorldSpaceLightDir(float4 v) 僅可用于前向渲染中。輸入一個模型空間中的頂點位置,返回世界空間中從該點到光源的光照方向。
float3 UnityWorldSpaceLightDir(float4 v) 僅可用于前向渲染中。輸入一個世界空間中的頂點位置,返回世界空間中從該點到光源的光照方向。
float3 ObjSpaceLightDir(float4 v) 僅可用于前向渲染中。輸入一個模型空間中的頂點位置,返回模型空間中從該點到光源的光照方向。沒有被歸一化。
float3 UnityObjectToWorldNormal(float3 norm) 把法線方向從模型空間轉換到世界空間中。
float3 UnityObjectToWorldDir(flaot3 dir) 把方向矢量從模型空間變換到世界空間中。
float3 UnityWorldToObjectDir(float dir) 把方向矢量從世界空間變換到模型空間中。

二.法線貼圖
逐像素計算光照時,我們每一個像素都會根據該點的法向量來計算最終該點的光照結果,那么,我們如果能夠改變這個法線的方向,不是就可以改變這個點的光照結果了呢!那么,把紋理采樣的思想用在這里,我們直接用一張圖來存儲法線(或者法線偏移值,見下文),逐像素計算時,在采樣diffuse貼圖的時候,再采樣一張法線的貼圖,就可以修改法線了,進而修改最終的效果。

什么是切線空間?
切線空間就是,基于模型上的一個頂點建立的坐標空間,它的X軸是這個頂點在模型中的切線分量,Z軸是改點在模型上的法線,Y軸就是這個頂點的副切線,因為坐標空間XYZ三個面都是互相垂直的嘛,所以這個副切線我們是可以求出來的(以為同樣是與一個平面垂直的單位向量是有兩方向的,在Unity中模型會提供一個副切線的方向的數據)。
來上一個圖,讓我們更好的理解這個所謂的切線空間。

QQ截圖20170424172859.png

我們的表面法線是單位向量, 位于范圍 -1.0 到 1.0 之間. 而RGB的值域是(0,1) , 我們可以通過把法線范圍轉換為 0.0 到 1.0之間來把法線向量(x, y, z)存儲到一個 RGB 紋理貼圖中.
Color.rgb = Normal.xyz / 2.0 + 0.5;
現在我們可以分析為什么tangent space法線貼圖是偏藍色了.因為這個面渲染時計算機認為這個面的"彎曲"程度很小,即面上各個點插值得來的法線相互間偏差很小.基本跟整個面的垂直方向不會差太多.因此在tangent space里,這些法線都跟z軸偏差較小.而z軸是被保存在貼圖里的b字節處(藍色通道)里.所以貼圖顯示出來的顏色就偏藍了.

http://blog.csdn.net/candycat1992/article/details/41605257

三.(渲染路徑)Rendering Paths
1.Deferred Lighting,延遲光照路徑。3者中最高質量地還原光照陰影。光照性能只與最終像素數目有關,光源數量再多都不會影響性能。
2.Forward Rendering,前向渲染路徑。能發揮出Shader全部特性的渲染路徑,當然也就支持像素級光照。最常用、功能最自由,性能與光源數目*受光照物體數目有關,具體性能視乎其具體使用到的Shader的復雜度。
3.Vertex Lit,頂點光照路徑。頂點級光照。性能最高、兼容性最強、支持特性最少、品質最差。

1.)前向渲染
根據影響物體的光源的不同,正向渲染路徑用單個或多個通道來渲染物體。在正向渲染中,光源本身也會根據他們的設置和強度受到不同的對待。
在正向渲染中,影響物體的最亮的幾個光源使用逐像素光照模式。接下來,最多有4個點光源會以逐頂點渲染的方式被計算。其他光源將以球面調和(Spherical Harmonics)的方式進行計算,球面調和技術計算很快但只能得到近似值。根據以下的規則判斷一個光源是否為逐像素光源:

?渲染模式被設置為不重要(Not Important)的光源以逐頂點或球面調和的方式進行計算
?最亮的方向光源為像素光源
?渲染模式被設置重要(Important)的光源為像素光源
?如根據以上規則得到的像素光源數量小于質量設置中的像素光源數量(Pixel Light Count),為了減少亮度,會有更多的光源以逐像素的方式進行渲染

Base Pass 基本通道
Base pass renders object with one per-pixel directional light and all SH/vertex lights. This pass also adds any lightmaps, ambient and emissive lighting from the shader. Directional light rendered in this pass can have Shadows. Note that Lightmapped objects do not get illumination from SH lights.
Note that when “OnlyDirectional” pass flag is used in the shader, then the forward base pass only renders main directional light, ambient/lightprobe and lightmaps (SH and vertex lights are not included into pass data).
需要在設置Pass的 Tags { "LightMode"="ForwardBase" }
定義宏#pragma multi_compile_fwdbase
Additional Passes附加通道
Additional passes are rendered for each additional per-pixel light that affect this object. Lights in these passes by default do not have shadows (so in result, Forward Rendering supports one directional light with shadows), unless multi_compile_fwdadd_fullshadows variant shortcut is used.
需要在設置Pass的 Tags { "LightMode"="ForwardAdd" }
定義宏#pragma multi_compile_fwdadd

https://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html

四.投射陰影和接收陰影
1.)投射陰影
需要有平行光,且平行光開啟陰影
物體的renderer組件需要開啟Cast Shadow
物體的shader需要一個tags為”ShadowCaster”的pass來讓物體加入陰影貼圖的渲染內.可用FallBack "Specular"來讓Unity自動查詢可用的shader,注意透明物體需要特別指定.另外,如果有使用頂點動畫,則需要自己定義可用的shader

2.)接收陰影
Unity中,對于衰減,主要是通過一張光照衰減紋理(_LightTexture0)的采樣得到,其采樣操作主要是在光照空間中進行。對于陰影,一般不會采用實時陰影的方式(性能耗費太高),但是現在隨著技術的發展,越來越多的游戲采用的實時光照,當然這是對整體的光照的優化有一個極其高的情況下。一般情況下都是將場景烘培,對模型自身添加相應的光照設置。
在unity中,主要是通過一個shadowCaster的shader來實現對陰影的計算,對于物體是否投射陰影可以在其自身的組件上設置。而unity將陰影和衰減的計算合并在一起,主要通過三個基本的內部操作來實現:在a2v的結構體中設置SHADOW_COORDS(n),在vert shader中進行TRANSFER_SHADOW(o),最后在frag shader中進行 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos),此時得到的atten就是綜合了衰減和陰影的結果,可以用其來作為衰減和陰影的因子與最終的光照顏色相乘。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,034評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,337評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,883評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,114評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,625評論 1 332
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,555評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,737評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,973評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,343評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,699評論 2 370

推薦閱讀更多精彩內容

  • <轉>我也忘了轉自哪里,抱歉,感謝原作者 什么是Shader Shader(著色器)是一段能夠針對3D對象進行操作...
    星易乾川閱讀 5,614評論 1 16
  • 版本記錄 前言 OpenGL 圖形庫項目中一直也沒用過,最近也想學著使用這個圖形庫,感覺還是很有意思,也就自然想著...
    刀客傳奇閱讀 6,123評論 0 2
  • 一、Surface Output (表面著色器的標準輸出結構)Surface Shader的標準輸出結構-第一要素...
    CarlDonitz閱讀 940評論 0 1
  • 給你 ——釋白丁 時時想起的 是你那含羞時粉紅的臉頰 在微微的笑容的襯托下 如春天含苞待放的花 我小心翼翼地...
    釋白丁閱讀 227評論 0 0
  • 每個人都有自己的舞臺,都是自己生命中的主角。人有時可能會身不由己,但是我覺得堅持做真實的自己,就會成就一個...
    李嘉欣_d162閱讀 267評論 0 1