Unity Shader自定義光照模型

2021-07-16 16:11:49 字數 2402 閱讀 4700

前幾天去一家公司面試,因為簡歷上寫著「能寫簡單的shader」,就被問了乙個問題:怎麼自定義乙個光照模型?

直接懵逼了,隱隱約約能聯想到的什麼漫反射光+鏡面反射光+環境光...難道是這個?光照模型就是#pragam su***ce surf lambert裡面的那個lambert唄?這不都是寫好的嗎?還能自定義啊?!本著「程式是嚴謹的」的心態,寧可說不知道,也不能瞎說。。。

今天有空,抓緊學習一下自定義光照模型...

首先,新建乙個su***ceshader,開啟後做如下修改

#pragma

su***ce

surf

standard

fullforwardshadows >> #pragma

su***ce

surf

mylightingmodel

之後,在subshader塊兒中實現這個光照模型:

inline float4 lightingmylightingmodel(su***ceoutput s, fixed3 lightdir, fixed atten)

這個的方法名注意,要前面多了乙個「lighting」,如果直接寫「mylightingmodel

」是會報錯滴...因為找不到,這裡具體是怎麼做的我也不知道,以後知道了再來補充。

其中lightdir是點到光源的單位向量,atten(attenuation)是衰減係數。如果要用到點到攝像機(觀察者)的單位向量,就需要另乙個引數:half3 viewdir(因為這個模型是個漫反射模型,就先不考慮觀察者角度了)。

dot方法是點乘(點積),在這裡求的是入射光線和該點法線的相似度,相似度越高,反射的光線就越多。

關於這個_lightcolor0

變數,查了一下,比較複雜,是根據當前環境中的各種光源計算出來的...我們只管用就好了。

以上就實現了乙個簡單的反射的光照模型。

最後來乙個漫反射+鏡面反射的光照模型,是不是傳說中的馮氏反射模型呢?暫且就當做是吧...

float4 lightingphongmodel(su***ceoutput s, float3 lightdir,half3 viewdir, half atten)

float3 h = normalize(lightdir+viewdir);

float specbase = max(0,dot(s.normal,h));

specf = pow(specbase,8);

這三句是用來計算鏡面反射的,鏡面反射必然與觀察者的位置有關,所以這個方法裡用到了這個viewdir引數。

最後來點理論知識,關於漫反射和鏡面反射的計算方式。

漫反射:

漫反射與鏡面反射的主要區別是法線的分布。如果物體完全光滑的話,那麼法線完全垂直於平面,例如鏡面及鋥亮的金屬表面。而很多看起來很光滑平整的物體,如紙,桌面,衣服等,實際上,

用放大鏡仔細觀察,就會看到其表面是凹凸不平的。法線並不與肉眼看見的面垂直,而是與實際的面平行。

漫反射:光射到粗糙表面時,表面會把光線向著四面八方反射,所以即使入射線平行,由於各點的法線方向不一致,造成反射光線向不同的方向無規則地反射

。這種反射光稱為漫反射光。

漫反射的計算

diffuse = kd x colorlight xmax(n*l,0)

kd漫反射係數

colorlight 光的顏色

n單位法線向量

l由點指向光源的單位向量

其中n與l點乘,如果結果小於等於0,則漫反射為0

鏡面反射:

光射到表面光滑平整,法線均勻的物體表面上,這種反射光稱為鏡面反射光。

部分內容參考和引用自風宇衝

所謂的光照模型(光照方程),就是模型對光線做出的反應。因為材質和表面光滑度的不同,在光線照射到物體表面後,因為對光線的吸收和折射反射等等,最終進入眼睛的光線。

比較經典的乙個例子,遊戲《半條命》中使用的halflambert,修改一下我們的第乙個光照模型:

float diflight = max(0, dot (s.normal, lightdir));

float hlambert = diflight * 0.5 + 0.5;

float4 col;

col.rgb = s.albedo * _lightcolor0.rgb * (hlambert * atten * 2);

col.a = s.alpha;

return col;

嗯,很簡單,想怎麼算就怎麼算。但是,要做出炫酷的效果,要學的理論知識還有很多很多...

Unity Shader 自定義Phong光照

今天我們來學習一下怎麼在unity裡實現自定義phong光照模型 什麼是phong光照?環境光和漫反射光比較容易計算,那鏡面高光要如何計算呢?鏡面高光其實可以通過利用入射光方向 即光照方向的反方向 和法線計算出反射光方向,然後再通過反射光方向和觀察視角方向計算出實際進入眼睛的光照強度,然後再做乙個光...

UnityShader自定義屬性面板

基本的屬性有,好像又是沒什麼規律,就乙個個試試吧 properties secondtex secondtex 2d white tintcolor color color 0.5,0.5,0.5,1 bright bright float 2 space 50 toggle drivesecond...

UnityShader自學日誌 建立自定義著色器

在 asset 中,建立乙個新的standard su ce shader,在mono或者vs中開啟,將原有的 段全部刪除 加入以下 每行 具體功能如下所示 shader packt moon 指定了該著色器在著色器選單中的名稱 基礎紋理貼圖,2d指定該屬性是乙個二維貼圖 子著色器 subshade...