UnityGI5:实时 GI 与光探代理体

前置:UnityGI2:Lightmaps

一、实时 GI

字面意思,实时计算间接光照,设置与代码修改如下:

1. LightSetting 里面开启 Realtime Lighting,并将对应的主光源 Mode 设置为 Realtime

2. 修改 Shader 代码,和之前 Lightmap 采样一样,不过这次采样 dynLightmap,也就是动态光照贴图:MetaPass 的代码可以参考《UnityGI2:Lightmaps》这一章的第三节

struct appdata
{
    float4 vertex: POSITION;
    float3 normal: NORMAL;                  //法线
    float4 tangent: TANGENT;                //切线
    float2 uv: TEXCOORD0;                   //uv坐标
    #if defined(LIGHTMAP_ON)
        float2 lightmapUV: TEXCOORD1;           //光照贴图uv坐标
    #endif
    #if defined(DYNAMICLIGHTMAP_ON)
        float2 dynLightmapUV: TEXCOORD2;        //动态光照贴图uv坐标
    #endif
};

//……
v2f vert(appdata v)
{
    //……
    #if defined(LIGHTMAP_ON)
        o.lightmapUV = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
    #endif
    #if defined(DYNAMICLIGHTMAP_ON)
        o.dynLightmapUV = v.dynLightmapUV * unity_DynamicLightmapST.xy + 
    unity_DynamicLightmapST.zw;
    #endif
}

//……
fixed4 frag(v2f i): SV_Target
{
    //……
    float3 indirectDiffuse = 0;
    #if defined(LIGHTMAP_ON)
        float3 defIndirectDiffuse = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.lightmapUV));
        #if defined(DIRLIGHTMAP_COMBINED)
            float4 lightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER(unity_LightmapInd, unity_Lightmap, i.lightmapUV);
            defIndirectDiffuse = DecodeDirectionalLightmap(defIndirectDiffuse, lightmapDirection, normal);
        #endif
        indirectDiffuse += defIndirectDiffuse;
    #endif
    #if defined(DYNAMICLIGHTMAP_ON)
        float3 dynIndirectDiffuse = DecodeRealtimeLightmap(UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, i.dynLightmapUV));
        #if defined(DIRLIGHTMAP_COMBINED)
            float4 dynLightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, i.dynLightmapUV);
            dynIndirectDiffuse = DecodeDirectionalLightmap(dynIndirectDiffuse, dynLightmapDirection, normal);
        #endif
        indirectDiffuse += dynIndirectDiffuse;
    #endif
    #if !defined(LIGHTMAP_ON) && !defined(DYNAMICLIGHTMAP_ON)
        indirectDiffuse += max(0, ShadeSH9(float4(normal, 1)));
    #endif
}

 此时调整主光源的大小、亮度和方向,可以看到效果(包括间接光)也会实时变化:

可以通过调整光源的 indirect lighting 属性调整间接光的亮度:

支持多光源,但是不支持烘焙点光源和聚光灯的间接光阴影

二、光探针代理体

动态物体的间接光是通过光照探针来获取的,运行时会判断物体的中心在哪4个光照探针连成的区域内,并从这些探针获取光照数据,如果一个动态物体过大,就不能只拿动态物体的中心点作为参照了,否则物体上将不会有间接光过渡的效果

使用光探针代理体

1. 检查 Project Setting → Graphics 中是否支持使用光探针代理体,除此之外,这对硬件也有一定的要求,如果硬件和设置都支持,在 Shader 中 UNITY_LIGHT_PROBE_PROXY_VOLUME 宏就会被启用

2. 给对应的过大的动态物体对象添加 LightProbeProxyVolume 组件,组件参数可以参考 U3D 官网,这里就不再多介绍了,同时别忘了还要设置物体 MeshRender 组件上的 Light Probes 属性

3. 修改 Shader 代码如下:单个对象是否使用 LPPV 由 unity_ProbeVolumeParams 的 x 向量指示,该组件在 UnityShaderVariables 中定义,除此之外,核心代码在内置方法 ShadeSHPixel 中,具体可以参考 UnityStandardUtils.cginc 文件

#if !defined(LIGHTMAP_ON) && !defined(DYNAMICLIGHTMAP_ON)
    #if UNITY_LIGHT_PROBE_PROXY_VOLUME
        if (unity_ProbeVolumeParams.x == 1)
        {
            float3 LPPVDiffuse = max(0, ShadeSHPerPixel(float4(normal, 1), 0, i.posWorld));
            indirectDiffuse += LPPVDiffuse;
        }
        else
            indirectDiffuse += max(0, ShadeSH9(float4(normal, 1)));
    #else
        indirectDiffuse += max(0, ShadeSH9(float4(normal, 1)));
    #endif
#endif

搞定:

参考文章:

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/118761205
今日推荐