Files
JJBB/Assets/Project/Shader/UnityGiBase.cginc

204 lines
6.2 KiB
HLSL
Raw Normal View History

2024-08-23 15:49:34 +08:00
// 统一处理UnityGI的算法
#ifndef UNITY_GI_BASE_INCLUDE
#define UNITY_GI_BASE_INCLUDE
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "SimLightSpecular.cginc"
// Forward Base 通用的参数结构
struct v2f_Base {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 tSpace0 : TEXCOORD1;
float4 tSpace1 : TEXCOORD2;
float4 tSpace2 : TEXCOORD3;
UNITY_FOG_COORDS(4)
SHADOW_COORDS(5)
#ifndef LIGHTMAP_OFF
float4 lmap : TEXCOORD6;
#endif
#if UNITY_SHOULD_SAMPLE_SH
half3 sh : TEXCOORD7; // SH
#endif
};
// Forward Add 使用的参数结构
struct v2f_Add {
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 lightDir : TEXCOORD1;
float3 worldPos : TEXCOORD2;
UNITY_FOG_COORDS(3)
SHADOW_COORDS(4)
};
GLOBAL_LIGHT_INFORMATION
#if PLAYER_HALO_ON
uniform float _PlayerLightStrength;
uniform float4 _PlayerLightPos;
fixed LightColorFromWorld(float3 pos)
{
float lengthSqr = 0;
float toLightX = pos.x - _PlayerLightPos.x;
float toLightY = pos.y - _PlayerLightPos.y;
float toLightZ = pos.z - _PlayerLightPos.z;
lengthSqr += toLightX * toLightX;
lengthSqr += toLightY * toLightY;
lengthSqr += toLightZ * toLightZ;
return _PlayerLightStrength * 2.0 / (1.0 + lengthSqr);
}
#endif
// 通用ForwardBase的Vertex代码
v2f_Base vert_Base(appdata_full v)
{
v2f_Base o;
UNITY_INITIALIZE_OUTPUT(v2f_Base, o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
TRANSFER_SHADOW(o)
UNITY_TRANSFER_FOG(o,o.pos);
#ifndef LIGHTMAP_OFF
o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#ifndef DYNAMICLIGHTMAP_OFF
o.lmap.zw = v.texcoord2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
#endif
#endif
#if UNITY_SHOULD_SAMPLE_SH
o.sh = 0;
// Approximated illumination from non-important point lights
#ifdef VERTEXLIGHT_ON
o.sh += Shade4PointLights (
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, worldPos, worldNormal);
#endif
o.sh = ShadeSHPerVertex (worldNormal, o.sh);
#endif
return o;
}
// 通用ForwardAdd的Vertex代码
v2f_Add vert_Add (appdata_full v) {
v2f_Add o;
UNITY_INITIALIZE_OUTPUT(v2f_Add, o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
// 使用真实光源参数光照贴图将不会走ForwardAdd
#ifdef USING_DIRECTIONAL_LIGHT
fixed3 lightDir = _WorldSpaceLightPos0.xyz;
#else
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(o.worldPos));
#endif
TANGENT_SPACE_ROTATION;
o.lightDir = normalize(MUL_3x3_WITH_VECTOR(rotation, MUL_3x3_WITH_VECTOR(unity_WorldToObject, lightDir)));
TRANSFER_SHADOW(o)
UNITY_TRANSFER_FOG(o, o.pos);
return o;
}
float3 GetWorldPos(v2f_Base i)
{
return float3(i.tSpace0.w, i.tSpace1.w, i.tSpace2.w);
}
float3 GetLightDir(float3 worldPos)
{
#ifndef LIGHTMAP_OFF
fixed3 lightDir = _DirectionalLight.xyz;
#else
#ifndef USING_DIRECTIONAL_LIGHT
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
#else
fixed3 lightDir = _WorldSpaceLightPos0.xyz;
#endif
#endif
return lightDir;
}
// 不使用SurfaceOutput的LambertLight直接使用ndotl执行计算
inline fixed3 LambertLight (half3 albedo, half ndotl, UnityLight light)
{
fixed3 c = albedo * light.color * ndotl;
return c;
}
fixed3 GetUnityGiColorFull(half3 color, v2f_Base i, half3 worldNormal, half3 worldPos, half3 lightDir, float ndotl, float atten)
{
// 构造常规函数UnityGI
UnityGI gi;
UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
gi.indirect.diffuse = 0;
gi.indirect.specular = 0;
#if !defined(LIGHTMAP_ON)
gi.light.color = _LightColor0.rgb;
gi.light.dir = lightDir;
gi.light.ndotl = ndotl;
#endif
// 构造常规函数UnityGIInput
UnityGIInput giInput;
UNITY_INITIALIZE_OUTPUT(UnityGIInput, giInput);
giInput.light = gi.light;
giInput.worldPos = worldPos;
giInput.atten = atten;
#ifndef LIGHTMAP_OFF
giInput.lightmapUV = i.lmap;
#else
giInput.lightmapUV = 0.0;
#endif
#if UNITY_SHOULD_SAMPLE_SH
giInput.ambient = i.sh;
#else
giInput.ambient.rgb = 0.0;
#endif
giInput.probeHDR[0] = unity_SpecCube0_HDR;
giInput.probeHDR[1] = unity_SpecCube1_HDR;
#if UNITY_SPECCUBE_BLENDING || UNITY_SPECCUBE_BOX_PROJECTION
giInput.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
#endif
#if UNITY_SPECCUBE_BOX_PROJECTION
giInput.boxMax[0] = unity_SpecCube0_BoxMax;
giInput.probePosition[0] = unity_SpecCube0_ProbePosition;
giInput.boxMax[1] = unity_SpecCube1_BoxMax;
giInput.boxMin[1] = unity_SpecCube1_BoxMin;
giInput.probePosition[1] = unity_SpecCube1_ProbePosition;
#endif
// 计算最终UnityGI
gi = UnityGlobalIllumination(giInput, 1.0, worldNormal);
// 相当于LightingBlinnPhong(o, worldViewDir, gi);
fixed3 albedo = color;
color = LambertLight(albedo, ndotl, gi.light);
// 不会使用分离贴图处理
#if defined(DIRLIGHTMAP_SEPARATE)
#ifdef LIGHTMAP_ON
color += LambertLight (albedo, ndotl, gi.light2);
#endif
#ifdef DYNAMICLIGHTMAP_ON
color += LambertLight (albedo, ndotl, gi.light3);
#endif
#endif
#ifdef UNITY_LIGHT_FUNCTION_APPLY_INDIRECT
color += albedo * gi.indirect.diffuse;
#endif
return color;
}
#define GET_UNITY_GI_COLOR \
half3 worldPos = GetWorldPos(i); \
half3 lightDir = GetLightDir(worldPos); \
fixed ndotl = LambertTerm(worldNormal, lightDir); \
half atten = SHADOW_ATTENUATION(i); \
fixed3 giColor = GetUnityGiColorFull(c.rgb, i, worldNormal, worldPos, lightDir, ndotl, atten)
#endif