寫一個發光材質

寫一個發光材質

來自專欄 360企業安全可視化實驗室

在繪製三維圖形的時候,不論是三維建模軟體還是Three.js都提供了很多現成的材質,可供開發者選擇,如Lambert材質、Phong材質、法向材質等。然鵝在做開發時,這些材質往往不滿足設計需求,比如發光材質就是設計常用的材質,那麼如何寫出一個透明發光材質呢?

分析透明發光材質的特點,它是在三維圖形結構的邊緣處顏色不透明度越高,向內不透明度逐漸降低,其著色跟視角方向強相關。

敲黑板~ 這是一個經典的菲涅爾反射問題。菲尼爾反射描述了一種光學現象,即當光纖照射到物體表面上時,部分光發生反射,部分光發生折射或散射,反射的光和入射的光存在一定比例關係,這個關係可用菲涅爾等式計算。常見的例子如站在湖邊,腳邊的湖面的水是透明的,可以看到水底的石頭,遠處的湖面是看不到水下物體的,只能看到水面反射的結果。

常用的菲涅爾近似等式有:

F_{schlick}(v, n) = F_{0} + (1 - F_{0})(1 - vcdot n)

其中 F_{0} 是一個反射係數,用來控制反射的強度, v 是視角方向, n 是法線方向。

我們用的是另一個廣泛應用的等式:

F_{Empricial}(v, n) = max(0, min(1, bias + scale 	imes (1 - vcdot n)^{power}))

其中 biasscalepower 是控制項。

看圖說話

令歸一化的法線方向為 n ,視角方向為 v ,那麼有表面的透明度與 ncdot v 成反比。當 | ncdot v | 接近 0 時,越不透明,| ncdot v |接近 1 時,越透明。

簡化後的代碼有:

void main() { float a = pow( bias + scale * abs(dot(vNormal, vPositionNormal)), power ); gl_FragColor = vec4( glowColor, a ); }

其中bias值決定了顏色最亮值的位置,power決定了透明度變化速度及方向。

下圖為bias取1.0,power取2.0的效果,scale取-1.0。

同理,下圖為bias取 0,power取2.0,scale取1.0。

此處注意,vNormal的normalMatrix為模型矩陣的逆矩陣的轉置。

代碼示例請戳:

codepen.io/mysisi/detai

參考:

[1] Unity Shader入門精要,馮樂樂.

[2] Everything has Fresnel

請大家持續關注我們的公眾號

我們會不斷地分享更多有趣的乾貨~

筆芯~


推薦閱讀:

QQX計劃推廣H5——這可能是地球上最美的H5,是怎麼做出來的?

TAG:shader | threejs | WebGL |