Files
3d-bianpo/Assets/URPWater/Shaders/HLSL/Includes/URPWaterLighting.hlsl
2026-03-03 11:30:53 +08:00

266 lines
8.6 KiB
HLSL

//-----------------------------------------------------------------------------
// Copyright(C) Yan Verde - All Rights Reserved
// Copyright protected under Unity Asset Store EULA
// Refer to https://unity3d.com/legal/as_terms for more informations
// -----------------------------------------------------------------------------
// URP Water
// Author : Yan Verde
// Date : April 10, 2021
// -----------------------------------------------------------------------------
#ifndef URPWATER_LIGHTING_INCLUDED
#define URPWATER_LIGHTING_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "URPWaterVariables.hlsl"
#include "URPWaterHelpers.hlsl"
// ShadowCoord: TransformWorldToShadowCoord(worldPosition);
// WorldNormal: TransformObjectToWorldNormal(v.normal);
// worldViewDir: SafeNormalize(_WorldSpaceCameraPos.xyz - worldPos)
// worldPos: TransformObjectToWorld(v.vertex.xyz);
// ShadowCoord: TransformWorldToShadowCoord(WorldPos);
// ShadowSample: MainLightRealtimeShadow(shadowCoord);
//From unity file:
//ShaderLibrary\Shadows.hlsl
half SampleShadows(Varyings IN, GlobalData data)
{
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
float4 shadowCoord = IN.shadowCoord;
#elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
float4 shadowCoord = TransformWorldToShadowCoord(data.worldPosition);
#else
float4 shadowCoord = float4(0, 0, 0, 0);
#endif
shadowCoord.xz += data.worldNormal.xz * 0.01;
return MainLightRealtimeShadow(shadowCoord);
}
void ComputeCaustics(out float3 causticColor, inout GlobalData data, Varyings IN, float3 Ambient)
{
#if UNITY_REVERSED_Z
real depth = data.rawDepthDst;
#else
// Adjust Z to match NDC for OpenGL ([-1, 1])
real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, data.rawDepthDst);
#endif
float3 worldUV = ComputeWorldSpacePosition(data.refractionUV, depth, UNITY_MATRIX_I_VP);
float causticFade = DistanceFade(data.refractionData.a, data.pixelDepth, _CausticsStart, _CausticsEnd);
#if _CAUSTICSMODE_3D
float3 speed = _CausticsSpeed3D.xyz * _Time.x;
float3 UV3D = worldUV * _CausticsTiling3D + speed;
float3 CausticMix = SAMPLE_TEXTURE3D(_CausticsTex3D, URPWater_linear_repeat_sampler, UV3D).rgb;
#else
float4 offsets = frac(_CausticsSpeed * _Time.x);
float3 CausticsA = SAMPLE_TEXTURE2D(_CausticsTex, URPWater_linear_repeat_sampler, worldUV.xz * _CausticsTiling.xy + offsets.xy).rgb;
float3 CausticsB = SAMPLE_TEXTURE2D(_CausticsTex, URPWater_linear_repeat_sampler, worldUV.xz * _CausticsTiling.zw + offsets.zw).rgb;
float3 CausticMix = min(CausticsA, CausticsB);
#endif
// Normals
#if _CAUSTICS_ANGLE_ON || _CAUSTICS_DIRECTION_ON
float3 angleMask = NormalFromDepthFast(IN.pos, data.refractionOffset);
#if _CAUSTICS_ANGLE_ON
causticFade *= saturate(angleMask.y * angleMask.y);
#endif
#if _CAUSTICS_DIRECTION_ON
float dotMask = dot(data.mainLight.direction, angleMask);
causticFade *= saturate(dotMask);
#endif
#endif
// Caustic projection for shadow
//Light mainLight = GetMainLight(TransformWorldToShadowCoord(worldUV));
//float shadow = mainLight.shadowAttenuation;
#if (defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN))
half shadow = SampleShadows(IN, data);
#else
half shadow = 1.0;
#endif
#if _FOAM_ON
causticFade *= 1 - data.foamMask * 2;
#endif
causticColor = CausticMix * max(0,_CausticsIntensity) * causticFade * (shadow + Ambient * 0.5);
}
// =================================================================
// Directional light computations
// =================================================================
float3 ComputeMainLightDiffuse(float3 direction, float3 worldNormal)
{
return saturate(dot(worldNormal, direction));
}
float3 ComputeMainLightSpecular(
Light mainLight,
float3 worldNormal,
float3 worldViewDir,
float3 specular,
float smoothness)
{
smoothness = exp2(10 * smoothness + 1);
/*
float reflectiveFactor = max(0.0, dot(-worldViewDir, reflect(mainLight.direction, worldNormal)));
float3 spec = pow(reflectiveFactor, smoothness);
return mainLight.color * specular * spec;
*/
// Unity spec
return LightingSpecular(mainLight.color, mainLight.direction, worldNormal, worldViewDir, float4(specular, 0), smoothness);
}
Light ComputeMainLight(float3 worldPos)
{
return GetMainLight(TransformWorldToShadowCoord(worldPos));
}
// =================================================================
// Additive lights computations
// =================================================================
float3 ComputeAdditiveLight(float3 worldPos, float3 worldNormal, float3 worldViewDir, float3 specColor, float smoothness)
{
smoothness = exp2(10 * smoothness + 1);
int pixelLightCount = GetAdditionalLightsCount();
float3 diffuse = float3(0, 0, 0);
float3 specularColor = float3(0, 0, 0);
for (int l = 0; l < pixelLightCount; ++l)
{
Light light = GetAdditionalLight(l, worldPos);
half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
diffuse += LightingLambert(attenuatedLightColor, light.direction, worldNormal) * 0.25;
specularColor += LightingSpecular(attenuatedLightColor, light.direction, worldNormal, worldViewDir, half4(specColor, 0), smoothness);
}
return diffuse + specularColor;
}
void ComputeUnderWaterShading(inout GlobalData data, Varyings IN, float3 ambient)
{
float3 clearRefraction = data.refractionData.rgb;
#if _COLORMODE_COLORS
float3 shallowColor = _Color.rgb * data.refractionData.rgb;
float3 depthColor = _DepthColor.rgb * data.shadowColor.rgb;
data.refractionData.rgb = lerp(depthColor, shallowColor, data.depth);
#endif
#if _COLORMODE_GRADIENT
float3 ramp = SAMPLE_TEXTURE2D(_RefractionColor, URPWater_linear_clamp_sampler, float2(data.depth, 0.5)).rgb * data.shadowColor.rgb;
float3 shallowColor = ramp * data.refractionData.rgb;
data.refractionData.rgb = lerp(ramp, shallowColor, data.depth);
#endif
#if _DOUBLE_SIDED_ON
float3 underColor = lerp(clearRefraction.rgb * _UnderWaterColor.rgb, _UnderWaterColor.rgb, _UnderWaterColor.a);
data.refractionData.rgb = lerp(underColor, data.refractionData.rgb, data.vFace);
#endif
float invDepth = 1 - data.depth;
data.finalColor = lerp(data.refractionData.rgb, data.refractionData.rgb * saturate(data.mainLight.color) , invDepth);
}
// =================================================================
// Full lighting computations
// =================================================================
void ComputeLighting(inout GlobalData data, Varyings IN)
{
Light mainLight = data.mainLight;
float3 lightDir = mainLight.direction;
float3 lightColor = mainLight.color;
#if _DOUBLE_SIDED_ON
float3 flippedLight = mainLight.direction;
flippedLight.y = -flippedLight.y;
mainLight.direction = lerp(flippedLight, mainLight.direction, data.vFace);
#endif
//float3 mainDiffuse = ComputeMainLightDiffuse(lightDir.xyz, data.worldNormal) * lightColor * 0.5 + 0.5;
float3 mainSpecular = ComputeMainLightSpecular(mainLight, data.worldNormal, data.worldViewDir, _SpecColor.rgb, _Smoothness);
#if (defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN))
half shadow = SampleShadows(IN, data);
#else
half shadow = 1.0;
#endif
float shadowMask = shadow;//max(data.depth, shadow);
float3 ambient = SampleSH(data.worldNormal);
float3 AddLighting = ComputeAdditiveLight(data.worldPosition, data.worldNormal, data.worldViewDir, _SpecColor.rgb, _Smoothness);
// TODO: Try using ambient color again
//data.shadowColor = lerp(_AmbientColor.rgb, float3(1,1,1), saturate(shadow + data.depth));
// Shadow
data.shadowColor = saturate(shadowMask + ambient * 2.0);
// Underwater color
ComputeUnderWaterShading(data, IN, ambient);
//data.finalColor = lerp(data.refractionData.rgb, data.refractionData.rgb * saturate(lightColor) , invDepth);
#if _CAUSTICS_ON
float3 caustics = float3(1,1,1);
ComputeCaustics(caustics, data, IN, ambient);
#if _DOUBLE_SIDED_ON
caustics = lerp(0, caustics, data.vFace);
#endif
data.finalColor += data.finalColor * caustics * saturate(length(lightColor));
#endif
#if _SCATTERING_ON
data.finalColor.rgb += data.scattering * shadow;
#endif
#if _FOAM_ON
mainSpecular *= 1- saturate(data.foamMask.xxx);
half NdotL = dot(data.worldNormal, lightDir);
half3 foamColor = _FoamColor.rgb * saturate(NdotL) * lightColor * shadow + ambient;
data.finalColor = lerp(data.finalColor, foamColor, data.foamMask * _FoamColor.a);
#endif
// Specular and additive light after reflection
data.addLight = (AddLighting + mainSpecular) * data.shadowColor;
// Shadows
data.finalColor = data.finalColor * data.shadowColor;
}
#endif