文章目录
- 前言
- 一、GI中 间接光照的实现
- 1、看Unity的源码可知,在计算GI的间接光照时,最主要的实现是在UnityGI_Base函数中
- 二、分析 UnityGI_Base 中实现的功能
- 1、ResetUnityGI的作用
- 2、第一个#if中实现的功能:计算在Distance Shadowmask 中实时阴影与烘培阴影的混合过程
- 3、第二个#if中实现的功能:计算使用球谐光照(当使用光照探针后的效果)
- 4、第三个#if中实现的功能:计算静态 GI (当使用BackedGI后的效果)
- 5、第四个#if中实现的功能:计算动态 GI (当使用RealtimeGI后的效果)
前言
Unity中Shader的GI的间接光实现。在上一篇文章中,我们实现了GI中的直接光。但是,Global Illumination 是由 直接光 加 间接光 后的结果,所以我们还需要准备 GI 中的间接光。
- Unity中Shader的GI的直接光实现
一、GI中 间接光照的实现
1、看Unity的源码可知,在计算GI的间接光照时,最主要的实现是在UnityGI_Base函数中
UnityGI_Base如下:
inline UnityGI UnityGI_Base1(UnityGIInput data, half occlusion, half3 normalWorld)
{UnityGI o_gi;ResetUnityGI1(o_gi);// Base pass with Lightmap support is responsible for handling ShadowMask / blending here for performance reason#if defined(HANDLE_SHADOWS_BLENDING_IN_GI)half bakedAtten = UnitySampleBakedOcclusion(data.lightmapUV.xy, data.worldPos);float zDist = dot(_WorldSpaceCameraPos - data.worldPos, UNITY_MATRIX_V[2].xyz);float fadeDist = UnityComputeShadowFadeDistance(data.worldPos, zDist);data.atten = UnityMixRealtimeAndBakedShadows(data.atten, bakedAtten, UnityComputeShadowFade(fadeDist));#endifo_gi.light = data.light;o_gi.light.color *= data.atten;#if UNITY_SHOULD_SAMPLE_SHo_gi.indirect.diffuse = ShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);#endif#if defined(LIGHTMAP_ON)// Baked lightmapshalf4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);half3 bakedColor = DecodeLightmap(bakedColorTex);#ifdef DIRLIGHTMAP_COMBINEDfixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER (unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);o_gi.indirect.diffuse += DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);#if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)ResetUnityLight(o_gi.light);o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap (o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);#endif#else // not directional lightmapo_gi.indirect.diffuse += bakedColor;#if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)ResetUnityLight(o_gi.light);o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);#endif#endif#endif#ifdef DYNAMICLIGHTMAP_ON// Dynamic lightmapsfixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, data.lightmapUV.zw);half3 realtimeColor = DecodeRealtimeLightmap (realtimeColorTex);#ifdef DIRLIGHTMAP_COMBINEDhalf4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);o_gi.indirect.diffuse += DecodeDirectionalLightmap (realtimeColor, realtimeDirTex, normalWorld);#elseo_gi.indirect.diffuse += realtimeColor;#endif#endifo_gi.indirect.diffuse *= occlusion;return o_gi;
}
所以我们在片元着色器中可以直接给 gi 赋值,不使用 LightingLambert_GI1函数
gi = UnityGI_Base1(giInput,1,o.Normal);
可以看出,效果是一样的:
二、分析 UnityGI_Base 中实现的功能
1、ResetUnityGI的作用
由图可见:这个 ResetUnityGI1 函数的作用是和之前初始化的函数 UNITY_INITIALIZE_OUTPUT 功能一样的。
然后,除掉 #if 的部分,主要实现了以下功能。
2、第一个#if中实现的功能:计算在Distance Shadowmask 中实时阴影与烘培阴影的混合过程
3、第二个#if中实现的功能:计算使用球谐光照(当使用光照探针后的效果)
4、第三个#if中实现的功能:计算静态 GI (当使用BackedGI后的效果)
光照图的采样(核心部分)
之后这个功能是在Unity中开启 定向光 模式时使用
5、第四个#if中实现的功能:计算动态 GI (当使用RealtimeGI后的效果)