全局光照的实现Shader

主要使用 LightingLambert_GI(o,giInput,gi) 采样光照贴图来实现间接光照和阴影的效果

使用 LightingLambert(o,gi) 来实现间接光照和直接光照的混合

一、LightingLambert_GI(o,giInput,gi)

unityGI_Base中实现不同类型的分支来采样光照贴图

例如 #if defined(LIGHTMAP_ON)代表当打开烘焙全局光照采样光照贴图(lightmapUV.xy)来实现光照效果

#ifdef DYNAMICLIGHTMAP_ON代表当打开实时全局光照采样光照贴图(lightmapUV.zw)来实现光照效果

unity中与LightingLambert()函数相关的内置的宏

inline UnityGI UnityGI_Base(UnityGIInput data, half occlusion, half3 normalWorld)
{
    //声明了一个UnityGI类型的变量o_gi,用来存储最终计算的GI信息
    UnityGI o_gi;


    //重置UnityGI
    ResetUnityGI(o_gi);


    //计算在Distance Shadowmask中实时阴影与烘焙阴影的混合过度
#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

    //将主平行灯传入GI中   UnityGIInput giInput;  data=giInput
    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

    //当使用Baked GI时
#if defined(LIGHTMAP_ON)
        // Baked lightmaps
        //用lightmapUV.xy的UV坐标对unity_Lightmap贴图进行采样存储到bakedColorTex这个变量中
        half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
        //DecodeLightmap对采样后的贴图进行解码
        half3 bakedColor = DecodeLightmap(bakedColorTex);

    //当directional(定向光)模式开启时
#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


    //当采用Realtime GI时
#ifdef DYNAMICLIGHTMAP_ON
        // Dynamic lightmaps
        //采样unity_DynamicLightmap贴图
        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;
}

inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld)

{

    return UnityGI_Base(data, occlusion, normalWorld);

}

inline void LightingLambert_GI (SurfaceOutput s,UnityGIInput data,inout UnityGI gi)

{

    gi = UnityGlobalIllumination (data, 1.0, s.Normal);

}

二、LightingLambert_GI(o,giInput,gi)LightingLambert_GI中的参数属性

有 SurfaceOutput o, UnityGIInput giInput , UnityGI gi 

SurfaceOutput o

定义模型的顶点数据
struct SurfaceOutput  {
   fixed3 Albedo;       //漫反射
   fixed3 Normal;      //法线
   fixed3 Emission;   //自发光
   half Specular;       //高光
   fixed Gloss;         //光滑度
   fixed Alpha;         //透明度
    };

UnityGIInput giInput

struct UnityGIInput
{
                直接光照
                UnityLight light;  //pixel light, sent from the engine  
                float3 worldPos;
                half3 worldViewDir;     //世界空间下的视角方向
                half atten;                    //衰减
                half3 ambient;             //环境色
                用来采样纹理贴图的UV坐标
                float4 lightmapUV;      //.xy = static lightmap UV, .zw = dynamic lightmap UV
                ....
                }

UnityGI gi 

直接光照
struct UnityLight      
{
                half3 color;   //光照颜色
                half3 dir;       //光照方向
};
间接光照
struct UnityIndirect
{
                half3 diffuse;        //漫反射颜色
                half3 specular;     //高光色
};
struct UnityGI
{
                UnityLight light;            //直接光照
                UnityIndirect indirect;   //间接光照
};

三、fixed4 c=LightingLambert(o,gi);(直接光照与间接光照的混合)

LightingLambert(o,gi)函数需要使用到的内置宏

#if defined(UNITY_SHOULD_SAMPLE_SH) || defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
#define UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
#endif

//实现lambert光照模型

inline fixed4 UnityLambertLight(SurfaceOutput s,UnityLight light)
{
    fixed diff = max(0, dot(s.Normal, light.dir));

    fixed4 c;
    c.rgb = s.Albedo * light.color * diff;
    c.a = s.Alpha;
    return c;
}

inline fixed4 LightingLambert(SurfaceOutput s, UnityGI gi)
{
    fixed4 c;
    c = UnityLambertLight(s, gi.light);
    //是否要应用间接光 将间接光照与直接光照进行混合
#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
        c.rgb += s.Albedo * gi.indirect.diffuse;
#endif

    return c;
}

四、在片元着色器中对函数的参数进行初始化操作

初始化函数(初始化为0)

UNITY_INITIALIZE_OUTPUT();

 fixed4 frag (v2f i) : SV_Target
 {
     //顶点的表面数据
     SurfaceOutput o;
     UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o) // 使SurfaceOutPut中的参数初始化为0
     o.Normal=i.worldNormal;    //定义NORMAL的值
     o.Albedo=1;   //定义Albedo漫反射

     UnityGI gi;

     // 初始化GI
     UNITY_INITIALIZE_OUTPUT(UnityGI,gi)

     // 定义主直接光照(平行灯)的灯光颜色
     gi.light.color=_LightColor0;

     // 定义主直接光照(平行灯)的位置方向
     gi.light.dir=_WorldSpaceLightPos0;  

     // 定义间接光照的漫反射
     gi.indirect.diffuse=1;

     // 定义间接光照的高光
     gi.indirect.specular=0;

     //实时的阴影贴图纹理采样
     UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);

     UnityGIInput giInput;

     // 初始化操作
     UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput);
     giInput.light=gi.light;      // 主平行灯  直接光照

     giInput.worldPos=i.worldPos;

     giInput.worldViewDir=normalize(_WorldSpaceCameraPos-i.worldPos);

     //将实时的阴影赋予giInput.atten,将实时阴影与采样阴影进行混合
     giInput.atten=atten;

     giInput.ambient=0;

     // 在实时全局光照或烘焙全局光照开启的情况下才会用到lightmapUV,所以要进行分支判断
     #if defined(LIGHTMAP_ON)||defined(DYNAMICLIGHTMAP_ON)
     giInput.lightmapUV=i.lightmapUV;
     #endif

     //GI 间接光照的计算
     LightingLambert_GI1(o,giInput,gi);


     //UnityGI UnityGI_Base1(UnityGIInput data, half occlusion, half3 normalWorld)
     // gi=UnityGI_Base1(giInput,1,o.Normal);          与LightingLambert_GI1(o,giInput,gi)功能相同

     //GI直接光照的计算
     fixed4 c=LightingLambert1(o,gi);

     return c;
 }

五、关于lightmapUV的使用

只有在开启了烘焙全局光照(Baked GI)和实时全局光照(Realtime GI)的情况下才会使用lightmapUV来采样光照贴图

所以在Shader中对lightmapUV声明时需进行分支判断

在顶点着色器的输入输出结构体中都添加下面语句(当开启烘焙GI和实时GI时声明lightmapUV)

#if defined(LIGHTMAP_ON)||defined(DYNAMICLIGHTMAP_ON)
      float4 lightmapUV:TEXCOORD1;
#endif

所以需要在结构体前添加宏开关#pragma multi_compile_fwdbase

需要注意的是lightmapUV不能使用第一套UV,否则会出现错误

在顶点着色器中使用相关的语句使lightmapUV的平铺和偏移有效

//Baked GI(静态)//使UV的平铺和偏移有效
#if defined(
LIGHTMAP_ON)
    o.lightmapUV.xy=v.lightmapUV*unity_LightmapST.xy+unity_LightmapST.zw;
#endif

//LightMapUV中的zw代表的是动态的GI(Realtime GI)
#if defined(
DYNAMICLIGHTMAP_ON)         o.lightmapUV.zw=v.lightmapUV*unity_DynamicLightmapST.xy+unity_DynamicLightmapST.zw;
#endif

o.lightmapUV.xy 代表Baked GI的光照贴图

 o.lightmapUV.zw代表Realtime GI的光照贴图

在片段着色器中将lightmapUV传给UnityGIInput中的lightmapUV

#if defined(LIGHTMAP_ON)||defined(DYNAMICLIGHTMAP_ON)
    giInput.lightmapUV=i.lightmapUV;
#endif

六、添加实时的阴影效果

此时的Shader中并没有添加实时的阴影效果,(赋予该Shader的模型只有烘焙阴影,并不会产生跟随平行灯光而产生的实时阴影),所以要通过添加ShadowCaster Pass和实时的阴影采样语句来实现实时的阴影效果(利用之前学习的知识,忘记的话可以看前面的文章)

需要添加与阴影接收相关的变体

#pragma multi_compile SHADOWS_SCREEN DIRECTIONAL

1.在顶点着色器的输出结构体中添加

UNITY_LIGHTING_COORDS(2,3)

//定义了两个变量,同时定义灯光衰减和实时阴影采样的变量

2.在顶点着色器中添加

UNITY_TRANSFER_LIGHTING(o,v.lightmapUV.xy);

3.在片元着色器中添加

UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);

//实时的阴影贴图纹理采样以及灯光衰减的计算

七、自定义的.cginc文件

如何创建自己的cginc文件?

首先创建一个文件夹(Folder),用来存放自定义的cginc文件,然后再创建一个Shader

然后右击Shader,选择在文件夹中打开Shader文件

最后将文件重命名为.cginc后缀的文件即可

如何引用自定义的cginc文件?

自定义的cginc文件代码 

#ifndef MYGLOBAL_CGINCLUDE
#define MYGLOBAL_CGINCLUDE

//将UnityGI的相关方法都添加到自定义的cginc文件中,并将unity中内置的函数名更改一下,以便区分

// 计算Lambert光照模型的式子
//SurfaceOutput表面的输出数据 
#if defined(UNITY_SHOULD_SAMPLE_SH) || defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
#define UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
#endif

//直接光照Lambert的计算结果
inline fixed4 UnityLambertLight1(SurfaceOutput s,UnityLight light)
{
    fixed diff = max(0, dot(s.Normal, light.dir));

    fixed4 c;
    c.rgb = s.Albedo * light.color * diff;
    c.a = s.Alpha;
    return c;
}

inline fixed4 LightingLambert1(SurfaceOutput s, UnityGI gi)
{
    fixed4 c;
    c = UnityLambertLight1(s, gi.light);
    //是否要应用间接光 将间接光照与直接光照进行混合
#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
        c.rgb += s.Albedo * gi.indirect.diffuse;
#endif

    return c;
}

inline void ResetUnityLight1(out UnityLight outLight)
{
    outLight.color = half3(0, 0, 0);
    outLight.dir = half3(0, 1, 0); // Irrelevant direction, just not null
    outLight.ndotl = 0; // Not used
}

inline void ResetUnityGI1(out UnityGI outGI)
{
    ResetUnityLight(outGI.light);
    outGI.indirect.diffuse = 0;
    outGI.indirect.specular = 0;
}

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;
}

/*inline UnityGI UnityGI_Base1(UnityGIInput data, half occlusion, half3 normalWorld)
{
    //声明了一个UnityGI类型的变量o_gi,用来存储最终计算的GI信息
    UnityGI o_gi;
    //重置UnityGI
    ResetUnityGI(o_gi);

    // Base pass with Lightmap support is responsible for handling ShadowMask / blending here for performance reason
    
    //计算在Distance Shadowmask中实时阴影与烘焙阴影的混合过度
#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

    //将主平行灯传入GI中   UnityGIInput giInput;  data=giInput
    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

    //当使用Baked GI时
#if defined(LIGHTMAP_ON)
        // Baked lightmaps
        //用lightmapUV.xy的UV坐标对unity_Lightmap贴图进行采样存储到bakedColorTex这个变量中
        half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
        //DecodeLightmap对采样后的贴图进行解码
        half3 bakedColor = DecodeLightmap(bakedColorTex);

    //当directional(定向光)模式开启时
#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
    
    
    //当采用Realtime GI时
#ifdef DYNAMICLIGHTMAP_ON
        // Dynamic lightmaps
        //采样unity_DynamicLightmap贴图
        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;
}*/

inline UnityGI UnityGlobalIllumination1(UnityGIInput data, half occlusion, half3 normalWorld)
{
    return UnityGI_Base1(data, occlusion, normalWorld);
}

//该函数的目的是传出gi参数
inline void LightingLambert_GI1(SurfaceOutput s,UnityGIInput data,inout UnityGI gi)
{
    gi = UnityGlobalIllumination1(data, 1.0, s.Normal);
}

#endif

八、Shader

Shader "unity/Global"
{
    Properties
    {
    }
    SubShader
    {

        Pass
        {
            Tags{"LightMode"="ForWardBase"}

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile SHADOWS_SCREEN DIRECTIONAL

            #pragma multi_compile_fwdbase

            #include "UnityCG.cginc"

            //在做光照时一般都需要引用下面两个文件
            #include "AutoLight.cginc"
            #include "Lighting.cginc"

            //引用自定义的cginc文件
            #include"../CGincludes/MyGlobal.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                //定义LightMapUV (或判断)
                #if defined(LIGHTMAP_ON)||defined(DYNAMICLIGHTMAP_ON)
                float4 lightmapUV:TEXCOORD1;
                #endif
                half3 normal:NORMAL;
            };

            struct v2f
            {
                float4 pos: SV_POSITION;
                float4 worldPos:TEXCOORD;
                //DYNAMICLIGHTMAP_ON动态GI(Realtime GI)或静态GI(Baked GI)LIGHTMAP_ON
                #if defined(LIGHTMAP_ON)||defined(DYNAMICLIGHTMAP_ON)
                float4 lightmapUV:TEXCOORD1;
                #endif
                half3 worldNormal:NORMAL;

                //定义了两个变量,同时定义灯光衰减和实时阴影采样的变量
                UNITY_LIGHTING_COORDS(2,3)
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.worldPos=mul(unity_ObjectToWorld,v.vertex);
                o.worldNormal=UnityObjectToWorldNormal(v.normal);

                //Baked GI(静态)//使UV的平铺和偏移有效
                #if defined(LIGHTMAP_ON)
                o.lightmapUV.xy=v.lightmapUV*unity_LightmapST.xy+unity_LightmapST.zw;
                #endif

                //LightMapUV中的zw代表的是动态的GI(Realtime GI)
                #if defined(DYNAMICLIGHTMAP_ON)
                o.lightmapUV.zw=v.lightmapUV*unity_DynamicLightmapST.xy+unity_DynamicLightmapST.zw;
                #endif

                UNITY_TRANSFER_LIGHTING(o,v.lightmapUV.xy);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {

                // #if defined(LIGHTMAP_ON)
                // #if defined(DYNAMICLIGHTMAP_ON)
                // return 1;
                // #else
                // return 0;
                // #endif

                //顶点的表面数据
                SurfaceOutput o;

                // 使SurfaceOutPut中的参数初始化为0
                UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)
                //定义NORMAL的值
                o.Normal=i.worldNormal;
                //定义Albedo漫反射
                o.Albedo=1;

                //实时的阴影贴图纹理采样
                UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);

                UnityGI gi;

                // 初始化GI
                UNITY_INITIALIZE_OUTPUT(UnityGI,gi)

                // 定义主直接光照(平行灯)的灯光颜色
                gi.light.color=_LightColor0;

                // 定义主直接光照(平行灯)的位置方向
                gi.light.dir=_WorldSpaceLightPos0;  

                // 定义间接光照的漫反射
                gi.indirect.diffuse=1;

                // 定义间接光照的高光
                gi.indirect.specular=0;



                UnityGIInput giInput;

                // 初始化操作
                UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput);

                // 主平行灯
                giInput.light=gi.light;   //直接光照

                giInput.worldPos=i.worldPos;

                giInput.worldViewDir=normalize(_WorldSpaceCameraPos-i.worldPos);

                //将实时的阴影赋予giInput.atten,将实时阴影与采样阴影进行混合
                giInput.atten=atten;

                giInput.ambient=0;

                // 在特定的情况下才会用到lightmapUV,所以要进行分支判断
                #if defined(LIGHTMAP_ON)||defined(DYNAMICLIGHTMAP_ON)
                giInput.lightmapUV=i.lightmapUV;
                #endif

                // 更改Shader中调用的内置函数名和自定义cginc中的函数名,来以区别
                // LightingLambert_GI改为 LightingLambert_GI1

                //GI 间接光照的计算
                LightingLambert_GI1(o,giInput,gi);
                //UnityGI UnityGI_Base1(UnityGIInput data, half occlusion, half3 normalWorld)
                // gi=UnityGI_Base1(giInput,1,o.Normal);          与LightingLambert_GI1(o,giInput,gi)功能相同



                //返回间接光照的漫反射颜色
                // return fixed4(gi.indirect.diffuse,1);

                //GI直接光照的计算
                fixed4 c=LightingLambert1(o,gi);

                return c;
            }
            ENDCG
        }
    } FallBack "Specular"
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值