文章目录
- 前言
- 一、上一篇文章中所需要的 lightmapUV 只有在烘焙时才会使用
- 1、查看帮助文档后,Unity中判断烘培是否开启,使用的是LIGHTMAP_ON
- 2、我们在 appdata 和 v2f 中,定义第二套UV
前言
Unity中Shader的烘培分支的判断,基于上一篇文章,继续实现 GI Shader
- Unity中Shader的GI相关数据的准备
一、上一篇文章中所需要的 lightmapUV 只有在烘焙时才会使用
即只有在 BackGI 和 RealtimeGI 下才会使用到 lightmapUV ,所以我们需要用分支来区别
1、查看帮助文档后,Unity中判断烘培是否开启,使用的是LIGHTMAP_ON
- DYNAMICLIGHTMAP_ON :RealtimeGI是否开启
- 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
}
}
}