Unity PBR Standard Shader 實現詳解(一)

2021-01-14 Unity技術美術

說在開頭

在知乎及各大論壇裡已經有許多關於PBR的實現原理,公式以及方法的討論。但是似乎沒有一個完整的逐行的代碼作用的講解。最近在學習Unity的PBR shader,有一點自己的結論,特來這裡分享一下。

我自己是一個美術工作者,不是程式設計師,所以更多的是講實現效果。以及一些必須知道的原則。站在美術的角度的一些新的思考。數學原理上只提出,但不會深入分析。

但這篇文章也不是純美術向的,我不會涉及美術的製作部分:比如高低模,烘焙,貼圖繪製這類的。著重於的是TA的應用方面:Shader。

這個系列的第一篇不會進入shader,先做一個簡單的PBR內容的普及,目標受眾是美術或者想簡單了解PBR的人。

1.0 PBR的概念

關於PBR,我之前發過一篇八猴的翻譯文章,其實已經說的比較詳盡,完全不了解的可以先看看。

那麼我再具體的總結一下:

所謂PBR,就是基於真實世界光和材質的互相作用的機制,進行渲染的方式。那麼光是如何和真實材質相互作用的呢。我粗暴的畫個圖:

如上圖,一束光照射在材質表面後,會變成三個分身:反射光(specular),散射光(diffuse),和一部分被吸收的光線。
由於宇宙的能量守恆,所以:


入射光 = 反射光+散射光+(吸收部分)
incident = specular + diffuse + (absorption)


這裡有幾個值得注意的點:

我們能看到的只有反射光和散射光。吸收光被材質「吃掉」了,看不見的。

反射光視覺上就是高光的部分和鏡子一樣反射(鏡面反射)的部分。

散射光就是物體本身的顏色部分,紅蘋果啊綠帽子啊這類的。

(重要)金屬是沒有散射的部分的!金屬直接只有反射和吸收兩個部分。那麼金屬的顏色,其實是反射顏色。金屬的反射是有顏色傾向的,這也是金屬的特點。

有些金屬其實不是金屬,比如鏽跡是氧化物,其實不是金屬。金屬上的灰塵也不是金屬。

記住這些觀點後,接下來我講一下怎麼用美術的眼光看PBR。

2.1 PBR之前的次世代

首先,一開始有次世代這回事時,我們的次世代貼圖長這樣

這裡一般有三張貼圖:顏色貼圖,反射貼圖,法線貼圖。 

對於一個美術來說三張很容易理解:

diffuse map: 顏色

specular map: 哪兒反光哪兒不反光

normal map: 表面凹凸信息。

我認為這種類型的次時代有幾個特點:

引入高模製作流程 ,需要烘焙法線。然後在引擎裡利用法線實現高模的視覺效果。

顏色貼圖中需要繪製適當的光影及AO效果。製作流程是使用PS,先製作顏色貼圖,再由顏色貼圖逐圖層轉高光貼圖。

相比於之後的PBR次時代。不能很好的體現金屬的質感。金屬將有強烈的塑料感。

以上的總結不一定會十分完整。但總之這個階段的次世代和PBR次世代的差異是巨大的。

後文我們稱這種製作方式為傳統次時代。

2.2 PBR次世代製作,金屬度粗糙度流程和高光度光滑度流程(metalness-roughness workflow和specular-smoothness workflow)


約麼2014-15年的時候,國內開始慢慢有公司開始做PBR次世代,這個時候我們的貼圖變成了4張:

四張圖是:

顏色貼圖(Albedo)

金屬度(Metallic||Metalness)

粗糙度 (Roughness)

法線貼圖

在有的引擎裡,粗糙度會被光滑度(smoothness)代替,其實兩者意義是類似的,數學上是相反的(1-x)關係。
一開始有人會覺得:那相比於傳統次世代,不就等同於多了一張金屬度貼圖而已唄。。且慢,差別大了:

傳統貼圖的顏色貼圖會繪製光線,而Albedo貼圖幾乎不繪製光線。

傳統貼圖中,沒有粗糙/光滑的細節控制,而在PBR裡粗糙/光滑度是一個十分影響效果的通道。

傳統次世代可以在DCC軟體中直接查看效果。而PBR時代十分依賴引擎查看器的效果。

傳統次世代的主要繪製工具是PS,概念是顏色貼圖-->高光貼圖-->效果。

PBR貼圖的主要繪製工具是SubstancePainter,概念是材質的疊加。

部分遊戲從業者,尤其是程式設計師同學,會不清楚除了metallic-roughness(smoothness)流程之外,還有一個specular-glossiness(smoothness)流程,也就是反射度-光澤度。如下圖。

反射度-光澤度流程也包含了四張貼圖:

反射度光澤度流程需要注意以下幾個點:

有心的同學會發現,上面兩者好像和美術沒什麼關係呀。。。而且看貼圖,Diffuse黑咕隆咚的,然後specular畫起來也有很多限制。那為什麼還會存在這種流程呢。

這裡祭出我們在文章的第一個部分列出的公式

入射光 = 反射光+散射光+(不見了的吸收部分)
incident = specular + diffuse + (absorption)

注意,這裡既沒有說Albedo,也沒有說metallic。它說的是specular和diffuse呀!所以其實反射度-光澤度流程是對於光照公式的更加直接的描繪。

其實在shader的內部實現中,首先會對albedo和metallic進行轉換,轉換成diffuse和specColor(有的時候寫作F0)。其實就是這個原因。在有些論壇的討論文章中,會對這幾個參數的轉換講的比較含糊,那麼有貼圖的概念就比較容易理解了。

關於兩種流程的貼圖形式對比,我拼在一起放出來,可以看到最後的渲染結果是一致的。

那麼為什麼現在主流的引擎,像Unity和Unreal會同一的採用金屬度流程呢,這裡我覺得有幾個原因:

那麼反射度流程的存在還有什麼意義呢?其實金屬度流程固然好,但是以犧牲畫面效果為代價的:整個非金屬的specular變化全部用固定值衡量,從metallic+albedo轉換到specular+diffuse的過程中,也不可避免的會產生損耗,所以在高質量的渲染中。比如八猴渲染器和離線渲染中,默認會採用反射度流程。

關於流程的問題,其實八猴也做過一個文章,關於幾個流程的轉換,可以一看

再貼兩張Unity官方的不同流程的色度效果,可以有一個直觀的感受:

這次系列文章的目的是為了講解Unity StandardShader的應用。為什麼一開始會花一段篇幅講流程問題。主要是因為網上關於美術類的PBR實在是太少,那麼當美術的同學看到此篇文章時,可以有一些收穫。而程式設計師的同學們看了,也會有一些新的認知。

在寫作這篇文章時,我只是一個剛接觸shader內容的模型師,文內可能有所疏漏,希望能有大佬斧正。

我參考了如下資料,獻出我的膝蓋以示感謝:

peace:)


最後


如果想觀看更多關於雨軒的分享,可以看看他的專欄:

https://zhuanlan.zhihu.com/c_1237815823202291712




相關焦點

  • Unity3d-UI-Shader-太極圖案
    準備階段基於ui的shader,先找到對應unity3d版本的內置shader包,下載下來之後找到UI-Default.shader,拷貝該文件修改名字為要編輯效果的名字。調整shader 名稱為 OEngine/UI/TaiChi,創建材質球TaiChi.mat,設置shader為OEngine/UI/TaiChi。
  • 使用Unity 粒子系統實現 2D 人物足跡效果
    其基本思路是根據輸入計算一個 2 維向量lookDirection作為角色的「面向」,並根據這一向量移動剛體以及播放動畫。 它能夠保證對於任意角度,角色的移動速度都保持一致,並且這一向量對於腳印效果的實現很重要。 如有疑問可以查閱底部的教程連結或直接下載腳本。
  • unity 半透明渲染技巧(3則)
    理解這個基礎原因很有好處,否則一堆美術問你為什麼max maya 沒問題 unity ue有問題的時候 你不知道怎麼回答。所以 實現了這版 除了消耗點性能 通用性和精確度都很高原理引擎默認是之渲染離相機最近的一層depth,和color。這種始終對無序半透明渲染是信息不足的,我們想 如果 每一處遮擋 都可以保留遮擋後面的最近的顏色 那麼我們自然就能 對這些顏色 一起混合。就像做ui 拿到5張從前到後的圖片 計算他們透明疊加就很簡單了。那麼怎麼獲得這些顏色呢?
  • Unity高級知識點總結:性能優化與圖形渲染進階
    二、優化的經驗(一) UI的性能優化1、寫一個UICollider而不是透明的Image,可以減少overdraw2、小地圖用shader實現指定位置的圖片渲染,而不是RectMask2D,可以減少overdraw。因為RectMask2D是使用alpha=0來實現裁剪的。
  • PBR基本原理解析
    散射出來的一部分可能又照射到眼睛裡或者攝像機上,這一部分有很多名字比如:Diffuse light,Diffusion,「Subsurface Scattering」等。所有都描述的這一效果。這也是shader中執行的能量守恆。也就是說散射後離開物體的光線,不可能比它落在物體上的光線更亮。著在shader中很容易實現,一個簡單的減法就可以,減去反射的光,就是要發生散射的光,也就是說越高的反射,呈現的散射就越弱。
  • 【遊戲流體力學基礎及Unity代碼(二)】用平流方程模擬染料流動
    我們現在假設這個染料粒子只能平流,速度向右,也就是某個網格下一時刻的染料粒子密度,只能由這一時刻此網格左側網格決定,並且速度是每秒一網格,那麼所有網格的水染料粒子密度將如何變化? 等式左邊就是此網格下一時刻染料粒子密度相較於這一時刻的增長,而右邊a就是速度,偏微分代表此時刻此網格與前一個網格的密度差。真實世界中,dt和dx都是無窮小的,所以上面這個公式是絕對精確的。
  • 2021新年匯總:Unity項目原型快速開發資源,看這一篇就夠
    Example Game : https://assetstore.unity.com/packages/templates/flappy-bird-style-example-game-80330 Tower Defense Template : https://assetstore.unity.com/packages/essentials
  • Unity基礎之物理引擎
    我們在unity裡面建了一個正方體cube , 要如何使這個cube可以跟現實中的物體一樣受重力呢 ? 這就需要用到Rigidbody(剛體)組件了 .單擊cube , 在右邊的Inspector面板添加Rigidbody組件添加完Rigidbody組件後,cube1就可以受重力影響了,運行unity時,cube1會因為受到重力往下落.下面為大家介紹 Rigidbody 組件常用參數 : 1. Mass : 物體的質量 .
  • Unreal|PBR檢測工具
    我們在使用pbr流程的時候都根據項目要求有一些顏色值範圍,比如說substance的30/50-240。我們在painter或者designer裡面畫貼圖的時候如果顏色值不在正確的範圍內,導入到引擎裡面效果就會有問題,所以就需要一些在引擎裡面檢查顏色值或者粗糙度值是否規範的工具。下面就介紹一些這款朋友提供的檢查basecolor的工具。
  • unity|specular年終結
    打開上次diffuse的那個shader,我們直接在這個shader的基礎上疊加specular效果,就可以最終得到phong shader的效果。人觀察的方向可以直接用shader graph自帶的view direction來獲取,所以結果如下;因為黑色顏色值為0,但是如果是負數的話,得到的顏色也是0,所以為保證顏色值在0-1之間,我們給結果加上一個Maximum節點,去除掉小於0的值。如此便得到specular的效果,最後將其與之前做的diffuse相加,輸入到最後的輸出節點中。
  • Shadertoy | 水母生物的創作小記
    sdSphere( vec3 p, float r ) { return length(p) - r;}float map( vec3 p ) { float radius = 0.5; return sdSphere( p, radius );}如果我們想對這個球體進行克隆,只需要在 map() 函數的一開始加入一行代碼
  • unity遊戲製作初始人物控制代碼
    大家好,今天小編帶大家學習一哈unity遊戲製作中初始人物控制代碼。1.我們知道遊戲中,選中人物,在人物未開始運動前,往往會有一個初始的動作,好的,我們這節課通過unity中相關代碼和基礎設置來實現這一效果。
  • Unity漸進式光照貼圖烘焙詳解|unity
    不過目前的實時光追技術還只能在配備了最新Nvidia RTX 20系列顯卡的PC機上才能實現(前一代Nvidia 10系列顯卡,比如GeForce 1080,1070,甚至1060也可以用軟體實現實時光追,但是總體效果不佳)。大多數玩家所在的移動平臺上,目前並沒有實時光追技術被正式推出。
  • Unity3D 尋路系統
    一、尋路方式二、實現尋路方法確定尋路者烘培尋路路面程序實現尋路算法1、實現尋路步驟將場景中不動的物體勾選
  • 那個容易被遺忘的統計學名詞——standard deviation
    無論是AP,IB還是A-level體系,同學們在學習數學的過程中,往往多少都會學習一部分統計學中的知識點,而這裡面有一個讓大家容易遺忘且理解不夠透徹的名詞 standard derivation。比較兩組數據standard derivation的大小是SAT數學常出的題型,解決這樣的問題主要是理解和明白standard derivation的數學含義:展示一組數據的離散程度或者波動程度,越是離散或者波動,standard
  • 博主營地 | Unity3D 實用技巧 - 理論知識庫(一)
    抽象類表示該類中可能已經有一些方法的具體定義,但接口就是只能定義各個方法的界面 ,不能具體的實現代碼在成員方法中。類是子類用來繼承的,當父類已經有實際功能的方法時該方法在子類中可以不必實現,直接引用父類的方法,子類也可以重寫該父類的方法。實現接口的時候必須要實現接口中所有的方法,不能遺漏任何一個。
  • SOLIDWORKS 2019新功能——業界最新技術PBR材質
    這是一種將材質表現拆分成多種貼圖的疊加,再結合當今優秀的顯卡性能,從而實現運算速度更快,視覺表現更精準的渲染技術。下圖是材質拆分的示例,可以看到鋼鐵俠材質拆分成了「基色貼圖(base color)」 +「粗糙度貼圖(roughness)」 +「金屬反光強度貼圖metallic)」 +「法線貼圖(normal)」 +「高度貼圖(height)」,所有貼圖疊加後,形成我們看到的材質效果。
  • Unity編碼篇 Rigidbody類
    Rigidbogy組件可以使遊戲對象在物理系統的控制下運動 , 發射一顆子彈 ,如果子彈沒有命中任何物體 ,最後 子彈會因為重力落下 , 此時就可以利用 Rigidbody 組件實現 , 但是使用該組件一般在 FixedUpdate 函數中執行 , 因為物理仿真一般都在固定頻率下進行計算的 .
  • Unity 2018.3 Beta版發布
    直播課程:Facial AR Remote面部捕捉解決方案課程(第一期)直播地址:https://connect.unity.com/events/unitychina-facialarUnity官方教師培訓報名火熱進行中Unity將在10月22-26日,舉辦為期5天的專業的Unity官方教師培訓課程,誠邀廣大教師與
  • unity什麼意思
    unity什麼意思uni前綴,只包含一個的,更多例子還有:uniform, unique, unilateral, etc. 發音類似於有你,整個世界中有你就夠了,不需要別人,也就是只包含一個的。unity,聯合、統一、團結、和睦。學單詞,只記住意思可不行,會用才行,小夥伴們可以在評論區造句,我們一起學習哦!我先來:造句:Unity is strength. (團結就是力量)