在知乎及各大論壇裡已經有許多關於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畫起來也有很多限制。那為什麼還會存在這種流程呢。
這裡祭出我們在文章的第一個部分列出的公式
入射光 = 反射光+散射光+(不見了的吸收部分)注意,這裡既沒有說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