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
        }
    }
}
相关推荐
星火撩猿44 分钟前
常见游戏引擎介绍与对比
unity·ue5·游戏引擎·godot
sky_smile_Allen2 小时前
[Unity]-[UI]-[Prefab] 关于Unity UGUI 的布局及组件讲解
ui·unity·游戏引擎
虾球xz4 小时前
游戏引擎学习第244天: 完成异步纹理下载
c++·学习·游戏引擎
太妃糖耶7 小时前
URP-利用矩阵在Shader中实现物体的平移和缩放
unity·矩阵
Magnum Lehar10 小时前
ApophisZerg游戏引擎项目目录展示
人工智能·vscode·编辑器·游戏引擎
Tandy12356_13 小时前
Godot开发2D冒险游戏——第一节:主角登场!
python·游戏引擎·godot
是阿根20 小时前
unity使用iTextSharp生成PDF文件
unity·c#·游戏引擎
常城1 天前
Unity中通过TMP使用图片字体
unity·游戏引擎
惊鸿醉1 天前
⭐Unity 开发 | 如何通过 NTP 网络时间实现精准的跨平台时间同步【附完整源码 + UI 模块 + 偏差分析】
网络·unity·游戏引擎
虾球xz1 天前
游戏引擎学习第243天:异步纹理下载
c++·学习·游戏引擎