精選文章

SmallBurger Asset Home

  SmallBurger

2018年11月9日 星期五

SSAO使用於打光AO map的做法

一般的SSAO最讓人詬病的部份,就是會把模型弄髒,感覺就像是鋼彈模型舊化失敗的作品,就算是把Density調低或探測球調小,仍然是不改直接覆改打光結果的根本問題。

其實在Unity的PBR渲染,是把AO這一層當間接光照處理,也就是他並不會影響直接光照,在LightWeight SRP的做法如下:
half3 GlobalIllumination(in BRDFData theBRDFData, in LightInputData lightInputData, in SurfaceData surfaceData, in half occlusion)
{
    half3 reflectVector = reflect(-lightInputData.worldViewDirection, lightInputData.worldNormal);
    //有機會優化,也許直接參考一張貼圖
    half fresnelTerm = Pow4(1.0 - saturate(dot(lightInputData.worldNormal, lightInputData.worldViewDirection)));
    //half3 indirectDiffuse = half3(0.0, 0.0, 0.0);
    half3 indirectDiffuse = half3(0.0, 0.0, 0.0);
#ifdef _PROCESS_VERTEX_SH
    //indirectDiffuse = lightInputData.bakedGI * occlusion;
    indirectDiffuse = lightInputData.bakedGI;
#endif
    indirectDiffuse *= Gamma22ToLinear(occlusion);

    half3 indirectSpecular = GlossyEnvironmentReflection(reflectVector, theBRDFData.perceptualRoughness, occlusion);
    return EnvironmentBRDF(theBRDFData, indirectDiffuse, indirectSpecular, fresnelTerm);
}

half3 GlossyEnvironmentReflection(half3 reflectVector, half perceptualRoughness, half occlusion)
{
#if !defined(_GLOSSYREFLECTIONS_OFF)
    half mip = PerceptualRoughnessToMipmapLevel(perceptualRoughness);
    half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectVector, mip);

#if !defined(UNITY_USE_NATIVE_HDR)
    half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR);
#else
    half3 irradiance = encodedIrradiance.rbg;
#endif

    return irradiance * occlusion;
#endif // GLOSSY_REFLECTIONS

    return _GlossyEnvironmentColor.rgb * occlusion;
}
所以這邊的做法是將SSAO計算出來,並把其放在打光的計算上,而且這樣一來,也不會影響到Emission的部份。

未上SSAO的結果:


SSAO後置特效的狀況,很明顯示會弄髒Model:


SSAO使用AO map打光計算後的結果(為了讓差別更清楚,暫時讓GlossyEnvironmentReflection不受AO的影響,而且可以加入打光計算後,可以更有彈性調整)


關於優化的部份,為了讓打光時不用再讀一張SSAO map,將其資料壓在ScreenSpaceShadowMap的G通道裡,圖中紅色那張貼圖,有點偏黃色的資料就是SSAO。

相關比較視頻如下:




Dream continues in...

沒有留言:

張貼留言