Unity中Shader的烘培分支的判断

文章目录


前言

Unity中Shader的烘培分支的判断,基于上一篇文章,继续实现 GI Shader


一、上一篇文章中所需要的 lightmapUV 只有在烘焙时才会使用

即只有在 BackGI 和 RealtimeGI 下才会使用到 lightmapUV ,所以我们需要用分支来区别

1、查看帮助文档后,Unity中判断烘培是否开启,使用的是LIGHTMAP_ON

  1. DYNAMICLIGHTMAP_ON :RealtimeGI是否开启
  2. LIGHTMAP_ON:当对象标记为LightMap Static并且场景烘焙后开启

所以,我们在Pass中,修改 LightMode 为 ForwardBase

定义 multi_compile_fwdbase 变体

Tags{"LightMode"="ForwardBase"}

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

#pragma multi_compile_fwdbase

2、我们在 appdata 和 v2f 中,定义第二套UV

复制代码
1.在appdata中,第二套UV对应的语义是 TEXCOORD1,这是不能乱改的

struct appdata

{

float4 vertex : POSITION;

//定义第二套 UV ,appdata 对应的固定语义为 TEXCOORD1

#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)

float4 lightmapUV : TEXCOORD1;

#endif

};

复制代码
2.在 v2f 中,也定义第二套UV,不过这里没有语义限制

struct v2f

{

float4 vertex : SV_POSITION;

float4 worldPos : TEXCOORD0;

#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)

float4 lightmapUV : TEXCOORD1;

#endif

};

复制代码
3.在顶点着色器中对其采样

float4 lightmapUV; // .xy = static lightmap UV, .zw = dynamic lightmap UV

lightmapUV的XY代表的是:BackGI

lightmapUV的ZW代表的是:RealTimeGI
//对第二套UV进行纹理采样,这个unity_LightmapST,类似于之前我们定义纹理的Tilling 和 Offset

#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)

o.lightmapUV.xy = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;

#endif

复制代码
4.在片元着色器,对其赋值

#if defined(DYNAMICLIGHTMAP_ON) || defined(LIGHTMAP_ON)

giInput.lightmapUV = i.lightmapUV;

#endif

以下是准备好所有数据后的代码:

复制代码
//在这里里面使用 自定义的 cginc 来实现全局GI
//GI数据的准备
//烘培分支的判断
Shader "MyShader/P1_8_4"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            Tags{"LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile DYNAMICLIGHTMAP_ON
            #pragma multi_compile LIGHTMAP_ON
            

            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #include "CGIncludes/MyGlobalIllumination.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                //定义第二套 UV ,appdata 对应的固定语义为 TEXCOORD1
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                float4 lightmapUV : TEXCOORD1;
                #endif
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float4 worldPos : TEXCOORD0;
                //定义第二套UV
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                float4 lightmapUV : TEXCOORD1;
                #endif
            };
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex);

                //对第二套UV进行纹理采样
                #if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
                    o.lightmapUV.xy = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw;
                #endif
                
                
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //1、准备 SurfaceOutput 的数据
                SurfaceOutput o;
                //目前先初始化为0,使用Unity自带的方法,把结构体中的内容初始化为0
                UNITY_INITIALIZE_OUTPUT(SurfaceOutput,o)

                //2、准备 UnityGIInput 的数据
                UnityGIInput giInput;
                //初始化
                UNITY_INITIALIZE_OUTPUT(UnityGIInput,giInput);
                //修改用到的数据
                giInput.light.color = _LightColor0;
                giInput.light.dir = _WorldSpaceLightPos0;
                giInput.worldPos = i.worldPos;
                giInput.worldViewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
                giInput.atten = 1;
                giInput.ambient = 0;
                
                #if defined(DYNAMICLIGHTMAP_ON) || defined(LIGHTMAP_ON)
                giInput.lightmapUV = i.lightmapUV;
                #endif
                
                //3、准备 UnityGI 的数据
                UnityGI gi;
                //直接光照数据(主平行光)
                gi.light.color = _LightColor0;
                gi.light.dir = _WorldSpaceLightPos0;
                //间接光照数据(目前先给0)
                gi.indirect.diffuse = 0;
                gi.indirect.specular = 0;
                
                LightingLambert_GI1(o,giInput,gi);
                return 1;
            }
            ENDCG
        }
    }
}
相关推荐
ellis19703 小时前
Unity插件SafeArea Helper适配异形屏详解
unity
nnsix4 小时前
Unity Physics.Raycast的 QueryTriggerInteraction枚举作用
unity·游戏引擎
地狱为王5 小时前
Cesium for Unity叠加行政区划线
unity·gis·cesium
小贺儿开发13 小时前
Unity3D 八大菜系连连看
游戏·unity·互动·传统文化
在路上看风景14 小时前
25. 屏幕像素和纹理像素不匹配
unity
ۓ明哲ڪ15 小时前
Unity功能——创建新脚本时自动添加自定义头注释
unity·游戏引擎
熬夜敲代码的小N15 小时前
Unity大场景卡顿“急救包”:从诊断到落地的全栈优化方案
java·unity·游戏引擎
派葛穆17 小时前
Unity-realvirtual-S7通讯快速配置(未完结)
unity·游戏引擎
w-白兰地1 天前
【Addressable远端加载资源】
unity·addressable·资源加载
小张不爱写代码1 天前
[Unity 技巧] 如何自定义 Inspector 变量显示名称 (CustomLabel)
unity·游戏引擎