[webGL] 小米炫彩後蓋材質分析

未標題-2.gif

紅米k40 webGL連接程序員

背景

在小米出mi 11的時候,就注意到小米商城app下有360全景體驗手機的功能,第一次打開的時候給個人感受是很震撼,震撼的不是模型,而是看到它的炫彩後蓋可以渲染的那麼真,感受和真機是如出一轍的,而後我就本身下載了手機模型,本身去作材質,發現怎麼都實現不了這種炫彩材質,興趣一下就沒了,心想,我一個程序員,關心材質幹什麼,直接讓建模師給到不就得了。。。就這樣通過了幾個月web

發現

在最近時間,我在琢磨模型軟件中的程序化着色器,在學習節點的過程當中,看到了有個屬性是菲涅爾,以前也有了解菲涅爾是水等透射物體上的物理現象,當視線和法向量的夾角越小時,越不容易造成反射,而在角度接近90°時,反射愈來愈明顯。以下圖:markdown

00e93901213fb80e7becc013e798382eb9389a503e97.jpg

原本是對菲涅爾反射有點了解的,但基本都是透射物體上才能想到的物理知識點,徹底沒有往炫彩材質上想,後來在單獨對菲涅爾屬性進行顏色輸出時,忽然發現這個感受和炫彩後蓋材質有點聯繫,效果以下:app

未標題-4.gif

可是又不太同樣,我試着調整菲涅爾的方式,改成面朝向(其實也是菲涅爾,只是實現方式略有不一樣),效果以下:oop

未標題-5.gif

在模型軟件中,材質我作到這個效果的時候,我發現這個就是我想要的,感受和炫彩效果很是吻合,剩下的就是須要根據這個灰度改變顏色便可,因而我開始個人實踐。學習

實現

下圖是我作炫彩的所有流程,圖片很大,能夠放大查看:webgl

未標題-1.jpg

  1. 得出菲涅爾值

首先是最主要的,也是前半截文章說的菲涅爾值,這裏就用到了向量的點乘概念,點乘的值簡單來講就是一個向量的長度乘以另外一個向量投影在第一個向量的長度,若是夾角爲90°是,投影的長度爲0,結果爲0,若是夾角遠離90°時,點乘的結果會愈來愈大。ui

有了上述知識,再來看下菲涅爾,菲涅爾的值就是根據視線和物體的表面向量去進行點乘計算得來的,而面向量很差求,相反,各個面的法向量咱們是知道的,因而就有了視線和法向量求點乘,獲得的值,而後被1減去獲得菲涅爾值(可是這裏不須要被1減去,在混合顏色時,傳入該值,顏色順序對調便可)。spa

因而有了上圖中左邊的三個節點:3d

未標題-2.jpg

相關glsl代碼以下(基於three):

//片元着色器
    float dot_6 = dot(normalize(vViewPosition), normalize(vNormal));
複製代碼
  1. 根據菲涅爾值進行顏色混合

我在觀察 mi11 藍色款時,發現他其實又三個色調變化,從直視後蓋到視線和後蓋相切,依次變化是:

白/淺藍交替變化 -> 深藍 -> 白

以下圖:

未標題-7.gif

其中第一個階段到第二個階段,以及第二個階段到最後一個階段很好理解,根據獲得的菲涅爾值進行混合顏色處理,在深藍到白的階段時我對菲涅爾值微調,緣由是由於我不想讓白色影響的範圍太大,後蓋和視線快相切的時候纔會起做用,並作了一次平滑處理:

未標題-8.jpg

相關glsl代碼以下(基於three):

//片元着色器
    ...
    vec4 mix_11 = mix( 
        vec4(150./256., 152./256., 161./256., 1.0), //深藍
        mix_10, //白/淺藍交替變化的混合顏色
        dot_6
    );
    vec4 mix_15 = mix(
        vec4(210./256., 214./256., 223./256., 1.0), //白
        mix_11, //前兩個階段的混合顏色
        smoothstep(0.0, 1.0, (dot_6 * 8.0))
    );
複製代碼

接下來講下第一個階段(白/淺藍交替變化),和以後的階段有所不一樣的是,這個階段交替變化,而不是出現一次,個人作法一樣是根據菲涅爾值去進行mix混合顏色的,可是會乘以一個倍數,使值大於PI,而後sin曲線和規格化(使值變爲0~1), 這樣就能夠獲得交替變化的灰度值,再根據這個值進行顏色混合,就完成全部步驟了,最後輸出這個混合顏色便可:

未標題-9.jpg

相關glsl代碼以下(基於three):

//片元着色器
    ...
    vec4 mix_10 = mix(
        vec4(194./256., 198./256., 212./256., 1.0), 
        vec4(220./256., 234./256., 243./256., 1.0), 
        ((sin((dot_6 * 20.0)) + 1.0) / 2.0)
    );
複製代碼

示例:

我嘗試吸收k40pro 白色款的三種顏色用上述着色器作demo,感受效果和預期一致。

999edc37231fdb2b55abbadd1f35608b.gif aa21e16fc5fceab595fa7fdb0b505934.gif

相關文章
相關標籤/搜索