您當前的位置:首頁 > 攝影

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

作者:由 凌霄 發表于 攝影時間:2020-04-01

最近按照學習小組內的分工,我一直在研究Unreal,被搞得有點痛苦。unreal由於開發時間太長,原始碼過於龐大,而且,體系化的中文文件也比較少,所以,就決定花一些時間來做英文資料的搬運工。

這次來翻譯一下2013年Epics Games工程師做的分享《Real Shading in Unreal Engine 4》這篇文章,這個作為Unreal Engine向真實渲染轉變的重要分析文件,對現在而言,還是有一些借鑑意義的。

Real Shading in Unreal Engine 4

by Brian Karis, Epic Games

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

圖1:UE4的滲透者Demo

一、介紹-Introduction

大約在一年前(2012年),我們決定投入一些時間去提升我們的著色模型並且包含一個更加基於物理的材質工作流。它部分驅動自渲染更真實的影象的需求,但是我們也對我們透過更基於物理的方法進行材質建立、使用分層材質可能達到的目標感興趣。藝術家感覺這可能是對工作流和質量的一個巨大的提升,並且我已經在另一個工作室第一時間看到了這些成效,在那裡我們已經過渡到離線混合的材質層。我們的其中一位技術美術在Epic在著色器中做分層的實驗,實現了結果很有希望,這成為了一個額外的需求。

為了支援這個方向,我們知道材質的分層需要簡單,並且高效。迪士尼的演講來的時間十分完美[2],涉及到了他們的基於物理的著色和使用Wreck-It Ralph的材質模型。Brent Burley 展示了一個非常小的材質引數集合可以足夠精緻的表現離線特性的電影渲染。他童謠展示了一個相當實用的著色模型可以緊密的適用於大多數取樣的材質。他們的工作成為了我們的一個靈感和基礎,並且像他們的“規則”相似,我們也決定去定義一個我們自己的系統的目標。

實時效能-Real-Time Performance

首要的是,它需要在每次許多可見燈光的條件下高效地使用。

簡化複雜度-Reduced Complexity

引數儘可能的少。大批的引數不僅會導致很難來做一個決定,需要反覆試驗和試錯,或者相互關聯的屬性對於一個預期效果需要許多的值來改變。

我們需要能夠使用基於影象的光照(IBL)和互動式地可分析光源,所以引數必須在多有的光照型別中表現一致。

直觀的介面-Intuitive Interface

我們更傾向易於理解的值,而不是像折射率(index of refraction)這樣的物理引數。

感知線性-Perceptually Linear

我們希望通過蒙版支援分層,但是我們只能承受逐畫素一次著色的負擔。這意味著混合引數著色必須儘可能的匹配著色結果的混合。

簡單掌握-Easy to Master

我們想要避免需要電介質和導體的技術理解,同時最小化建立基本的貌似物理的材質所需要的努力。

健壯-Robust

錯誤的建立物理上不可信的材質很困難。

所有引數的結合的應該儘可能的健壯和可信。

具有表現力-Expressive

延遲渲染限制了我們可以使用的著色模型的數量,所以我們的基本著色模型需要足夠描述覆蓋現實世界中99%的材質。

為了能夠混合所有可分層的材質,所以,他們之間需要共享相同的引數集。

靈活-Flexible

其他的專案或者被授權開發的專案,可能不是以照片級真實渲染為目標,所以也需要足夠靈活來允許非真實感渲染。

二、

著色模型-

Shading Model

2.1、漫反射雙向反射分佈函式-Diffuse BRDF

我們評估了Burley的漫反射模型,但是隻觀察到與Lambertain模型相比輕微的差別(等式1),所以我們不能判斷額外的開銷的合理性和必要性。除此之外,任何更復雜的漫反射模型很難高效的使用基於影象或球面諧調的光照。因此,我們不在評估其他選擇上投入精力。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

這裡Cdiff是材質的漫反射率(diffuse albedo)。

UE4。21的當前實現,請參考BRFD。usf檔案。

float3

Diffuse_Lambert

float3

DiffuseColor

{

return

DiffuseColor

*

1

/

PI

);

}

2.2、微表面鏡面反射雙向反射分佈函式-Microfacet Specular BRDF

常規的Cook-Torrance[5,6]微表面鏡面反射著色模型是:

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

請查閱[9]來獲取更多擴充套件資訊。

我們從迪士尼使用的模型開始,在與其他更高效的實現方式對比的情況下,評估了公式中每一項的重要性。這個工作遠比聽起來要困難的多;已經公佈的公式中的每項輸入不一定使用了相同的引數,但這對於正確的比較是至關重要的。

2.2.1、鏡面反射D-Specular D

對於法線分佈函式(NDF),我們發現迪士尼選擇的GGX/Trowbridge-Reitz的成本是值得的。相比於Blinn-Phong的公式,額外的消耗相當的小,並且提供了更好的“長尾效果”,這個長尾效果的表現吸引了我們的藝術家。我們也採用了迪士尼重新定義的引數α=Roughness^2。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

譯者注:

法線分佈函式D(Normal Distribution Function)

:或者說鏡面分佈,從統計學上近似的表示了與向量h取向一致的微平面的比率。

舉例來說,假設給定一個向量v,如果我們的微平面中有35%與向量v取向一致,則正態分佈函式或者說NDF將會返回0。35。

我們來增加一個針對NDF在長尾效果方面的展示和對比,如下圖所示。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

注:主流NDF函式高光長尾效果的對比,GGX擁有最好的長尾表現。

UE4。21中的程式碼實現:

從程式碼中看,跟D(h)的實現是完全一致的。

float

D_GGX

float

Roughness

float

NoH

{

float

a

=

Roughness

*

Roughness

float

a2

=

a

*

a

float

d

=

NoH

*

a2

-

NoH

*

NoH

+

1

// 2 mad

return

a2

/

PI

*

d

*

d

);

// 4 mul, 1 rcp

}

在UE4中,有另外一個關於各項異性的GGX實現,主要的實現思路是在X軸、Y軸兩個方向上分別進行計算roughness。

Anisotropic GGX, Burley 2012, "Physically-Based Shading at Disney"

float

D_GGXaniso

float

RoughnessX

float

RoughnessY

float

NoH

float3

H

float3

X

float3

Y

{

float

ax

=

RoughnessX

*

RoughnessX

float

ay

=

RoughnessY

*

RoughnessY

float

XoH

=

dot

X

H

);

float

YoH

=

dot

Y

H

);

float

d

=

XoH

*

XoH

/

ax

*

ax

+

YoH

*

YoH

/

ay

*

ay

+

NoH

*

NoH

return

1

/

PI

*

ax

*

ay

*

d

*

d

);

}

2。2。2、鏡面反射G-Specular G

我們評估了鏡面幾何衰減項的多種選擇。 到最後,我們選擇使用Schlick模型[19],但k =α/ 2,以便更好地擬合Smith模型GGX [21]。 透過這種修改,Schlick模型與α= 1的Smith完全匹配,並且相當[0,1]範圍內的近似逼近(如圖2所示)。 我們還選擇使用迪士尼的修改透過在平方之前使用

\frac{Roughness+1}{2}

重新對映粗糙度以減少“熱度hotness”。 請務必注意該調整僅用於光源計算;如果應用於基於影象的照明(IBL),則在掠射角度部分的顏色太暗。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

圖2:使用k=α/2的Schlick非常接近Smith匹配

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

注:

在基於物理的渲染中,幾何函式(Geometry Function)是一個0到1之間的標量,描述了微平面自陰影的屬性,表示了具有半向量法線的微平面(microfacet)中,同時被入射方向和反射方向可見(沒有被遮擋的)的比例,即未被遮擋的m= h微表面的百分比。幾何函式(Geometry Function)即是對能順利完成對光線的入射和出射互動的微平面機率進行建模的函式。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

注:幾何函式G(x)的光學涵義

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

注:白色表示沒有微平面的陰影,黑色表示微平面徹底被遮蔽

在UE4老的實現程式碼中,UE4將G(l,v)項和

4(n\circ l)(n\circ v)

合併為Vis(l, v),Schlick模型的實現程式碼如下:

float

Vis_Schlick

float

Roughness

float

NoV

float

NoL

{

float

k

=

Square

Roughness

*

0。5

float

Vis_SchlickV

=

NoV

*

1

-

k

+

k

float

Vis_SchlickL

=

NoL

*

1

-

k

+

k

return

0。25

/

Vis_SchlickV

*

Vis_SchlickL

);

}

但是,在UE4。21的程式碼中,實際的實現程式碼又發生了改變。如下所示。似乎是又朝著Smith的實現去進行了調整。

// Tuned to match behavior of Vis_Smith

float

Vis_Schlick

float

a2

float

NoV

float

NoL

{

float

k

=

sqrt

a2

*

0。5

float

Vis_SchlickV

=

NoV

*

1

-

k

+

k

float

Vis_SchlickL

=

NoL

*

1

-

k

+

k

return

0。25

/

Vis_SchlickV

*

Vis_SchlickL

);

}

2.2.3、鏡面反射F-Specular F

對於菲涅爾,我們做出使用Schlick近似的經典選擇 [19],但是有一點修改,我們使用了球面高斯Spherical Gaussian近似[10]來代替power計算。這稍微提高了計算效率,並且差異微不可察,公式為:

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

Schlick近似的經典公式

採用球面高斯的近似來代替Power的選擇,主要是考慮在GPU上運算的效率來考慮。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

注:GPU指令減少了50%

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

注:可以看到,這個擬合幾乎是完美的。

但是,從UE4。21的程式碼來看,似乎並沒有採用這個球面高斯趨近,而是採用了一種更高效的方式。按照實現應該是Fc + (1-Fc) * SpecularColor,但是,在第一個Fc前面增加了一個 50 * SpecularColor。g,但是,Fc還是採用了Pow5的處理。(哪位朋友瞭解原因,可以下面評論中幫忙解釋一下。)

float3

F_Schlick

float3

SpecularColor

float

VoH

{

float

Fc

=

Pow5

1

-

VoH

);

// 1 sub, 3 mul

// Anything less than 2% is physically impossible and is instead considered to be shadowing

return

saturate

50。0

*

SpecularColor

g

*

Fc

+

1

-

Fc

*

SpecularColor

}

譯者注:下面的部分介紹的就是IBL了,但是,從BRDF的整體性角度來說,還缺失了一個環境光的漫反射部分,為了讓讀者有一個更完整的理解,我這裡非常簡單地來介紹一下這部分。

漫反射環境光照部分一般採用傳統IBL中輝度環境對映(Irradiance Environment Mapping)技術,並不是基於物理的特有方案。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

環境光漫反射部分的計算公式

這個東西是沒辦法直接使用的,所以我們使用蒙特卡洛積分的期望法來進行積分。具體推導過程如下所示:

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

在寫程式碼實現的時候,用蒙特卡洛積分求係數的過程大概就是一系列的相乘與求和,虛擬碼:

void

SH_Coefficients

()

{

double

weight

=

4。0

*

PI

//生成n條光線進行取樣

for

int

i

=

0

i

<

n_samples

++

i

{

//生成帶抖動的無偏取樣方向(θ,ϕ)

for

int

n

=

0

n

<

n_coeff

++

n

{

//對於某一個light probe,它的每個球諧展開係數c_i就要累加起所有的【某方向上的irradiance * 這個方向上SH函式值】

result

n

+=

light

θ

ϕ

*

samples

i

]。

SH_basis_coeff

n

];

}

}

// 把蒙特卡洛積分的常數項乘上去(恆定的取樣權重,總取樣數)

double

factor

=

weight

/

n_samples

for

i

=

0

i

<

n_coeff

++

i

{

result

i

=

result

i

*

factor

}

}

上面的result[i]就是某個點上光照分佈的球面函式經過”編碼”之後得到的球諧係數。我們可以用離線預計算的係數,在runtime透過效率比較高的方式近似重構出原來的光照。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

透過上面的虛擬碼,將左邊的環境貼圖,計算成輝度環境對映,從而用於執行時刻的運算

2.2.4、基於影象的光照-Image-Based Lighting

為了在基於影象的光照使用這個著色模型,需要解決輻射率積分,這通常使用重要性取樣來完成。(注:關於輻射度這部分內容相當豐富和複雜,這裡就不解釋了。讀者可以去查詢輻射度的相關文章。)下面的等式描述了這個數值積分:

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

重要性取樣

(Importance Sample)即透過現有的一些已知條件(分佈函式),想辦法集中於被積函式分佈可能性較高的區域(重要的區域)進行取樣,進而可高效地計算準確的估算結果的的一種策略。

下面的HLSL程式碼展示瞭如何在我們的著色模型中實現:

(以下與原文略不一致,使用了4。21的程式碼替換)

float4

ImportanceSampleGGX

float2

E

float

Roughness

{

float

m

=

Roughness

*

Roughness

float

m2

=

m

*

m

float

Phi

=

2

*

PI

*

E

x

float

CosTheta

=

sqrt

1

-

E

y

/

1

+

m2

-

1

*

E

y

);

float

SinTheta

=

sqrt

1

-

CosTheta

*

CosTheta

);

float3

H

H

x

=

SinTheta

*

cos

Phi

);

H

y

=

SinTheta

*

sin

Phi

);

H

z

=

CosTheta

float

d

=

CosTheta

*

m2

-

CosTheta

*

CosTheta

+

1

float

D

=

m2

/

PI

*

d

*

d

);

float

PDF

=

D

*

CosTheta

return

float4

H

PDF

);

}

float4

ImportanceSampleGGX

float2

E

float

Roughness

{

float

m

=

Roughness

*

Roughness

float

m2

=

m

*

m

float

Phi

=

2

*

PI

*

E

x

float

CosTheta

=

sqrt

1

-

E

y

/

1

+

m2

-

1

*

E

y

);

float

SinTheta

=

sqrt

1

-

CosTheta

*

CosTheta

);

float3

H

H

x

=

SinTheta

*

cos

Phi

);

H

y

=

SinTheta

*

sin

Phi

);

H

z

=

CosTheta

float

d

=

CosTheta

*

m2

-

CosTheta

*

CosTheta

+

1

float

D

=

m2

/

PI

*

d

*

d

);

float

PDF

=

D

*

CosTheta

return

float4

H

PDF

);

}

即使有重要性取樣,許多的樣本仍然需要被採集。樣本數量可以透過mip maps顯著的減少,但是數量仍然需要大於16以滿足足夠的數量(注:原文1024次取樣,4。20為32次取樣)。因為我們為了獲得區域性的反射資訊,需要在許多張環境貼圖中進行逐畫素的混合,我們實踐中只能支援針對每張貼圖進行一次樣本取樣。(注:原文在這裡寫得並不清楚,其實,想表達的意思是說:所以呢,咱們還得想其他辦法。)

2.2.4.1、分解求和近似-Split Sum Approximation

為了實現這個,我們透過將上面的公式6分解成為兩個求和部分來近似求解。每一個分離出來的求和公式可以被進行提前的預計算。對於一個常數

L_{i}(l)

這個近似是準確的,並且對於常規的環境來說,此公式也相當的精確。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

2.2.4.2、預積分環境貼圖-Pre-Filtered Environment Map

我們對於不同的粗糙度值,預計算第一個求和項並且將結果儲存在CubeMap的mip-map層級中。這是在遊戲工業使用的典型方式[1,9]。一個較小的區別是,我們使用了重要性取樣和我們的著色模型中的GGX分佈對環境貼圖做了卷積計算。

因為這是微表面模型,分佈的形狀改變依賴於到表面上的觀察角度,所以

我們假設這個角度是0

,例如,n=v=r。

各向同性的假設

是近似的第二個來源,並且它不幸地意味著我們不會在掠射角獲得漫長的反射。

比起分離的和近似,實際上這是我們IBL解決方案中更大的錯誤來源。正如下面程式碼展示的,我們已經發現使用

cosθ_{lk}

可以實現更佳的結果。

下面的程式碼,選自UE4。21版本。

float3

PrefilterEnvMap

uint2

Random

float

Roughness

float3

R

{

float3

FilteredColor

=

0

float

Weight

=

0

const

uint

NumSamples

=

64

for

uint

i

=

0

i

<

NumSamples

i

++

{

float2

E

=

Hammersley

i

NumSamples

Random

);

float3

H

=

TangentToWorld

ImportanceSampleGGX

E

Pow4

Roughness

)。

xyz

R

);

float3

L

=

2

*

dot

R

H

*

H

-

R

float

NoL

=

saturate

dot

R

L

);

if

NoL

>

0

{

FilteredColor

+=

AmbientCubemap

SampleLevel

AmbientCubemapSampler

L

0

)。

rgb

*

NoL

Weight

+=

NoL

}

}

return

FilteredColor

/

max

Weight

0。001

);

}

譯者注:從程式碼上看,兩個程式碼主要有兩個變化,一個是在原來的程式碼中進行了1024次取樣,而最新的程式碼中,只進行了64次取樣;第二個變化,針對最後進行的除法進行了一個保護,使用max( Weight, 0。001 )替代了原來的Weight。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

預積分環境貼圖

上圖中的預積分環境貼圖,是透過PrefilterEvnMap來進行離線計算並生成的。因為它是離線渲染的,所以,使用1024次取樣,還是64次取樣,基本上沒什麼太大的差距。至於為什麼UE的最新程式碼,降低了大量的取樣,我就不得而知了。

在這個輸入的引數中,有一個Roughness的引數,這個就是為什麼會使用5級的mipmap的原因。畢竟針對不同的roughness,會從不同的mipmap來進行取樣,這樣也就獲得了不同的輻照度資訊。

說白了,這還是一種在不能進行光線追蹤情況下進行的一個模擬實現。將生成的Cubemap視為輻照度資訊,將不同等級的MipMap作為不同Roughness的輻照貼圖。這種方案既考慮到了實時渲染的效率問題,也在一定程度上保證了這個渲染的真實性。

2.2.4.3、環境雙向反射分佈函式-Environment BRDF

第二個求和項包含了其他所有的部分。這與用一個純白色的環境對鏡面反射雙向反射分佈函式進行積分操作是一樣的,例如,

L_{i}(I_{k}) = 1

。透過Schlick的菲涅爾代替:F(v,h)=F0+(1-F0)(1-v·h)^5,我們發現F0可以因式分解到積分外。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

這餘下了兩個輸入(粗糙度Roughness和cosθv),和兩個輸出(F0的縮放和偏移),所有的值都在[0,1]的範圍內。我們預計算這個函式的結果,並且儲存到一個2D的查詢表中(因為精確度是非常重要的,所以,在這裡使用R16G16的格式)。

上式留下了兩個輸入(Roughness 和 cos θv)和兩個輸出(縮放和向F0的偏差(a scale and bias to F0)),即把上述方程看成是F0 * Scale + Offset的形式。 我們預先計算此函式的結果並將其儲存在2D查詢紋理(LUT,look-up texture)中。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

圖3:2D紋理查詢表

這張紅綠色的貼圖,輸入roughness、cosθ,輸出環境BRDF鏡面反射的強度。這個是關於roughness、cosθ與環境BRDF鏡面反射強度的固有對映關係。這個事可以進行離線預計算。

具體的取出方式為:

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

即UE4是透過把Fresnel公式的F0提出來,組成F0 * Scale +Offset的方式,再將Scale和Offset的索引存到一張2D LUT上。靠roughness和 NdotV進行查詢。下面是從UE4。21程式碼中找到的製作這張LUT貼圖的函式。請注意在程式碼中,針對A,B的兩個變數的賦值。

float3

IntegrateBRDF

uint2

Random

float

Roughness

float

NoV

{

float3

V

V

x

=

sqrt

1。0f

-

NoV

*

NoV

);

// sin

V

y

=

0

V

z

=

NoV

// cos

float

A

=

0

float

B

=

0

float

C

=

0

const

uint

NumSamples

=

64

for

uint

i

=

0

i

<

NumSamples

i

++

{

float2

E

=

Hammersley

i

NumSamples

Random

);

{

float3

H

=

ImportanceSampleGGX

E

Pow4

Roughness

)。

xyz

float3

L

=

2

*

dot

V

H

*

H

-

V

float

NoL

=

saturate

L

z

);

float

NoH

=

saturate

H

z

);

float

VoH

=

saturate

dot

V

H

);

if

NoL

>

0

{

float

a

=

Square

Roughness

);

float

a2

=

a

*

a

float

Vis

=

Vis_SmithJointApprox

a2

NoV

NoL

);

float

Vis_SmithV

=

NoL

*

sqrt

NoV

*

NoV

-

NoV

*

a2

+

a2

);

float

Vis_SmithL

=

NoV

*

sqrt

NoL

*

NoL

-

NoL

*

a2

+

a2

);

//float Vis = 0。5 * rcp( Vis_SmithV + Vis_SmithL );

// Incident light = NoL

// pdf = D * NoH / (4 * VoH)

// NoL * Vis / pdf

float

NoL_Vis_PDF

=

NoL

*

Vis

*

4

*

VoH

/

NoH

);

float

Fc

=

pow

1

-

VoH

5

);

A

+=

1

-

Fc

*

NoL_Vis_PDF

B

+=

Fc

*

NoL_Vis_PDF

}

}

{

float3

L

=

CosineSampleHemisphere

E

)。

xyz

float3

H

=

normalize

V

+

L

);

float

NoL

=

saturate

L

z

);

float

NoH

=

saturate

H

z

);

float

VoH

=

saturate

dot

V

H

);

float

FD90

=

0。5

+

2

*

VoH

*

VoH

*

Roughness

float

FdV

=

1

+

FD90

-

1

*

pow

1

-

NoV

5

);

float

FdL

=

1

+

FD90

-

1

*

pow

1

-

NoL

5

);

C

+=

FdV

*

FdL

*

1

-

0。3333

*

Roughness

);

}

}

return

float3

A

B

C

/

NumSamples

}

在完成這項工作之後,我們發現目前的和同時進行的研究,幾乎都是和我們一致的結果。Whilst Gotanda使用了3D查詢表[8],Drobot最佳化它到2D的查詢表[7],就和我們所做的那樣。另外,作為這個課題的一員——Lazarov又向前邁進了一步[11],展示了相似積分的一對解析近似(這個方案中使用了不同的D和G函式)。

最後,為了近似重要性取樣的引用,我們將這兩個預計算的求和進行相乘的操作。

float3

ApproximateSpecularIBL

uint2

Random

float3

SpecularColor

float

Roughness

float3

N

float3

V

{

// Function replaced with prefiltered environment map sample

float3

R

=

2

*

dot

V

N

*

N

-

V

float3

PrefilteredColor

=

PrefilterEnvMap

Random

Roughness

R

);

//float3 PrefilteredColor = FilterEnvMap( Random, Roughness, N, V );

// Function replaced with 2D texture sample

float

NoV

=

saturate

dot

N

V

);

float2

AB

=

IntegrateBRDF

Random

Roughness

NoV

)。

xy

return

PrefilteredColor

*

SpecularColor

*

AB

x

+

AB

y

);

}

注:這個函式,只是說明了整個演算法而已,在真正去進行計算的時候,是不會採用這個方法的,而是,選擇直接進行針對預積分貼圖取樣的演算法。如下面的程式碼所示。

void

MainPS

in

noperspective

float4

UVAndScreenPos

TEXCOORD0

float4

SvPosition

SV_POSITION

out

float4

OutColor

SV_Target0

{

……

{

float

Mip

=

ComputeCubemapMipFromRoughness

GBuffer

Roughness

AmbientCubemapMipAdjust

w

);

float3

SampleColor

=

TextureCubeSampleLevel

AmbientCubemap

AmbientCubemapSampler

R

Mip

)。

rgb

SpecularContribution

+=

SampleColor

*

EnvBRDF

GBuffer

SpecularColor

GBuffer

Roughness

NoV

);

//SpecularContribution += ApproximateSpecularIBL( Random, GBuffer。SpecularColor, GBuffer。Roughness, GBuffer。WorldNormal, -ScreenVector );

}

}

half3

EnvBRDF

half3

SpecularColor

half

Roughness

half

NoV

{

// Importance sampled preintegrated G * F

float2

AB

=

Texture2DSampleLevel

PreIntegratedGF

PreIntegratedGFSampler

float2

NoV

Roughness

),

0

)。

rg

// Anything less than 2% is physically impossible and is instead considered to be shadowing

float3

GF

=

SpecularColor

*

AB

x

+

saturate

50。0

*

SpecularColor

g

*

AB

y

return

GF

}

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

圖4:最上方為參考(重要性取樣方案),分解求和近似(Split sum approxmation)位於中間,包含n=v假設的Complete Approximation在最底部。徑向對稱假設引入了誤差最大,但是組合近似依然和參考十分相似。

[譯]Real Shading in Unreal Engine 4(UE4中的真實渲染)(1)

圖5:電介質的對比圖(對比項與圖4相同)

思考:

Shading Model這部分到這裡基本上就算是完成了,剩下的Material Model和Lighting部分,放在下一篇吧。

針對這部分進行翻譯後,我個人對UE Shading Model有一些感受,跟大家分享一下:

1、對於UE4的初學者來說,我們也不要把UE4想得太神化。呵呵,從這個過程中,我們可以比較清晰地看出,從UE3向UE4轉換的主體思路。

2、引擎這個層面還是針對理論學界的各種演算法來進行實現的,下面列舉的參考文獻,其實,才是我們深入要去理解和分析的。如果這些基本的理論依據不能理解,對UE4的實現也就只能停留在表面。當然,這裡面涉及的知識實在是太多了,如果我們不做學術的話,有一些理論至少得理解。

3、UE4也是有很多折中和妥協的,比如,Specular這個概念。在文中,作者是很不行保留這個概念了,但是,《堡壘之夜》大量使用了這個材質屬性,估計最後作為引擎開發者,也只能妥協。

4、UE4依然是不斷在進化的,從文章中給出的參考實現程式碼,到UE4。21的最新程式碼不同這一點就能看出來。這主要還是因為,圖形學是在不斷演變和進化的,大家在學習的時候,要有一個認知。

5、對於實時渲染而言,一個重點要考慮的問題就是效率問題。在上面的各種演算法最佳化過程中,主要就是針對這種思路來實現。最佳化的方案主要有兩種:1個就是在純粹在數學上進行擬合,比如球面高斯擬合;第2個方案就是增加假設條件,比如,預積分環境貼圖生成的兩個重要假設。第一個進行數學逼近還好,第二個就是整體帶來偏差的主要原因了。

6、從未來的角度講,肯定還是會出現各種方案來最佳化各種D,G,F函式,以及針對環境光的各種最佳化演算法。如果因為效率還不能使用光追的話,在第5部分的各種最佳化還是會不斷進行。

7、不過,可喜的是,”光線追蹤“似乎就要來了,不光英偉達,AMD也基本上能夠做出”光線追蹤“的顯示卡了。在這樣的情況下,可能整個一套渲染方案,會產生一個更大的變化了。當然,移動裝置上可能還不行,所以,這套思路還是需要進一步研究和發展下去。

參考文獻:

[1] AMD, CubeMapGen: Cubemap Filtering and Mipchain Generation Tool。

http://

developer。amd

。 com/resources/archive/archived-tools/gpu-tools-archive/cubemapgen/

[2] Burley, Brent, “Physically-Based Shading at Disney”, part of “Practical Physically Based Shading in Film and Game Production”, SIGGRAPH 2012 Course Notes。

http://

blog。selfshadow。com/

publications/s2012-shading-course/

[3] Colbert, Mark, and Jaroslav Krivanek, “GPU-based Importance Sampling”, in Hubert Nguyen, ed。, GPU Gems 3, Addison-Wesley, pp。 459–479, 2007。

http://

http。developer。nvidia。com

/

GPUGems3/gpugems3_ch20。html

[4] Coffin, Christina, “SPU Based Deferred Shading in Battlefield 3 for Playstation 3”, Game Developers Conference, March 2011。

http://www。

slideshare。net/DICEStud

io/spubased-deferred-

shading-in-battlefield-3-for-playstation-3

[5] Cook, Robert L。, and Kenneth E。 Torrance, “A Reflectance Model for Computer Graphics”, Computer Graphics (SIGGRAPH ’81 Proceedings), pp。 307–316, July 1981。

[6] Cook, Robert L。, and Kenneth E。 Torrance, “A Reflectance Model for Computer Graphics”, ACM Transactions on Graphics, vol。 1, no。 1, pp。 7–24, January 1982。

http://

graphics。pixar

。 com/library/ReflectanceModel/

[7] Drobot, Michal , “Lighting Killzone: Shadow Fall”, Digital Dragons, April 2013。

http://

www

http://

guerrilla-games。com/pub

lications/

[8] Gotanda, Yoshiharu, “Practical Implementation of Physically-Based Shading Models at tri-Ace”, part of “Physically-Based Shading Models in Film and Game Production”, SIGGRAPH 2010 Course Notes。

http://

renderwonk。com/publicat

ions/s2010-shading-course/

[9] Hoffman, Naty, “Background: Physics and Math of Shading”, part of “Physically Based Shad- ing in Theory and Practice”, SIGGRAPH 2013 Course Notes。

http://

blog。selfshadow。com/

publications/s2013-shading-course/

[10] Lagarde, S ́ebastien, “Spherical Gaussian approximation for Blinn-Phong, Phong and Fresnel”, June 2012。

http://

seblagarde。wordpress。com

/2012/06/03/spherical-gaussien-approximation-

for-blinn-phong-phong-and-fresnel/

[11] Lazarov, Dimitar, “Getting More Physical in Call of Duty: Black Ops II”, part of “Physi- cally Based Shading in Theory and Practice”, SIGGRAPH 2013 Course Notes。

http://

blog

http://

selfshadow。com/publicat

ions/s2013-shading-course/

[12] Martinez, Adam, “Faster Photorealism in Wonderland: Physically-Based Shading and Lighting at Sony Pictures Imageworks”, part of “Physically-Based Shading Models in Film and Game Pro- duction”, SIGGRAPH 2010 Course Notes。

http://

renderwonk。com/publicat

ions/s2010-shading-

course/

[13] Mittring, Martin, and Bryan Dudash, “The Technology Behind the DirectX 11 Unreal Engine Samaritan Demo”, Game Developer Conference 2011。

http://

udn。epicgames。com/Three

/rsrc/

Three/DirectX11Rendering/MartinM_GDC11_DX11_presentation。pdf

[14] Mittring, Martin, “The Technology Behind the Unreal Engine 4 Elemental demo”, part of “Ad- vances in Real-Time Rendering in 3D Graphics and Games Course”, SIGGRAPH 2012。 http: //

http://www。

unrealengine。com/files/

misc/The_Technology_Behind_the_Elemental_Demo_16x9_(2)

。pdf

[15] Oat, Chris, “Ambient Aperture Lighting”, SIGGRAPH 2006。

http://

developer。amd。com/

wordpress/media/2012/10/Oat-AmbientApetureLighting。pdf

[16] Picott, Kevin P。, “Extensions of the Linear and Area Lighting Models”, Computers and Graphics, Volume 12 Issue 2, March 1992, pp。 31-38。

http://

dx。doi。org/10。1109/38。1

24286

[17] Poulin, Pierre, and John Amanatides, “Shading and Shadowing with Linear Light Sources”, IEEE Computer Graphics and Applications, 1991。

http://www。

cse。yorku。ca/~amana/res

earch/

[18] Quilez, Inigo, “Spherical ambient occlusion”, 2006。

http://www。

iquilezles。org/www/arti

cles/

sphereao/sphereao。htm

[19] Schlick, Christophe, “An Inexpensive BRDF Model for Physically-based Rendering”, Computer Graphics Forum, vol。 13, no。 3, Sept。 1994, pp。 149–162。

http://

dept-info。labri。u-bordeaux。fr

/

~schlick/DOC/eur2。html

[20] Snow, Ben, “Terminators and Iron Men: Image-based lighting and physical shading at ILM”, part of “Physically-Based Shading Models in Film and Game Production”, SIGGRAPH 2010 Course Notes。

http://

renderwonk。com/publicat

ions/s2010-shading-course/

[21] Walter, Bruce, Stephen R。 Marschner, Hongsong Li, Kenneth E。 Torrance, “Microfacet Models for Refraction through Rough Surfaces”, Eurographics Symposium on Rendering (2007), 195–206, June 2007。

http://www。

cs。cornell。edu/~srm/pub

lications/EGSR07-btdf。html

[22] Wang, Lifeng, Zhouchen Lin, Wenle Wang, and Kai Fu, “One-Shot Approximate Local Shading” 2006。

標簽: roughness  http  取樣  Shading  UE4