Unity中Shader的GI的间接光实现

文章目录


前言

Unity中Shader的GI的间接光实现。在上一篇文章中,我们实现了GI中的直接光。但是,Global Illumination 是由 直接光 加 间接光 后的结果,所以我们还需要准备 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));
    #endif

    o_gi.light = data.light;
    o_gi.light.color *= data.atten;

    #if UNITY_SHOULD_SAMPLE_SH
        o_gi.indirect.diffuse = ShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);
    #endif

    #if defined(LIGHTMAP_ON)
        // Baked lightmaps
        half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
        half3 bakedColor = DecodeLightmap(bakedColorTex);

        #ifdef DIRLIGHTMAP_COMBINED
            fixed4 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 lightmap
            o_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 lightmaps
        fixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, data.lightmapUV.zw);
        half3 realtimeColor = DecodeRealtimeLightmap (realtimeColorTex);

        #ifdef DIRLIGHTMAP_COMBINED
            half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);
            o_gi.indirect.diffuse += DecodeDirectionalLightmap (realtimeColor, realtimeDirTex, normalWorld);
        #else
            o_gi.indirect.diffuse += realtimeColor;
        #endif
    #endif

    o_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后的效果)


相关推荐
qq_213157894 分钟前
其域lcc2丢失部分lod/远处显示空洞的解决方式
unity·lcc2
辻弋20129 分钟前
自动检测硬件生成驱动清单、实时监控FPS、120秒性能记录——30+项优化模块化开关,所有改动可精确复原
服务器·windows·游戏引擎·电脑·开源软件
点心的游戏开发世界3 小时前
GDScript 入门笔记:目录
开发语言·笔记·游戏引擎·godot
XR技术研习社3 小时前
关于 PICO 串流测试中报错 IndexOutOfRangeException: renderPassIndex 的两个排障方法
unity·ar·xr·vr
想做后端的前端3 小时前
Unity · 性能优化:内存管理完全指南:从托管堆到跨桥开销
unity·性能优化·游戏引擎
平行云6 小时前
实时云渲染信创架构解析:从GPU池化到全栈适配的技术演进
linux·unity·docker·ue5·webgl·数字孪生·实时云渲染
玖玥拾8 小时前
Lua 基础语法(五)Unity xLua基础配置与 C# 访问 Lua
开发语言·unity·c#·lua
玖玥拾1 天前
Lua 基础语法(二)
开发语言·unity·lua
点心的游戏开发世界1 天前
GDScript 入门笔记(十六):文件读写与数据持久化
开发语言·笔记·游戏引擎·godot
点心的游戏开发世界1 天前
GDScript 入门笔记(十三):字符串操作
开发语言·笔记·游戏引擎·godot