名詞解釋
條目 | 解釋 |
---|---|
Sclera | 鞏膜[眼球表層的白色纖維膜,堅韌耐壓驱富,有支撐和保護眼球內(nèi)部組織的作用。] |
Limbus | 角膜緣[角膜同鞏膜之間的一條灰白色過渡帶,也即白色鞏膜組織同透明的角膜組織間的一條半透明灰白色的帶震檩,是角膜與鞏膜的移行區(qū),角膜鑲嵌在鞏膜而逐漸過渡到鞏膜組織內(nèi)僚焦。其寬度也不一致逼侦,上緣較寬,下緣次之鸡典,水平緣更窄源请。] |
Cornea | 角膜[人和某些動物眼球前方最外面的一層纖維膜。無色透明彻况,沒有血管谁尸,反應靈敏。] |
Iris | 虹膜[眼球前部角膜和晶狀體之間含色素的環(huán)形薄膜纽甘。膜的中間是瞳孔良蛮。舊稱虹彩。] |
Pupil | 瞳孔[眼球虹膜中央進光的圓孔悍赢,可以隨光線的強弱而縮小或擴大决瞳。] |
Aqueous Humor | 眼房水[眼球晶狀體和角膜之間的透明液體货徙,由睫狀體的無色素上皮細胞分泌。] |
重要紋理(Textures)
條目 | 解釋 | 圖示 |
---|---|---|
Wet Normal map | 主法線貼圖皮胡,為眼球濕面(Wet surface)提供細微的起伏感痴颊。 | |
Sclera map | 對應控制眼白部分基礎色的貼圖,可給予貼圖血管和組織顏色以豐富眼白的細節(jié)胸囱。 | |
Tangent map | 控制表面切線走向祷舀,以便在不同的朝向下強調(diào)角膜和鞏膜的變化和區(qū)別。注意圖例中圓心中心和圓形外圍的起伏變化烹笔,它們分別對應了角膜和鞏膜裳扯。 | |
Mid Plane Displacement map | 該貼圖用于鎖定一個橫切眼部中心的平面,之后基于這個平面來計算角膜的深度偏移谤职。 | |
Eye Diffuse | 注意角膜貼圖非常特殊饰豺,它與模型的UV布局并不匹配,相反允蜈,從圖例中可以看出冤吨,角膜基礎色填充滿了整張矩形紋理。后續(xù)UE將會通過UV和Alpha Mask來控制整個角膜的尺寸饶套,也包括瞳孔的大小漩蟆。 | |
Environment Texture Cube | 控制眼部高光反射內(nèi)容的環(huán)境光貼圖 | |
Noise | 通用噪聲圖 |
主要參數(shù)(Values)
條目 | 解釋 | 解釋原文 |
---|---|---|
Depth Scale[scaler] | 控制經(jīng)過角膜折射后,虹膜偏折的深度妓蛮。 | This controls the depth of the refraction of the iris underneath the cornea. |
Flatten Normal[scaler] | 控制全局眼球法線的平順度怠李,主要影響眼白部分(鞏膜)。 | This value controls how much flattening of the eye's normal map is taking place, focused particularly on the sclera. |
IOR (Index of Refraction)[scaler] | 角膜到晶狀體之間房水的折射率蛤克,控制折射程度捺癞。 | Index of refraction of the fluids underneath the cornea. Controls how much refraction takes place. |
Iris Concavity Power[scaler] | 與Iris Concavity Scale一起控制在虹膜表面因光線透射過角膜而形成的焦散(caustics)的形狀和強度。通常只有在真實光照環(huán)境下才可見构挤。 | Used alongside Iris Concavity Scale to control the shape and amount of light caustics that are calculated on the surface of the iris as light passes through the cornea. This will generally only be visible in an actual lit scene, and can be difficult to visualize within the Material Instance Editor. |
Iris Concavity Scale[scaler] | 同上髓介。 | ditto. |
Iris UV Radius[scaler] | 控制眼球上虹膜的整體大小。 | Controls the overall size of the iris on the eyeball. |
Iris Brightness[scaler] | 控制虹膜的明亮程度筋现。 | Controls the brightness of the iris. |
Iris Roughness[scaler] | 該值影響角膜(虹膜之上的表面)的閃亮(Shiny)程度唐础。 | This value drives how shiny the cornea is (the surface directly over the iris). |
Limbus Dark Scale[scaler] | 控制角膜邊緣暗環(huán)的大小。 | Controls the size of the darkening ring of the limbus. |
Limbus Power[scaler] | 控制角膜邊緣暗環(huán)向鞏膜(眼白)的擴散程度矾飞,過大的數(shù)值會染黑整個鞏膜彻犁。 | Controls the overall darkening of the limbus area. Overdriven values will darken the entire corneal area. |
Limbus UV Width Color[scaler] | 控制角膜緣的采樣尺寸,或者說要分配多少眼球的表面積來顯示角膜緣凰慈。這是個非常精巧的參數(shù)汞幢,小心設置它。 | Controls the sample size for the limbus, or how much of the eye surface will be alloted for showing the limbus. This is a fairly delicate setting and should be adjusted with care. |
Limbus UV Width Shading[scaler] | 控制有多少光照能夠影響角膜緣的渲染微谓。同樣非常精巧森篷,需要小心設置输钩。 | Controls how much light will affect the shading of the limbus. Very delicate setting, adjust with care. |
Normal UV Scale[scaler] | 控制Wet Normal紋理的縮放。 | Controls the scale of the normal map texture used across the surface of the eye. |
Pupil Scale[scaler] | 控制瞳孔大小仲智,用這個參數(shù)來擴張/縮小瞳孔买乃。 | Controls the size of the pupil. This is the setting you would use to dilate the eyes. |
Refraction On/Off[scaler] | 用于混合帶折射和不帶折射版本的著色結(jié)果。 | Blends between refracting and non-refracting versions of the shader. |
Scale By Center[scaler] | 調(diào)整整個虹膜/瞳孔的縮放(縮放基于中心)钓辆。 | Adjusts the scale of the entire iris/pupil area from its center. |
Sclera Brightness[scaler] | 控制鞏膜的明亮程度(或者白皙程度)剪验。 | Controls the brightness of the sclera, or white of the eye. |
Sclera Roughness[scaler] | 控制鞏膜(眼白)部分材質(zhì)的粗糙度。 | Controls the Material Roughness value of the sclera. |
Specularity Iris[scaler] | 控制在角膜區(qū)域(虹膜和瞳孔)形成的高光強度前联。 | Controls specularity level across the cornea (iris and pupil). |
Specularity Sclera[scaler] | 控制在鞏膜(眼白)區(qū)域形成的高光強度功戚。 | Controls the specularity level across the sclera. |
Shadow Hardness[scaler] | 控制鞏膜內(nèi)外層顏色混合的銳利度。與Shadow Radius聯(lián)合使用似嗤。 | Controls the sharpness of the blend between the sclera inner and outer color. Used with Shadow Radius to help drive shading across the surface of the sclera, approximating the effect of the eyelid casting subsurface scattered shadows across the surface of the eyeball. |
Shadow Radius[scaler] | 控制鞏膜內(nèi)外層顏色混合的銳利度啸臀。與Shadow Hardness聯(lián)合使用。 | Controls the size of the blend between the inner and outer colors of the sclera. Used with Shadow Hardness . |
重要代碼段解析
1. ScaleUVsByCenter
float2 ScaleUVsByCenter(float2 uv, float Scale = 1)
{
float2 outUV;
outUV = uv / Scale + 0.5 - 0.5 / Scale;
return outUV;
}
解釋:令 b = 1 / Scale
烁落,則有乘粒,outUV = uv * b - 0.5 * b + 0.5 = (uv - 0.5) * b + 0.5;
該式將整個分布在[0, 1]區(qū)間的uv先平移到中心點對齊0點的位置,然后進行尺度為b的縮放伤塌,最后再平移回中心點為(0.5, 0.5)的正常位置灯萍。
當Scale調(diào)大 -> b縮小 -> 令uv的分布向中心點緊縮 -> 原本可以采樣到紋理外圍的點,現(xiàn)在只能采樣到靠近中心的紋素了 -> 反過來想就是紋理的中心部分紋素向外擴張每聪。
2. IrisiUVMask
float2 IrisiUVMask(float IrisUVRadius, float2 UV, float2 LimbusUVWidth)
{
// Iris Mask with Limbus Ring falloff
UV = UV - float2(0.5f, 0.5f);
float2 m, r;
r = (length(UV) - (IrisUVRadius - LimbusUVWidth)) / LimbusUVWidth;
m = saturate(1 - r);
m = smoothstep(0, 1, m);
return m;
}
解釋:入?yún)risUVRadius是用戶設置參數(shù)旦棉,表示UV尺度上虹膜的半徑,而虹膜的邊緣有一圈暗色的角膜緣(Limbus)熊痴,參考入?yún)imbusUVWidth他爸,注意這是個float2類型的值聂宾,可以認為其xy分量分別代表了Limbus的外側(cè)和內(nèi)側(cè)邊緣果善,比如LimbusUVWidth=[0.01, 0.045]
表示從虹膜半徑IrisUVRadius=0.133
往內(nèi)移動0.01
的UV距離是Limbus的外側(cè),繼續(xù)移動(0.045 - 0.01 = 0.035)
的UV距離則可觸碰到Limbus的內(nèi)邊緣系谐。
方法現(xiàn)將UV的中心點對齊到0
點巾陕,這樣計算length(UV)
時就能獲得著色點的UV半徑。
算式:r = (len(UV) - (R - W)) / W;
獲得的返回值r可以這樣理解:
- 若r < 0 則說明點在Limbus環(huán)以內(nèi)纪他;
- 若0 < r < 1 則說明點在Limbus環(huán)上鄙煤;
- 若 r > 1 表示點在整個虹膜之外。
后面通過 m = sat(1 - r)茶袒;
將r
重新映射梯刚,使得:
- 若m < 0 -> 點在Limbus環(huán)外;
- 若m 從0過渡到1 -> 點從環(huán)外邊緣過渡到環(huán)內(nèi)邊緣薪寓;
- 若m > 1 -> 點在虹膜上(不在Limbus環(huán)上)亡资。
最終通過 m = smoothstep(0, 1, m);
將原本的線性過渡替換為平滑過渡澜共。
上圖黃色外邊緣實際上是Limbus的內(nèi)邊緣,而紅色外邊緣則是Limbus的外邊緣锥腻。
3. RefractionDirection
float3 RefractionDirection(float internalIoR, float3 normalWS, float3 cameraWS)
{
float airIoR = 1.00029;
float n = airIoR / internalIoR;
float facing = dot(normalWS, cameraWS);
float w = n * facing;
float k = sqrt(1 + (w - n) * (w + n));
float3 t;
t = (w - k) * normalWS - n * cameraWS;
t = normalize(t);
return -t;
}
圖示:
如圖[A]所示嗦董,入射光線經(jīng)介質(zhì)分界面形成折射,假設入射角為 θ1
瘦黑,折射角為θ2
京革,入射介質(zhì)和出射介質(zhì)的折射率(IoR)分別為n1
和n2
,且由Snell折射定律可知:n1sinθ1 = n2sinθ2
幸斥。方法RefractionDirection利用入射向量V
匹摇,介質(zhì)分界面法線N
,以及折射率n1
和n2
來計算折射向量R
睡毒。
首先方法定義了 n = airIoR / internalIoR = n1 / n2 = sinθ2 / sinθ1来惧;
(1)
另外定義了facing = dot(N, V) = cosθ1;
(2)
接下來將 w = n * facing = n * cosθ1
帶入到 k = sqrt(1 + (w - n) * (w + n))
中演顾,并重組多項式有:
k = sqrt(1 + n^2 * cosθ1^2 - n^2);
k = sqrt(1 - n^2(1 - cosθ1^2) );
由三角公式已知:sinθ^2 + cosθ^2 = 1;
代入上式可得:
k = sqrt(1 - n^2 * sinθ1^2);
由折射定律可知 n^2 = (sinθ2 / sinθ1)^2 -> n^2 * sinθ1^2 = sinθ2^2
供搀,代入上式可得:
k = sqrt(1 - sinθ2^2);
繼續(xù)套用三角公式最終可得
k = cosθ2; (θ2 ∈[0, π/2])
(3)
其次是計算折射向量R
,原始是這個公式:t = (w - k) * N - n * V;
展開重組一下:t = w * N - k * N - n * V;
其中 w = n * cosθ1
钠至,代入上式得:
t = n * cosθ1 * N - n * V - k * N;
合并含n
的項:
t = n * (cosθ1 * N - V) - k * N;
這里N
和V
都是單位向量葛虐,參考圖示[B],由cosθ1 = dot(N, V)
可知棉钧,cosθ1 * N
在物理上可以認為是單位向量V
在單位向量N
上的投影N'
屿脐。
這樣上式括號中的部分就可以轉(zhuǎn)換為切線T'
,參考圖示[C]宪卿,T'
沿著切線朝向的诵,其模長正好為:sinθ1
。這樣上式可改寫成如下形式:
t = n * T' - k * N;
代入(1)可得:
t = (sinθ2 / sinθ1) * T' - k * N佑钾;
其中的T'
如前文所示西疤,可以改寫為sinθ1 * T
, 其中T
代表切線朝向的單位向量休溶。
t = (sinθ2 / sinθ1) * (sinθ1 * T) - k * N代赁;
化簡并帶入(3)式可得:
t = sinθ2 * T - cosθ2 * N;
參考圖示[D]兽掰,其中切線方向的深紅色向量就是(sinθ2 * T)
芭碍,它代表折射單位向量R在切線方向上的投影。
t = sinθ2 * T + cosθ2 * (-N)孽尽;
借用符號窖壕,將N
轉(zhuǎn)換為-N
,參考圖示[E],其中負法線方向的深紅色向量就是(cosθ2 * (-N))
瞻讽,它代表折射單位向量R
在負法線上的投影狐蜕。至此可得: t = R
;
最后通過:t = normalize(t); return -t;
獲得了歸一化后的折射方向R的反方向。
4. EyeRefraction
void EyeRefraction(
float IoR, float ScaleByCenter, float2 LimbusUVWidth, float DepthScale,
float DepthPlaneOffset, float3 MidPlaneDisplacement, float3 EyeDirectionWorld,
float IrisUVRadius, float2 InputUV, float3 PixelNormalWS, float3 ViewDirWS,
float3 TangentWS, out float2 OutputRefractedUV, out float2 OutputIrisMask)
{
//Step#1 計算虹膜遮罩
float2 scaledUV = ScaleUVsByCenter(InputUV, ScaleByCenter);
OutputIrisMask = IrisiUVMask(IrisUVRadius, scaledUV, LimbusUVWidth);
//Step#2 計算折射向量并據(jù)此計算折射UV
float3 RefractionDir = RefractionDirection(IoR, PixelNormalWS, ViewDirWS);
float cosAlpha = dot(EyeDirectionWorld, ViewDirWS);
float facingRatio = lerp(0.325, 1, cosAlpha * cosAlpha);
float heightW = max(0, MidPlaneDisplacement - DepthPlaneOffset);
heightW *= DepthScale;
float ScaleRefractionFactor = heightW / facingRatio;
RefractionDir *= ScaleRefractionFactor;
float3 IrisTangentWS = TangentWS - dot(TangentWS, EyeDirectionWorld) * EyeDirectionWorld;
IrisTangentWS = normalize(IrisTangentWS);
float3 IrisBitangentWS = cross(IrisTangentWS, EyeDirectionWorld);
float2 RefractedUVOffset = float2(dot(RefractionDir, IrisTangentWS), dot(RefractionDir, IrisBitangentWS));
float2 RefractedUV = IrisUVRadius * float2(-1, 1) * RefractedUVOffset + scaledUV;
OutputRefractedUV = lerp(scaledUV, RefractedUV, OutputIrisMask.r);
}
解釋:入?yún)⒂糜幸恍┦乔拔亩x的全局材質(zhì)入?yún)⑿断Γ孕袑φ詹檎壹纯刹闶停幸恍┎皇牵@里說一說:
- EyeDirectionWorld -> 虹膜平面上的世界空間法線
- PixelNormalWS -> 眼球濕面對應的世界空間法線(Wet Normal: 包含Cornea和Sclera表面法線)
- ViewDirWS -> 視方向(從著色點指向攝像機)
- TangentWS -> 眼球模型對應的世界空間切線
- MidPlaneDisplacement -> 是基于虹膜平面的整個眼睛前半球的深度偏移
- DepthPlaneOffset -> 是基于虹膜平面的位于虹膜邊緣處的深度偏移(所有像素都是這個值)
- OutputRefractedUV -> 輸出變量: 經(jīng)過折射影響后的UV分布
- OutputIrisMask -> 輸出變量: UV空間中定義的虹膜范圍
所以總體上該方法是用于計算視角光線經(jīng)過角膜后房水的折射快集,到達虹膜時的坐標的贡羔。當然因為是實時渲染環(huán)境,方法返回的虹膜坐標實際上是以UV采樣坐標的形式表述的个初。下面找一些重要代碼簡單解讀一下:
cosAlpha = dot(EyeDirectionWorld, ViewDirWS)
是攝像機視角與虹膜平面法線形成的夾角余弦 (Facing Ratio)乖寒,注意EyeDirectionWorld代表虹膜表面的法線分布,區(qū)別于眼球表面法線院溺,該法線相對眼球法線而言呈內(nèi)凹狀態(tài)楣嘁。
heightW = max(0, MidPlaneDisplacement - DepthPlaneOffset)
所得計算結(jié)果是整個虹膜區(qū)域的深度差,可以簡單理解為:當heightW=0
時虹膜到角膜之間的深度差為0
珍逸,意味著該區(qū)域位于虹膜(角膜緣)之外逐虚,反之則在虹膜以內(nèi)。另外由于深度圖中心數(shù)值高谆膳,邊緣低的設計特性叭爱,當說色點接近瞳孔時(靠近中心),深度差值大漱病,反之亦然买雾。
ScaleRefractionFactor = heightW / facingRatio
是一個正比于高度差,反比于視角與虹膜法線相似度的標量杨帽,用于修正折射向量的模長漓穿,從而使得:
- 越靠近虹膜中心,折射效果越強
- 視角越偏(側(cè)視)注盈,折射效果越強
接下來是如何將折射向量轉(zhuǎn)化為貼圖UV晃危,過程非常有意思。
首先是計算折射向量在虹膜平面上的投影当凡,這需要用到虹膜平面的切線和副切線山害,我們來看看UE的做法:
IrisTangentWS = TangentWS - dot(TangentWS, EyeDirectionWorld) * EyeDirectionWorld纠俭;
上式利用眼球模型切線和虹膜法線沿量,直接構(gòu)造出垂直于虹膜法線的“虹膜切線”。
然后利用虹膜切線和已知的虹膜法線冤荆,構(gòu)造“虹膜副切線”朴则。
IrisBitangentWS = cross(IrisTangentWS, EyeDirectionWorld);
這樣就能如下式所示,將折射向量(-R)
分別投影到虹膜切線和虹膜副切線上:
RefractedUVOffset = float2(dot(RefractionDir, IrisTangentWS), dot(RefractionDir, IrisBitangentWS));
該計算結(jié)果將會得到一個位于[0,1]
區(qū)間上虹膜貼圖采樣的UV偏移(Offset) -> RefractedUVOffset。
應用這個偏移乌妒,如下式所示汹想,UE重新調(diào)整折射UV偏移范圍,使其落在IrisUVRadius規(guī)定的UV范圍之內(nèi)撤蚊,同時翻轉(zhuǎn)U方向古掏,使水平朝向上抵消折射向量(-R)
中的符號影響,匡正視覺效果上的錯誤:
StructuredRefractedUV = IrisUVRadius * float2(-1, 1) * RefractedUVOffset;
然后在經(jīng)過如下公式侦啸,將調(diào)整后UV偏移疊加到縮放過的UV上槽唾,得到折射后采樣紋理可用的UV:
RefractedUV = StructuredRefractedUV + scaledUV;
對比效果參考下圖:
在方法的最后光涂,為了只讓虹膜和瞳孔部分產(chǎn)生折射偏移庞萍,UE使用Step#1中的虹膜遮罩參與lerp:
OutputRefractedUV = lerp(scaledUV, RefractedUV, OutputIrisMask.r) ;
注意忘闻,OutputIrisMask.r
從1
趨向0
的過程對應了在UV空間中由瞳孔趨向角膜緣外邊緣的過程钝计。
5. CalcIrisDistance
float CalcIrisDistance(float2 RefractedUV, float IrisUVRadius,
float IrisConcavityScale, float IrisConcavityPower)
{
float UVRadius = length(RefractedUV - 0.5);
float IrisUVSpaceDistance = UVRadius / IrisUVRadius;
IrisUVSpaceDistance *= IrisConcavityScale;
return saturate(pow(IrisUVSpaceDistance, IrisConcavityPower));
}
解釋:方法通過數(shù)學公式擬合的方式,將水平方向上折射點UV到瞳孔中心點的距離(UV空間中的半徑)映射到著色點之于虹膜整體的距離(既Iris Distance)齐佳。
方法首先通過length(RefractedUV - 0.5)
折算出UV空間中距離中心點距離私恬,在通過除以虹膜UV半徑(IrisUVRadius)獲得定義在虹膜UV空間內(nèi)的UV距離IrisUVSpaceDistance。最后進過參數(shù)IrisConcavityScale和IrisConcavityPower的縮放和乘方調(diào)整炼吴,映射成虹膜距離践付,具體映射趨勢參考下圖:
該映射后結(jié)果即是IrisDistance,又作為GBuffer的Metallic屬性缺厉。
6. ScalePupils
float2 ScalePupils(float2 UV, float PupilScale)
{
float2 UVcentered = UV - float2(0.5f, 0.5f);
float UVlength = length(UVcentered);
float2 UVmax = normalize(UVcentered) * 0.5f;
float2 UVscaled = lerp(UVmax, float2(0.f, 0.f), saturate((1.f - UVlength * 2.f) * PupilScale));
return saturate(UVscaled + float2(0.5f, 0.5f));
}
解釋:方法將輸入的沿著貼圖紋理軸向均勻展開的UV重新映射成由中心點(0.5,0.5)
向四周環(huán)狀散射展開的形式永高,同時按照PupilScale規(guī)定的比例將UV沿著放射線朝向進行縮放,從而達到擴展/縮小瞳孔的目的提针。
方法構(gòu)造了中心點(0
點)對齊的最大環(huán)狀散射UV:UVmax = normalize(UVcentered) * 0.5f
命爬,通過巧妙的normalize將UV的模長固定為1
,同時保留原有的朝向辐脖,之后再通過 (* 0.5)
構(gòu)造出UV的最大半徑(在中心0
點對齊的UV空間饲宛,UV取值范圍是-0.5 ~ +0.5
)。
方法隨后利用:UVscaled = lerp(UVmax, float2(0.f, 0.f), saturate((1.f - UVlength * 2.f) * PupilScale))
完成縮放嗜价,具體來說就是構(gòu)造lerp艇抠,在UV與0
點連線的放射狀朝向上從0
到UVmax
進行縮放,縮放因子是另一個入?yún)ⅲ篜upilScale久锥,式中的(1.f - UVlength * 2.f)
部分確奔矣伲縮放不會超過UV的最大值。
7. ScaleIrisAndPupilsUV
void ScaleIrisAndPupilsUV(float IrisUVRadius, float PupilScale, float2 RefractedUV,
float LimbusDarkScale, float LimbusPow, out float2 ScaledIrisPupilsUV, out float ScaledLimbusDarkMask)
{
float IrisUVDiameter = IrisUVRadius * 2;
float2 ScaledIrisUV = ScaleUVsByCenter(RefractedUV, IrisUVDiameter)
ScaledIrisPupilsUV = ScalePupils(ScaledIrisUV, PupilScale);
float2 CenterLimbusDarkUV = (ScaledIrisPupilsUV - 0.5) * LimbusDarkScale;
float LimbusDarkDistance = length(CenterLimbusDarkUV);
ScaledLimbusDarkMask = 1 - pow(LimbusDarkDistance, LimbusPow);
}
void main(...)
{
...
float3 IrisColor = SAMPLE_TEXTURE2D(IrisMap, mySampler, ScaledIrisPupilsUV).rgb * ScaledLimbusDarkMask;
...
}
解釋:構(gòu)造出最終采樣虹膜貼圖的UV瑟由,以及對虹膜之外部分進行剔除的遮罩絮重。
方法首先計算出虹膜的UV空間直徑:IrisUVDiameter = IrisUVRadius * 2
,這個數(shù)值是接下來進行ScaleUVsByCenter的目標縮放倍率,目的是將原本紋理占比100%的虹膜部分通過UV縮放到在紋理空間中占比為IrisUVDiameter(圖例中為0.3
)大小的尺寸青伤。
接下來通過ScalePupils方法將UV沿著中心點向外的放射方向進行縮放督怜,從而對瞳孔的顯示效果進行調(diào)節(jié)。這時我們就得到了最終的IrisMap采樣UV:ScaledIrisPupilsUV狠角。
最后是計算能夠覆蓋角膜緣以內(nèi)部分的遮罩号杠,現(xiàn)將上述UV進行中心對齊,并再次進行縮放:CenterLimbusDarkUV = (ScaledIrisPupilsUV - 0.5) * LimbusDarkScale
丰歌,用戶通過調(diào)節(jié)縮放因子:LimbusDarkScale的大小究流,以便使得:LimbusDarkDistance = length(CenterLimbusDarkUV)
對應角膜緣的UV位置正好落在下圖中x軸向上[0, 1]
區(qū)間內(nèi),從而使角膜緣外的Mask值恒為0
动遭,角膜緣內(nèi)的Mask值參考下圖所示從0
到1
分布芬探。
總之UE使用輸出的ScaledIrisPupilsUV采樣虹膜貼圖,結(jié)果與遮罩ScaledLimbusDarkMask相乘厘惦,從而將完整的虹膜部分繪制出來偷仿,結(jié)果參考下列組圖:
8. SphereMask && EyeBaseColor
float SphereMask(float4 Coords, float4 Center, float Radius, float Hardness)
{
return 1 - saturate((distance(Coords, Center) - Radius) / (1 - Hardness));
}
void main(...)
{
...
//#Step 1
float2 ScaledScleraUV = ScaleUVsByCenter(RefractedUV, ScaleByCenter); //計算鞏膜紋理的縮放
float3 ScleraColor = SAMPLE_TEXTURE2D(ScleraMap, mySampler, ScaledScleraUV).rgb * ScleraBrightness; //采樣獲得鞏膜顏色
float3 EyeBaseColor = lerp(ScleraColor, IrisColor, ScaledLimbusDarkMask); //混合得到EyeBaseColor
//#Step 2
float3 EyeCloudyColor = SphereMask(ScaledIrisPupilsUV, 0.5, 0.18, 0.2) * CloudyIrisColor;
float EyeDarknessFactor = SphereMask(ScaledScleraUV, 0.5, ShadowRadius, ShadowHardness);
float3 EyeDraknessColor = lerp(EyeCornerDarknessColor, 1, EyeDarknessFactor);
EyeBaseColor = (BaseColor + EyeCloudyColor) * EyeDraknessColor;
...
}
解釋:在#Step1中UE將先前獲得的虹膜顏色“IrisColor”在主方法內(nèi)與另行采樣獲得的鞏膜顏色“ScleraColor”進行混合,混合遮罩使用了上文提及的“ScaledLimbusDarkMask”遮罩宵蕉,從而獲得較為完整的EyeBaseColor:
隨后在#Step2中酝静,UE為這個眼睛基礎上增加了2項額外顏色:分別是控制角膜內(nèi)渾濁度的“EyeCloudyColor”和控制環(huán)境光遮蔽程度的“EyeDraknessColor”。其中前者以Add的形式附加在基礎色上羡玛,后者則以 Mulityply(乘法)的形式將基礎上按比例壓暗别智。
如代碼所示,生成“EyeCloudyColor”和“EyeDraknessColor”這兩種遮罩使用到了SphereMask方法:
該方法用于生成一個均勻分布在UV空間中的圓形遮罩稼稿,圓心由入?yún)ⅰ癈enter”控制薄榛,“Radius”則定義了圓心到外邊緣的半徑,最后“Hardness”控制圓心向邊緣強度衰減半徑让歼,所有這些參數(shù)都基于UV空間敞恋。
生成的遮罩和最終合成效果參考如下圖例:
9. FlattenNormal & WetNormalWS
float3 FlattenNormal(float3 Normal, float flatness)
{
return lerp(Normal, float3(0, 0, 1), flatness);
}
void main(...)
{
...
float2 ScaledNormalUV = ScaleUVsByCenter(InputUV, NormalUVScale);
float3 WetNormalTS = SAMPLE_TEXTURE2D(WetNormalMap, mySampler, ScaledNormalUV).rgb;
float flatness = lerp(FlattenNormal, 1, IrisMask.r);
WetNormalTS = FlattenNormal(WetNormalTS, flatness);
WetNormalTS = WetNormalTS * GlobalNormalScale + GlobalNormalBias;
float WetNormalWS = TransformTangentToWorld(WetNormalTS, tbn);
...
}
解釋:這部分比較簡單就不贅述了,由于濕件部分(角膜+鞏膜)的法線需要對角膜部分進行特殊處理谋右,使其表面法線更加平坦硬猫,因此如上述代碼所示,UE對采樣后的WetNormalTS進行了一次基于flatness參數(shù)的平滑處理改执,而flatness確保其在角膜范圍內(nèi)達到最大值1
啸蜜。切線空間法線的處理后效果如下圖所示:
后記:
作為UE4.27新版電子人之前的眼球渲染解決方案,雖然在角膜折射方面辈挂,存在某些角度觀察時出現(xiàn)形變的現(xiàn)象衬横,但是其整體效果對得起所付出的計算消耗,甚至非常有性價比呢岗。如果有興趣了解具體源碼冕香,可以參考虛幻商城的“數(shù)字人類”資產(chǎn)中眼球部分的Shader實現(xiàn),以及UE4.26源碼部分“YourUnrealEngineFolder\Engine\Shaders\Private\ShadingModelsMaterial.ush”文件中ShadingModel == SHADINGMODELID_EYE
的部分后豫。
參考
[1] Digital Humans
[2] Digital Human Eye Shader
[3] Making of The Heretic: Digital Human tech package
[4] [UE4.26] 眼球渲染筆記
[5] ue眼球渲染
[6] Eye Shaders - Advanced Materials - Episode 12