中文版:https://edu.uwa4d.com/lesson-detail/282/1314/0?isPreview=0
英文原版:https://catlikecoding.com/unity/tutorials/custom-srp/lod-and-reflections/
一、URP LOD 組件
1、LOD Group的使用
1. 首先該組件需要將子類模型置于該組件物體子節(jié)點(diǎn)下
2. 可在單個(gè)LOD中設(shè)置其level的模型,并可設(shè)置它的距離范圍,即可在不同距離下顯示不同的模型
若模型變化時(shí)間不符合預(yù)期,有如下幾種方式調(diào)節(jié):
- 重新繼續(xù)Bound,Unity會(huì)根據(jù)三種LOD模型計(jì)算該模型的包圍盒,從而在計(jì)算物體占屏幕
2. Project Settings > Quality > Level of Detail > LOD Bias, 該變量增大物體的評(píng)估高度,從而導(dǎo)致LOD切換時(shí)占比與實(shí)踐物體占比不同。將 LOD Bias設(shè)為1,可以使組件閾值與實(shí)際大小同步。
- LOD過渡類型:
- Cross Fade(淡入淡出),F(xiàn)ade Transition Width可調(diào)節(jié)過渡區(qū)域占比
- Cross Fade(淡入淡出),F(xiàn)ade Transition Width可調(diào)節(jié)過渡區(qū)域占比
2、LOD切換原理
Cross Fade(淡入淡出)模式
當(dāng)啟用Cross Fade(淡入淡出)模式,相鄰兩個(gè)LOD對(duì)象會(huì)同時(shí)渲染出來,著色器將以某種方式進(jìn)行混合。Unity通常使用屏幕抖動(dòng)或者混合來實(shí)現(xiàn)Cross Fade。
在URP通用管線中,LOD現(xiàn)只用于SpeedTree7XXX.shader,即大面積樹木的渲染,其余Shader并未使用,但并不代表不可以自定義。
我們可以通過UnityPerDraw
下的變量float4 unity_LODFade;
取得LOD信息
CBUFFER_START(UnityPerDraw)
float4 unity_LODFade;
// x is the fade value ranging within [0,1].
// y is x quantized into 16 levels
CBUFFER_END
- x分量存儲(chǔ)過渡因子(逐漸遠(yuǎn)離消失的LOD對(duì)象,x分量從1變換到0;漸入的LOD對(duì)象,x分量從0變換到 -1 )
- y分量存儲(chǔ)了相同的因子,只不過被量化為16步
即,若漸出LOD的x值為0.4,則漸入LOD的值為 -0.6
我們可以通過一個(gè)Noise圖來決定使用哪一級(jí)LOD的選擇。
通過如下內(nèi)置函數(shù),即可快速得到一個(gè)Noise圖
float dither = InterleavedGradientNoise(positionCS.xy, 0);
使用屏幕抖動(dòng)實(shí)現(xiàn)LOD混合
void ShadowCasterPassFragment (Varyings input) {
UNITY_SETUP_INSTANCE_ID(input);
ClipLOD(input.positionCS.xy, unity_LODFade.x);
…
}
void ClipLOD (float2 positionCS, float fade) {
#if defined(LOD_FADE_CROSSFADE)
float dither = InterleavedGradientNoise(positionCS.xy, 0);
clip(fade + (fade < 0.0 ? dither : -dither));
#endif
}
Animated Cross-Fading
啟用Animated Cross-Fading后,不再通過距離去設(shè)置漸入漸出的比例,當(dāng)物體組比例超過LOD閾值就通過動(dòng)畫快速交叉漸變。
默認(rèn)的動(dòng)畫持續(xù)時(shí)間為半秒,可以通過設(shè)置static LODGroup.crossFadeAnimationDuration
來更改所有組的動(dòng)畫持續(xù)時(shí)間。然而,在unity2022中,當(dāng)不在播放模式下,轉(zhuǎn)換速度更快。
如果未設(shè)置Clip,并且Fade Transition Width不為0
則,當(dāng)距離處于交叉切換之間,會(huì)使兩個(gè)物體同時(shí)被渲染出來。
因此,如果未實(shí)現(xiàn)LOD交叉切換算法,請(qǐng)不要使用CrossFade選項(xiàng)。
LOD物體烘培
LOD0會(huì)被用于光照映射(Lightmapping)。其他LOD級(jí)別也會(huì)得到烘焙照明(Baked Light),但場(chǎng)景的其余部分只考慮LOD 0。你也可以決定只烘焙一些級(jí)別,讓其他級(jí)別依靠光探針。
SpeedTree 模式
這種模式是專門針對(duì)SpeedTree樹的,它使用自己的LOD系統(tǒng)來折疊樹,并在3D模型和廣告牌表示之間進(jìn)行轉(zhuǎn)換。
二、反射探針
1. 獲取反射探針數(shù)據(jù)
- 如果未定義LightMap(烘培光照),則會(huì)使用球諧函數(shù)作為基礎(chǔ)環(huán)境光顏色。此球諧函數(shù)即為環(huán)境球的球諧采樣結(jié)果。
- 若想使用IBL作為鏡面反射,需要添加反射探針標(biāo)志。
perObjectData |= PerObjectData.ReflectionProbes;
2. 環(huán)境光照明 IBL
在Unity中,IBL環(huán)境光照貼圖保存在UnityInput.hlsl
// Unity specific
TEXTURECUBE(unity_SpecCube0);
SAMPLER(samplerunity_SpecCube0);
TEXTURECUBE(unity_SpecCube1);
SAMPLER(samplerunity_SpecCube1);
在GlobalIllumination.hlsl中,使用函數(shù)
half3 CalculateIrradianceFromReflectionProbes(half3 reflectVector, float3 positionWS, half perceptualRoughness)
即可得到環(huán)境光照。函數(shù)中使用
half4 encodedIrradiance = half4(SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip));
得到CubeMap Mipmap插值采樣結(jié)果,并根據(jù)是否使用HDR解碼。
#if defined(UNITY_USE_NATIVE_HDR)
irradiance += weightProbe0 * encodedIrradiance.rbg;
#else
irradiance += weightProbe0 * DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
#endif // UNITY_USE_NATIVE_HDR
SAMPLE_TEXTURECUBE_LOD函數(shù)根據(jù)使用的API不同,實(shí)現(xiàn)各不相同
IBL在URP Shader中,通過如下函數(shù)得到包括環(huán)境光照在內(nèi)的所有全局光照。
lightingData.giColor = GlobalIllumination(brdfData, brdfDataClearCoat, surfaceData.clearCoatMask,
inputData.bakedGI, aoFactor.indirectAmbientOcclusion, inputData.positionWS,
inputData.normalWS, inputData.viewDirectionWS);
half3 reflectVector = reflect(-viewDirectionWS, normalWS);
half NoV = saturate(dot(normalWS, viewDirectionWS));
half fresnelTerm = Pow4(1.0 - NoV);
half3 indirectDiffuse = bakedGI;
half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, positionWS, brdfData.perceptualRoughness, 1.0h);
half3 color = EnvironmentBRDF(brdfData, indirectDiffuse, indirectSpecular, fresnelTerm);
- bakedGI值為L(zhǎng)ightMap烘培光照數(shù)據(jù),或者是環(huán)境球諧的采樣結(jié)果。
- 通過GlossyEnvironmentReflection計(jì)算基于環(huán)境的鏡面反射光照
- 最后通過EnvironmentBRDF函數(shù)獲取混合結(jié)果(漫反射顏色 * 漫反射系數(shù) + 鏡面反射顏色 * 鏡面反射系數(shù))。
half3 EnvironmentBRDF(BRDFData brdfData, half3 indirectDiffuse, half3 indirectSpecular, half fresnelTerm)
{
half3 c = indirectDiffuse * brdfData.diffuse;
c += indirectSpecular * EnvironmentBRDFSpecular(brdfData, fresnelTerm);
return c;
}
3. 反射探針(Reflection Probes)
在場(chǎng)景中未使用反射探針時(shí),場(chǎng)景中具有反射(包括鏡面反射Specular和金屬反射Metallic)的物體會(huì)使用天空貼圖(包括天空面 Sky Plane / 天空盒 Sky Box / 天空球 Sky Dome)的信息來制作反射效果。
默認(rèn)的 environment cube map 只包含天空盒。為了反射場(chǎng)景中的其他東西,我們必須通過GameObject / Light / reflection probe為其添加反射探針。這些探測(cè)器在它們的位置處看向場(chǎng)景,將場(chǎng)景渲染為立方體貼圖。因此,只有在靠近探測(cè)器的表面上,反射才會(huì)顯得或多或少正確。因此,通常需要在一個(gè)場(chǎng)景中放置多個(gè)探頭。它們具有Importance和Box Size屬性,可用于控制每個(gè)探針影響的區(qū)域。
探測(cè)器的Type默認(rèn)設(shè)置為Baked,這意味著它只渲染一次,CubeMap在構(gòu)建時(shí)渲染。你也可以將其設(shè)置為實(shí)時(shí),這將使地圖與動(dòng)態(tài)場(chǎng)景保持同步。它像任何其他相機(jī)一樣被渲染,使用我們的RP,對(duì)立方體地圖的六個(gè)面分別渲染一次。所以實(shí)時(shí)反射探測(cè)器很昂貴。
每個(gè)對(duì)象只使用一個(gè)環(huán)境探針,但場(chǎng)景中可以有多個(gè)探針。因此,你可能不得不 split 對(duì)象以獲得 acceptable(理想的) 的反射。例如,理想情況下,用于構(gòu)建結(jié)構(gòu)的立方體應(yīng)該分成單獨(dú)的內(nèi)部和外部部分,這樣每個(gè)部分都可以使用不同的反射探頭。此外,這意味著GPU batching 會(huì)被反射探針破壞。不幸的是,網(wǎng)格球根本不能使用反射探針,所以渲染出來的總是天空盒。
MeshRenderer組件有一個(gè)Anchor Override(直接將帶有Probe的物體拖上去就好),可以用來微調(diào)它們使用的探針,而不必?fù)?dān)心盒子的大小和位置。還有一個(gè)Reflection Probes,默認(rèn)設(shè)置為Blend Probes。我們的想法是,Unity允許在最好的兩個(gè)反射探針之間進(jìn)行混合。然而,這種模式與SRP批處理程序不兼容,所以Unity的其他rp不支持它,我們也不支持。如果你很好奇,我在2018年SRP教程的反射教程中解釋了如何混合探針,但我希望這個(gè)功能在遺留管道被刪除后消失。
我們將在將來研究其他反射技術(shù)。所以僅有的兩個(gè)功能模式是Off,它總是使用天空盒子,和Simple,它選擇最重要的探測(cè)器。其他的功能和Simple完全一樣。
除此之外,反射探針還可以選擇啟用box projection mode。這將改變?nèi)绾未_定反射以更好地匹配其有限的影響區(qū)域,但SRP批處理程序也不支持這一點(diǎn),因此我們也不支持它。
注:物體在選擇反射探針時(shí),確定物體是否在探針包圍盒內(nèi),如果在,則加入列表;再根據(jù)所有影響物體的反射探針的權(quán)重,只保留權(quán)重最大的一批(若有2個(gè)權(quán)重為5,3個(gè)權(quán)重為3,則只保留權(quán)重為5的探針),再根據(jù)交叉體積權(quán)重計(jì)算保留的反射探針的系數(shù)。
特別的,當(dāng)大包圍盒反射探針完全覆蓋小包圍盒反射探針,且物體處于小包圍盒反射探針內(nèi),則默認(rèn)最小包圍盒探針為最重要探針。
解碼探針
最后,我們必須確保正確地解釋來自CubeMap的數(shù)據(jù)。它可以是HDR或LDR,其強(qiáng)度也可以調(diào)節(jié)。這些設(shè)置是通過unity_SpecCube0_HDR矢量提供的,它在UnityPerDraw緩沖區(qū)中的unity_ProbesOcclusion之后。
// Reflection Probe 0 block feature
// HDR environment map decode instructions
real4 unity_SpecCube0_HDR;
real4 unity_SpecCube1_HDR;
解碼函數(shù):
float3 SampleEnvironment (Surface surfaceWS, BRDF brdf) {
…
return DecodeHDREnvironment(environment, unity_SpecCube0_HDR);
}
4. Box Projection 盒體投影
引自:技術(shù)美術(shù)雜談 反射探針(Reflection Probe)
在未開啟盒體投影時(shí),反射貼圖的圖像通常是通過從無限遠(yuǎn)處投射的。
開啟盒體投影允許我們使用探針包圍盒尺寸Probe Size 、探針包圍盒偏移 Probe Offset 以及鏡頭與反射物體的距離作為參數(shù),控制反射探針?biāo)傻姆瓷滟N圖的尺寸和效果。文章來源:http://www.zghlxwxcb.cn/news/detail-830862.html
通常情況下,Unity默認(rèn)開啟反射探針的盒體投影支持。如果想自定義不同畫面質(zhì)量是否支持盒體投影效果,可以在編輯面板 Edit →項(xiàng)目設(shè)置 Project Settings →圖像設(shè)置 Graphics →畫面分級(jí)設(shè)置 Tier Settings 中取消勾選使用默認(rèn)設(shè)置 Use Defaults ,并進(jìn)行自定義設(shè)置。文章來源地址http://www.zghlxwxcb.cn/news/detail-830862.html
到了這里,關(guān)于Unity SRP 管線【第七講:URP LOD實(shí)現(xiàn)以及Reflections反射探針】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!