)
這個問題我在無數(shù)場合見過了技術群、面試現(xiàn)場、項目評審甚至美術朋友拿著材質參數(shù)來問我“為什么金屬度調0.6高光就臟”。對著“Unity PBR的渲染方程是啥”這個標題如果只丟出一句“Cook-Torrance BRDF”那真的不夠用。因為答案連著D項、G項、F項連著Metallic、Smoothness在Shader里到底怎么變成光的參數(shù)連著環(huán)境光怎么不靠光追也能算鏡面反射。只有把渲染方程拆到和Unity參數(shù)一一對應才算真正吃透。這篇東西我打算按六步來講先把渲染方程的框架立起來再把Cook-Torrance的D、G、F三個項逐一拆開然后到Unity源碼里找落點接著手寫一個簡化PBR Shader做驗證再列一批常見問題和排查手段最后從面試角度看看這個題目怎么答才不翻車。1. 從渲染方程到Unity先有一張全局圖1.1 渲染方程和反射率方程不是一回事渲染方程本身是一個積分方程描述某點往出射方向的總輻射亮度等于自發(fā)光加上入射半球積分Lo(p, ωo) Le(p, ωo) ∫Ω f_r(p, ωi, ωo) Li(p, ωi) (n·ωi) dωi其中Lo是出射輻射Le是自發(fā)光Li是入射輻射f_r就是BRDFn是法線ωi是入射方向積分范圍是整個法線半球Ω。這是個全局方程場景里任何光源、反射、折射到最后都會通過Li和f_r耦合在一起想完整解它只能走離線渲染或者路徑追蹤一輪一輪往里彈光線。實時渲染干不了這個事。Unity這類引擎做的事是把那個巨大的積分“砍”成兩部分一部分是對所有離散光源逐盞累加另一部分是用IBL采樣把環(huán)境光砸進來。這時真正使用的其實是反射率方程它只計算直接光照下的一次彈射不再追“光源照到A、A反射到B、B反射到眼睛”這種鏈路。很多人面試時說“Unity用的是渲染方程”嚴格講不太對Unity用的是反射率方程的實時近似只不過日常語境里大家把這兩者混著叫約定俗成也就接受了。理解了這個區(qū)別再看PBR就順了PBR的核心是選擇并實現(xiàn)一個有物理依據(jù)的BRDF讓能量守恒、讓高光形態(tài)接近真實微表面反射而不是美術自己拍腦袋去調“假高光”。1.2 Unity的PBR為什么是Cook-Torrance體系實時PBR的BRDF主流方案是微表面模型的Cook-TorranceUnity、UE、Godot大體都是這個方向。它的標準形態(tài)是把反射光分開成漫反射和鏡面反射兩部分f_r k_d * f_diffuse k_s * f_specular其中鏡面反射項長這樣f_specular D * G * F / (4 * (n·l) * (n·v))這里D是法線分布函數(shù)G是幾何遮蔽函數(shù)F是菲涅爾項。分子上三個函數(shù)負責“高光的形狀、遮擋和邊界”分母的4倍NoL乘NoV來自微表面投影面積的推導是一個幾何換算因子。Unity并不發(fā)明BRDF它只是把Cook-Torrance針對實時渲染做了一大堆性能適配再把參數(shù)改成美術熟悉的Metallic和Smoothness。因此不同引擎的PBR看起來差異不大根源就在于大家共用同一套物理模型差異只在近似程度和實現(xiàn)細節(jié)。搞清這一點后面所有代碼都容易理解得多。2. 拆開Cook-TorranceD、G、F三兄弟逐個過關2.1 D項GGX法線分布函數(shù)高光的“寬度”微表面模型假設粗糙表面是大量朝向各異的小鏡面組成的宏觀上只有一個法線n微觀上每個微表面有各自的法線m。光線從l方向進只有那些m恰好等于半角向量h的微表面才會把光按鏡面反射規(guī)則彈向v方向。D項回答的問題就是在這個粗糙度下有多少比例的微表面法線正好等于h。法線分布越集中D峰值越大高光越窄越亮分布越散高光越寬越暗淡。早期常用BlinnPhong模型做這個分布但BlinnPhong高光衰減太快形狀和真實金屬對不上。業(yè)界現(xiàn)在默認使用GGX也就是Trowbridge-Reitz分布它的公式是D_GGX(α, cosθh) α2 / (π * ((cosθh2 * (α2 ? 1) 1)2))其中α是幾何粗糙度通常由美術感知粗糙度的平方得到。這個分布最大的特點是有一條“長尾”主高光衰減之后還能保持較長的漸暈非常接近真實測量數(shù)據(jù)。在Shader里落地時大致是這個樣子half D_GGX(half NoH, half alpha) { half a2 alpha * alpha; half d (NoH * a2 - NoH) * NoH half(1.0); return a2 / (PI * d * d); }實際使用里有幾個坑。一是alpha不能為0否則分母會爆常用做法是給一個最小下限比如把粗糙度clamp到0.04以上。二是NoH必須做saturate保證角度在合理范圍。三是移動端half精度下d很小的區(qū)域非常容易出噪點遇到閃爍可以改用float算或者提高最小值。2.2 G項幾何遮蔽與可見性合并高光的“衰減”光找到了法線對路的微表面但這片微表面在入射方向和出射方向可能被旁邊的微表面擋住。入射時被擋叫Shadowing出射時被擋叫Masking合在一起就是幾何遮蔽項G。為什么必須有它因為沒有G粗糙表面的高光在掠射角會亮到失真能量明顯不守恒。真實材質在接近180度角時微表面遮擋極其嚴重高光應該快速衰減而不是越掠射越刺眼。Smith模型是業(yè)界標準做法它把G拆成兩個獨立遮擋函數(shù)的乘積G G1(n·l) * G1(n·v)G1的近似形式五花八門最常見的是Schlick-GGX或者Joint Approx。更進一步的優(yōu)化是把G和Cook-Torrance分母里的4NoLNoV合并成一個可見性項V這樣既能少算幾步除法也能避免0除風險。Unity的URP里有個Vis_SmithJointApprox就是這種合并后的形式half Vis_SmithJointApprox(half alpha, half NoV, half NoL) { half a max(alpha, half(0.05)); half a2 a * a; half lambdaV NoL * (NoV * (1.0 - a) a); half lambdaL NoV * (NoL * (1.0 - a) a); return half(0.5) / (lambdaV lambdaL half(1e-5)); }很多人把Unity里看到的代碼和書上公式對著看會發(fā)現(xiàn)“分母的4哪去了”正是因為已經(jīng)被V吞進去所以你在Unity代碼里看到的是0.5/(lambdaVlambdaL)而不是G/(4NoLNoV)。如果自己從零寫PBR這個細節(jié)很容易踩到建議直接把V和D、F一起封裝好不要在Shader里臨時拼湊。2.3 F項Schlick菲涅爾近似高光的“顏色與強度”菲涅爾說的是一個日?,F(xiàn)象視線垂直看水面時能看到水底視線貼近水面時看到的幾乎全是天空倒影。入射角越傾斜表面反射越強。BRDF里的F0是垂直入射時的反射率對非金屬大約在0.02到0.06之間業(yè)界習慣統(tǒng)一用0.04做默認值。金屬則完全不同它的F0直接由albedo顏色決定這就是金屬高光為什么帶強烈本色而非金屬高光基本是白色的根本原因。Unity里F0和Metallic之間有一條典型公式half3 F0 lerp(half3(0.04, 0.04, 0.04), albedo, metallic)Schlick近似把完整菲涅爾公式壓成一個五次冪表達F_Schlick F0 (1 ? F0) * (1 ? cosθ)^5half3 F_Schlick(half3 f0, half LoH) { half f90 half(1.0); half LoH5 pow(saturate(half(1.0) - LoH), half(5.0)); return f0 (f90 - f0) * LoH5; }Schlick不是精確的菲涅爾但誤差很小從垂直角度看已經(jīng)完全夠用實時渲染里幾乎沒有人用完整公式。對金屬來說高光顏色等于反射率顏色對非金屬來說高光接近白。下面這幾個參考值可以幫我們建立直覺材質類型線性空間F0參考值視覺效果水、玻璃、多數(shù)塑料0.02 ~ 0.04高光偏白強度不高鉆石0.15 ~ 0.18高光強且銳利鐵、鉻0.55 ~ 0.65高光帶明顯的金屬本色金約(1.0, 0.71, 0.29)金黃高光掠射角高光轉白還有一個特別重要但容易忽略的點F0必須在線性空間下計算。如果工程渲染在Gamma空間F0從sRGB色空間端進來高光顏色會偏整體對比會發(fā)灰。這也是為什么很多初次接觸PBR的人發(fā)現(xiàn)“我這F0沒問題、G沒問題為什么高光顏色就是不對”的原因之一。2.4 漫反射項Unity并不是無腦用albedo/π嚴格Lambert漫反射是albedo除以π但Unity的實際實現(xiàn)并沒有簡單到就這一步。關鍵差異在于金屬表面幾乎沒有漫反射因為光進入金屬后立刻被自由電子吸掉沒有辦法進入體內散射再出來。所以材質上“光進來后有多少能量可以變成漫反射顏色”是要按金屬度從albedo里扣出來的。對應的代碼邏輯是oneMinusReflectivity 0.96 * (1.0 - metallic) diffuseColor albedo * oneMinusReflectivity非金屬情況下反射率只有0.04所以留給漫反射的能量是96%和0.96這個系數(shù)完全對得上。金屬情況下oneMinusReflectivity接近0漫反射就被扣掉albedo直接拿去當F0了。傳統(tǒng)Blinn-Phong時代沒有這層“能量預算”概念給金屬貼一個卡通顏色當漫反射高光再單獨疊一層。PBR把albedo同時承擔了漫反射色和金屬反射色的雙重職責靠Metallic來分配預算。這就是為什么很多美術調金屬材質時總覺得“臟”如果鋁塊上albedo給了一個灰暗的深色那不僅漫反射變暗連F0這個高光基色也一起變暗高光整片死氣沉沉。3. 在實際代碼里找到這些公式的落點3.1 Standard Shader與URP/Lit的代碼入口內置渲染管線的Standard Shader底層一直維護在UnityStandardBRDF.cginc里老項目里能直接搜到DirectBRDF、SpecularTerm這類函數(shù)名。到了URP時代Cginc換成了Core RP Library的BRDF.hlsl函數(shù)入口是UniversalFragmentPBR。代碼結構變了命名換了但核心那套公式幾乎沒有動過。建議的追碼路徑是進入UniversalFragmentPBR后先找到BRDFData結構再看DirectBDRF怎么算直接光最后看GlobalIllumination怎么算間接光。在這條路徑上一定能看到D_GGX、Vis_SmithJointApprox、F_Schlick和某個漫反射函數(shù)和前面拆的公式一一對應。要注意的是不同Unity版本對roughness的命名和映射并不完全一致。有的版本BRDFData里已經(jīng)把roughness平方過D_GGX內部又做了一次平方等效alpha變成感知粗糙度的四次方看著不物理但工程上大家也都接受了。有的版本在調用前才做映射。所以別被函數(shù)名和變量名忽悠跟著數(shù)值走看它實際推進公式的是哪個量。3.2 Smoothness、roughness、alpha美術參數(shù)到底怎么進公式美術面板上那個Smoothness理解成roughness的補數(shù)就好關系是perceptualRoughness 1.0 - smoothness它叫感知粗糙度是給美術用的線性概念。進入GGX之前還要再平方一次得到幾何粗糙度alphaalpha perceptualRoughness * perceptualRoughnessalpha才是真正進D和G函數(shù)的參數(shù)。也就是說如果Smoothness是0.9perceptualRoughness0.1alpha0.01高光非常集中如果Smoothness是0.5perceptualRoughness0.5alpha0.25高光明顯散開。這個平方關系導致一個常見現(xiàn)象粗糙度從0.3調到0.4視覺變化不大從0.9調到1.0視覺變化也不大但在0.2附近微調一點點高光就會有明顯跳動。調參時心里要有這根弦。把這個關系整理成一個速查表方便日常使用SmoothnessperceptualRoughnessGGX alpha高光形態(tài)1.00.00.0理想鏡面實際需下限保護0.90.10.01小而銳利的高光0.70.30.09中等集中高光0.30.70.49明顯擴散接近亞光0.01.01.0非常發(fā)散幾乎全漫反射另外有個很典型的翻車現(xiàn)場美術在Substance Painter里導出一張Roughness貼圖回到Unity里順手接到Smoothness槽。Roughness和Smoothness本來就是反的這樣會得到完全相反的粗糙度表現(xiàn)材質像被整體調換過。正確做法是確認你的貼圖表示的是Smoothness還是Roughness再決定要不要反相或者直接用線性插值節(jié)點處理。3.3 IBL沒有光追環(huán)境光怎么也能有高光實時渲染里環(huán)境光不能逐方向積分但真實材質在環(huán)境下的高光又非常重要。于是業(yè)界普遍用Split-sum近似來拆成兩步第一步把環(huán)境貼圖按不同粗糙度預濾波存成一組miproughness越大采樣的mip越模糊第二步把BRDF對NoV和roughness的積分結果預計算成一張LUT運行時按NoV和粗糙度查表或者用解析近似模擬。最后合成時用roughness去采樣預濾波貼圖再乘LUT就得到了近似的IBL鏡面反射。Unity的Standard和URP對這個過程都有完整封裝常見的是采樣Cubemap的LOD后再乘一個EnvBRDF近似函數(shù)。因此反射探針質量對金屬物體的影響極大一個金屬壺如果周圍反射探針分辨率不夠它就像“最亮的鏡子照了一張糊掉的圖”高光糊成一片。還有一點值得特別注意IBL和直接光照是兩套獨立的近似如果他們內部對roughness的映射不一致就會出現(xiàn)“關掉環(huán)境光時很自然打開IBL后高光突然變亮或變暗”的斷層感。排查時把直接光和間接光分開驗證比在最終畫面上瞎調有效得多。4. 實戰(zhàn)手搓一個簡化PBR Shader來驗證公式4.1 初始化BRDFData金屬度如何拆出specular和diffuse與其背公式不如直接寫一段可用的HLSL骨架。下面這段代碼來自URP風格的實現(xiàn)思路但已經(jīng)簡化過特意把變量命名改得更清晰便于理解struct BRDFData { half3 albedo; half3 diffuse; half3 specular; half perceptualRoughness; half roughness; // 幾何粗糙度即GGX中的alpha half oneMinusReflectivity; }; BRDFData InitializeBRDFData(half3 albedo, half metallic, half smoothness) { half oneMinusReflectivity half(0.96) * (half(1.0) - metallic); half reflectivity half(1.0) - oneMinusReflectivity; half3 specular lerp(half3(0.04, 0.04, 0.04), albedo, metallic); BRDFData data; data.albedo albedo; data.diffuse albedo * oneMinusReflectivity; data.specular specular; data.perceptualRoughness half(1.0) - smoothness; data.roughness data.perceptualRoughness * data.perceptualRoughness; data.oneMinusReflectivity oneMinusReflectivity; return data; }注意這一步已經(jīng)把漫反射色像前面說的那樣扣掉了金屬所占的能量。如果你拿到一個metallic1的材質它的diffuseColor幾乎為0整張紋理就只剩下specular那條通道在發(fā)光。這也是為什么金屬材質在燈光暗的環(huán)境里看起來特別“吸光”。4.2 D、V、F三個函數(shù)的HLSL落地接下來是三個核心函數(shù)與前面章節(jié)的公式一一對應。這里alpha就是初始化函數(shù)里的roughness字段D_GGX內部再平方一次是為了得到alpha2half D_GGX(half NoH, half alpha) { half a2 alpha * alpha; half d (NoH * a2 - NoH) * NoH half(1.0); return a2 / (PI * d * d); } half Vis_SmithJointApprox(half alpha, half NoV, half NoL) { half a max(alpha, half(0.05)); half a2 a * a; half lambdaV NoL * (NoV * (half(1.0) - a) a); half lambdaL NoV * (NoL * (half(1.0) - a) a); return half(0.5) / (lambdaV lambdaL half(1e-5)); } half3 F_Schlick(half3 f0, half LoH) { half f90 half(1.0); half LoH5 pow(saturate(half(1.0) - LoH), half(5.0)); return f0 (f90 - f0) * LoH5; }最后在DirectBDRF里把它們組合到一起再乘光源顏色、NoL和衰減half3 DirectBDRF(BRDFData brdfData, half3 N, half3 V, half3 L, half3 lightColor, half lightAttenuation) { half3 H normalize(L V); half NoL saturate(dot(N, L)); half NoV saturate(dot(N, V)); half NoH saturate(dot(N, H)); half LoH saturate(dot(L, H)); half D D_GGX(NoH, brdfData.roughness); half Vis Vis_SmithJointApprox(brdfData.roughness, NoV, NoL); half3 F F_Schlick(brdfData.specular, LoH); half3 specular D * Vis * F; half3 diffuse brdfData.diffuse; return (specular diffuse) * lightColor * NoL * lightAttenuation; }如果你自己想驗證把specular和diffuse分別打到一個Debug顏色通道上就能很直觀地看到金屬度對兩者的影響。例如強行讓diffuse0只輸出specular金屬高光還是帶顏色反過來只輸出diffuse金屬表面會變成純黑這正好對應PBR的能量分配邏輯。4.3 用Frame Debugger和RenderDoc驗證每個中間量Shader寫完別急著看最終畫面先把中間量可視化。Unity的Frame Debugger可以在Game窗口定位到Lit PassRenderDoc更是可以直接抓取每張中間RT和數(shù)值。我的習慣是給Shader加一個Debug開關把D、Vis、F、NoL、lightAttenuation分別輸出成顏色先看單通道對不對再合成最終結果。例如把Vis輸出成灰度圖應該能看到邊緣區(qū)域比中心暗這是幾何遮蔽在起作用把F輸出成RGB圖應該能看到金屬物體在高光區(qū)域有強烈本色非金屬則接近白。如果這些中間量看起來都不對那問題一定在更上游的輸入比如法線、UV或者貼圖通道映射此時直接調最終顏色只會越調越亂。這套驗證方法比什么魔法調參都管用。大部分PBR材質“發(fā)灰”“臟”“過曝”的問題其實在中間量的灰度圖里就已經(jīng)露出馬腳了。5. 常見問題與排查實錄5.1 高光過曝或發(fā)灰高光過曝最常見的原因是G項沒用好。很多人按公式寫G/(4NoLNoV)但NoL或NoV沒有saturate負數(shù)進入分母后就會在背光面莫名其妙發(fā)亮。更隱蔽的問題是直接在Gamma空間算F結果高光色溫偏暖或偏灰。還有人在URP里把specular和diffuse簡單相加后不乘NoL導致垂直于法線的區(qū)域照樣有光照畫面一下子平了。排查時優(yōu)先把NoL單獨可視化燈從正面照NoL應當是一張平滑的明暗圖邊緣銳度取決于燈光角度而不是材質。NoL正常后再看Vis如果Vis在掠射角不衰減問題就在G項。最后看F檢查F0是否是lerp(0.04, albedo, metallic)得來的而不是拿原始albedo直接往高光里塞。下面這個速查表可以輔助定位現(xiàn)象常見原因處理方式高光整片發(fā)白過曝F項缺少能量守恒或F0計算錯誤檢查F0lerp(0.04, albedo, metallic)光照方向正常但高光平specular未乘NoL或attenuation確認最終光照乘了NoL和衰減背光面莫名高亮NoL或NoV未clamp對NoL、NoV做saturate高光顏色偏色Gamma空間計算F切換線性空間并在線性空間做F計算5.2 金屬材質怎么設置都是臟兮兮金屬材質最大的坑是把albedo當“漫反射顏色”來調。金屬沒有漫反射albedo直接成為F0基色所以想表現(xiàn)一塊干凈的鐵albedo必須給到接近鐵的反射率色值而不是一張黑灰色插畫。常見錯誤是把金屬度設為1后又把albedo調得極暗結果高光和漫反射一起消失材質看起來像一團焦炭。另一個問題是金屬度貼圖本身沒配好0和1之間根本沒有平滑過渡邊緣鋸齒感會直接把“金屬感”破壞掉。如果你想要一個相對折中的方案非金屬表面Metallic給0Smoothness給0.5~0.7金屬表面Metallic給1Smoothness按打磨程度給。不要在一張材質上到處拉0.4、0.5這種“半吊子金屬度”除非你在做介于金屬和非金屬之間的混合材質而且你清楚自己為什么這么做。5.3 粗糙度調來調去高光形態(tài)不對這種情況首先檢查Smoothness和Roughness有沒有反了。從Substance導出的Roughness貼圖如果不經(jīng)過反相就接到Unity的Smoothness槽高光形態(tài)會完全反著走。還有一種情況是貼圖導入時Unity把線性數(shù)據(jù)當sRGB解導致粗糙度數(shù)值被壓暗或提亮整個材質“軟塌塌”。另一個容易被忽略的問題是GGX的alpha映射差異。你在代碼里看到D_GGX內部又乘了一次roughness可能就是引擎在走“perceptualRoughness的平方在初始化時做一次、D_GGX內部再做一次”的雙平方路徑。如果你的工程恰好碰到這種情況視覺高光比普通PBR更“緊”調參時要參考這個歷史版本的行為而不是死磕物理公式。順手提一下Shader編譯錯誤的表現(xiàn)材質變成紫紅色或者粉色。這通常代表Shader有編譯錯誤或分支寫錯不是渲染方程本身的問題。如果看到粉紅材質先看Console里到底報了什么錯別去調參數(shù)折騰半天。5.4 直接光和間接光打架這個問題比較難排查因為在只有直接光的白色空間里測PBR渲染怎么都是對的一開環(huán)境光就出問題。常見的割裂來源有三個反射探針沒有更新導致動態(tài)物體周圍的環(huán)境信息是舊的IBL的roughness映射和直接光不一致導致同一材質在直接光高光集中、在IBL里卻像涂了層油環(huán)境貼圖不是HDR格式高光范圍被壓縮物體顯得死灰。解決思路是把“直接光”和“間接光”獨立測試。先關掉所有環(huán)境光把太陽光拉成明顯方向光確認直接光表現(xiàn)再只開反射探針關掉直接光看IBL單獨的表現(xiàn)。兩者都正常再打開一起看。如果一合起來就發(fā)灰大概率是環(huán)境光照強度或者探針分辨率與直接光不匹配而不是光照模型算錯了。6. 面試視角與延伸思考6.1 答這道題的正確順序和追問應對面試答這道題背公式是最低級的答法。一個明確的回答順序大概是先講實時渲染不能用完整渲染方程所以退化成反射率方程再說BRDF選型Unity用的是Cook-Torrance微表面模型分漫反射和鏡面反射然后拆鏡面項里的D、G、F各自說什么接著提到Unity的參數(shù)化路徑Metallic里藏著F0Smoothness先變perceptualRoughness再平方成GGX的alpha最后補一句IBL用Split-sum近似環(huán)境光和BRDF積分。面試官大概率會追三個問題。第一個是“為什么分母是4NoLNoV”。這個要答出來自微表面投影面積的幾何推導把宏表面的微表面面積投影到入射和出射兩套坐標系后產(chǎn)生的系數(shù)實時實現(xiàn)里經(jīng)常把它和G合并進可見性項。第二個是“為什么roughness要平方”。要答出美術給的perceptualRoughness是感知值跟微表面法線分布的標準差有關系幾何roughness近似等于它的平方同時GGX公式本身也需要一個二次方項來控制高光衰減形狀。第三個是“金屬度為什么能在0到1連續(xù)變化”。要答出這本質上是金屬和非金屬兩種反射模式的線性插值F0從0.04插到albedo顏色同時漫反射能量從0.96逐級扣到0并不是說0.5金屬度就是一個真實的中間態(tài)金屬而是一種材質混合控制參數(shù)。這三個追問能流利答下來基本就證明不是死記硬背了。6.2 理解渲染方程之后還能往哪兒走這套東西不光用于寫實渲染。搞明白PBR之后去看NPR卡通渲染完全就是一個“反著改”的樂趣把GGX的D項換成自定義的閃點分布把Fresnel從連續(xù)曲線換成硬閾值把漫反射從Lambert換成Ramp貼圖很多卡通效果的原理就是在打斷PBR的能量守恒強行塑造非物理的觀察信號。知道PBR每一步在做什么就能精確決定在哪里“破壞規(guī)則”這就是從“被shader推著走”變成“推著shader走”的轉折點。對性能敏感的項目PBR也不是什么洪水猛獸。核心BRDF就是D加Vis加F再乘一次NoL移動端用half精度完全跑得動真正貴的是多光源迭代和反射探針瀑布。日常優(yōu)化時優(yōu)先砍光源數(shù)量、降反射探頭更新頻率、把不參與高級光照的粒子改成Unlit比在Shader里扣float比half的細節(jié)有效得多。一點自己的實操體會做圖形渲染這些年我?guī)缀趺磕甓紩粏柕揭淮巍癠nity PBR的渲染方程是啥”問法五花八門但考察點始終穩(wěn)定你知不知道能量守恒、知不知道微表面模型、知不知道Unity每個參數(shù)最終落在公式里的哪個位置。建議想在這個方向上走遠的同學拿到任何PBR材質后都按這個順序調試先只開直接光把環(huán)境光關掉用金屬度和粗糙度把F0與alpha調對再打開IBL看整體融合。我在項目里只要嚴格按這套流程走基本沒有調不出來的材質也沒有解釋不清的高光問題。