204 lines
6.2 KiB
HLSL
204 lines
6.2 KiB
HLSL
|
// 统一处理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
|