Files
JJBB/Assets/Project/Shader/UnityGiBase.cginc
2024-08-23 15:49:34 +08:00

204 lines
6.2 KiB
HLSL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 统一处理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