还原水插件

This commit is contained in:
2026-03-05 00:14:42 +08:00
parent 0de35591e7
commit e82f2ea6b7
270 changed files with 2773 additions and 12445 deletions

View File

@@ -6,7 +6,7 @@
#define m_Properties \
const float2 i_UndisplacedXZ, \
float i_LodAlpha, \
const float i_LodAlpha, \
const half i_WaterLevelOffset, \
const float2 i_WaterLevelDerivatives, \
const half2 i_Flow, \
@@ -19,36 +19,13 @@
const float3 i_PositionWS, \
const float3 i_PositionVS, \
const float2 i_StaticLightMapUV, \
inout half3 o_Albedo, \
inout half3 o_NormalWS, \
inout half3 o_Specular, \
inout half3 o_Emission, \
inout half o_Smoothness, \
inout half o_Occlusion, \
inout half o_Alpha
#define m_Parameters \
i_UndisplacedXZ, \
i_LodAlpha, \
i_WaterLevelOffset, \
i_WaterLevelDerivatives, \
i_Flow, \
i_ViewDirectionWS, \
i_Facing, \
i_SceneColor, \
i_SceneDepthRaw, \
i_ScreenPosition, \
i_ScreenPositionRaw, \
i_PositionWS, \
i_PositionVS, \
i_StaticLightMapUV, \
o_Albedo, \
o_NormalWS, \
o_Specular, \
o_Emission, \
o_Smoothness, \
o_Occlusion, \
o_Alpha
out half3 o_Albedo, \
out half3 o_NormalWS, \
out half3 o_Specular, \
out half3 o_Emission, \
out half o_Smoothness, \
out half o_Occlusion, \
out half o_Alpha
// Guard against Shader Graph preview.
#ifndef SHADERGRAPH_PREVIEW
@@ -56,7 +33,6 @@
#define d_Crest_WaterSurface 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Shim.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Keywords.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
@@ -78,7 +54,6 @@
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Refraction.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Caustics.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Emission.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Fresnel.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Foam.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Alpha.hlsl"
@@ -104,18 +79,17 @@ static const TiledTexture _Crest_CausticsTiledTexture =
static const TiledTexture _Crest_CausticsDistortionTiledTexture =
TiledTexture::Make(_Crest_CausticsDistortionTexture, sampler_Crest_CausticsDistortionTexture, _Crest_CausticsDistortionTexture_TexelSize, _Crest_CausticsDistortionScale, 1.0);
void Fragment
(
m_Properties,
const uint i_LodIndex0,
const uint i_LodIndex1,
const float2 i_PositionSS,
const bool i_Underwater,
const float i_SceneZRaw,
const float i_NegativeFog
)
void Fragment(m_Properties)
{
float2 scenePositionSS = i_PositionSS;
o_Albedo = 0.0;
o_NormalWS = half3(0.0, 1.0, 0.0);
o_Specular = 0.0;
o_Emission = 0.0;
o_Smoothness = 0.7;
o_Occlusion = 1.0;
o_Alpha = 1.0;
const float2 positionSS = i_ScreenPosition.xy * _ScreenSize.xy;
// Editor only. There is no defined editor symbol.
if (_Crest_DrawBoundaryXZ)
@@ -131,25 +105,47 @@ void Fragment
}
}
const uint slice0 = i_LodIndex0;
const uint slice1 = i_LodIndex1;
bool underwater = IsUnderWater(i_Facing, g_Crest_ForceUnderwater, positionSS);
#if d_Crest_FlowLod
// TODO: Should we use PosToSIs or check for overflow?
float slice0 = _Crest_LodIndex;
float slice1 = _Crest_LodIndex + 1;
#ifdef CREST_FLOW_ON
const Flow flow = Flow::Make(i_Flow, g_Crest_Time);
#endif
const Cascade cascade0 = Cascade::Make(slice0);
const Cascade cascade1 = Cascade::Make(slice1);
const float sceneZ = Utility::CrestLinearEyeDepth(i_SceneZRaw);
const float pixelZ = -i_PositionVS.z;
float sceneRawZ = i_SceneDepthRaw;
float negativeFog = _ProjectionParams.y;
const bool isLastLod = slice0 == (uint)g_Crest_LodCount - 1;
#if (CREST_PORTALS != 0)
#ifndef CREST_SHADOWPASS
#if _ALPHATEST_ON
if (m_CrestPortal)
{
const float pixelRawZ = i_ScreenPositionRaw.z / i_ScreenPositionRaw.w;
if (Portal::EvaluateSurface(i_ScreenPosition.xy, pixelRawZ, i_PositionWS, underwater, sceneRawZ, negativeFog))
{
o_Alpha = 0.0;
return;
}
}
#endif
#endif
#endif
float sceneZ = Utility::CrestLinearEyeDepth(sceneRawZ);
float pixelZ = -i_PositionVS.z;
const bool isLastLod = _Crest_LodIndex == (uint)g_Crest_LodCount - 1;
const float weight0 = (1.0 - i_LodAlpha) * cascade0._Weight;
const float weight1 = (1.0 - weight0) * cascade1._Weight;
// Data that fades towards the edge.
half foam = 0.0; half _determinant = 0.0; half4 albedo = 0.0; half2 shadow = 0.0; half waterDepth = i_WaterLevelOffset; half shorelineDistance = 0.0;
half foam = 0.0; half _determinant = 0.0; half4 albedo = 0.0; half2 shadow = 0.0;
if (weight0 > m_CrestSampleLodThreshold)
{
Cascade::MakeAnimatedWaves(slice0).SampleNormals(i_UndisplacedXZ, weight0, o_NormalWS.xz, _determinant);
@@ -159,28 +155,15 @@ void Fragment
Cascade::MakeFoam(slice0).SampleFoam(i_UndisplacedXZ, weight0, foam);
}
#if d_Crest_AlbedoLod
if (_Crest_AlbedoEnabled)
{
Cascade::MakeAlbedo(slice0).SampleAlbedo(i_UndisplacedXZ, weight0, albedo);
}
#endif
#if d_Crest_ShadowLod
if (_Crest_ShadowsEnabled)
{
Cascade::MakeShadow(slice0).SampleShadow(i_PositionWS.xz, weight0, shadow);
}
#endif
#if d_Crest_SimpleTransparency || d_Crest_FoamBioluminescence
#if !d_Crest_SimpleTransparency
if (_Crest_FoamEnabled && _Crest_FoamBioluminescenceEnabled)
#endif
{
Cascade::MakeDepth(slice0).SampleSignedDepthFromSeaLevelAndDistance(i_PositionWS.xz, weight0, waterDepth, shorelineDistance);
}
#endif
}
if (weight1 > m_CrestSampleLodThreshold)
@@ -192,28 +175,15 @@ void Fragment
Cascade::MakeFoam(slice1).SampleFoam(i_UndisplacedXZ, weight1, foam);
}
#if d_Crest_AlbedoLod
if (_Crest_AlbedoEnabled)
{
Cascade::MakeAlbedo(slice1).SampleAlbedo(i_UndisplacedXZ, weight1, albedo);
}
#endif
#if d_Crest_ShadowLod
if (_Crest_ShadowsEnabled)
{
Cascade::MakeShadow(slice1).SampleShadow(i_PositionWS.xz, weight1, shadow);
}
#endif
#if d_Crest_SimpleTransparency || d_Crest_FoamBioluminescence
#if !d_Crest_SimpleTransparency
if (_Crest_FoamEnabled && _Crest_FoamBioluminescenceEnabled)
#endif
{
Cascade::MakeDepth(slice1).SampleSignedDepthFromSeaLevelAndDistance(i_PositionWS.xz, weight1, waterDepth, shorelineDistance);
}
#endif
}
// Invert so shadows are black as we normally multiply this by lighting.
@@ -221,81 +191,99 @@ void Fragment
// Data that displays to the edge.
// The default simulation value has been written to the border of the last slice.
half3 absorption = _Crest_Absorption.xyz; half3 scattering = _Crest_Scattering.xyz;
#if d_Crest_AbsorptionLod || d_Crest_ScatteringLod
half3 absorption = 0.0; half3 scattering = 0.0;
{
const float weight0 = (1.0 - (isLastLod ? 0.0 : i_LodAlpha)) * cascade0._Weight;
const float weight1 = (1.0 - weight0) * cascade1._Weight;
#if d_Crest_ScatteringLod
if (g_Crest_SampleScatteringSimulation)
{
scattering = 0.0;
}
#endif
#if d_Crest_AbsorptionLod
if (g_Crest_SampleAbsorptionSimulation)
{
absorption = 0.0;
}
#endif
if (weight0 > m_CrestSampleLodThreshold)
{
#if d_Crest_ScatteringLod
if (g_Crest_SampleScatteringSimulation)
{
Cascade::MakeScattering(slice0).SampleScattering(i_UndisplacedXZ, weight0, scattering);
}
#endif
#if d_Crest_AbsorptionLod
if (g_Crest_SampleAbsorptionSimulation)
{
Cascade::MakeAbsorption(slice0).SampleAbsorption(i_UndisplacedXZ, weight0, absorption);
}
#endif
}
if (weight1 > m_CrestSampleLodThreshold)
{
#if d_Crest_ScatteringLod
if (g_Crest_SampleScatteringSimulation)
{
Cascade::MakeScattering(slice1).SampleScattering(i_UndisplacedXZ, weight1, scattering);
}
#endif
#if d_Crest_AbsorptionLod
if (g_Crest_SampleAbsorptionSimulation)
{
Cascade::MakeAbsorption(slice1).SampleAbsorption(i_UndisplacedXZ, weight1, absorption);
}
#endif
}
}
#endif
if (!g_Crest_SampleScatteringSimulation)
{
scattering = _Crest_Scattering.xyz;
}
if (!g_Crest_SampleAbsorptionSimulation)
{
absorption = _Crest_Absorption.xyz;
}
// Determinant needs to be one when no waves.
if (isLastLod)
{
_determinant += 1.0 - weight0;
waterDepth = 10000.0;
}
#if d_Transparent
// Feather at intersection. Cannot be used for shadows since depth is not available.
const float feather =
#if d_Crest_SimpleTransparency
saturate(waterDepth / 0.2);
#else
saturate((sceneZ - pixelZ) / 0.2);
#endif
// Normal.
{
if (_Crest_NormalMapEnabled)
{
o_NormalWS.xz += SampleNormalMaps
(
#ifdef CREST_FLOW_ON
flow,
#endif
_Crest_NormalMapTiledTexture,
_Crest_NormalMapStrength,
i_UndisplacedXZ,
i_LodAlpha,
cascade0
);
}
const half3 extinction = VolumeExtinction(absorption, scattering);
o_NormalWS = normalize(o_NormalWS);
WaterNormal
(
i_WaterLevelDerivatives,
i_ViewDirectionWS,
_Crest_MinimumReflectionDirectionY,
underwater,
o_NormalWS
);
o_NormalWS = normalize(o_NormalWS);
o_NormalWS.xz *= _Crest_NormalsStrengthOverall;
o_NormalWS.y = lerp(1.0, o_NormalWS.y, _Crest_NormalsStrengthOverall);
if (underwater)
{
// Flip when underwater.
o_NormalWS.xyz *= -1.0;
}
}
// Default for opaque render type.
float sceneDistance = 1000.0;
float3 scenePositionWS = 0.0;
const half3 ambientLight = AmbientLight();
float3 lightIntensity = 0.0;
half3 lightDirection = 0.0;
@@ -307,123 +295,24 @@ void Fragment
lightDirection
);
const half3 ambientLight = AmbientLight();
const half3 additionalLight = AdditionalLighting(i_PositionWS, i_ScreenPositionRaw, i_StaticLightMapUV);
half3 additionalLight = AdditionalLighting(i_PositionWS, i_ScreenPositionRaw, i_StaticLightMapUV);
// Normal.
{
WaterNormal
(
i_WaterLevelDerivatives,
i_ViewDirectionWS,
_Crest_MinimumReflectionDirectionY,
i_Underwater,
o_NormalWS
);
#if d_Crest_NormalMap
if (_Crest_NormalMapEnabled)
{
const half2 normalMap = SampleNormalMaps
(
#if d_Crest_FlowLod
flow,
#endif
_Crest_NormalMapTiledTexture,
_Crest_NormalMapStrength,
i_UndisplacedXZ,
i_LodAlpha,
cascade0
);
half normalMapStrength = _Crest_NormalMapStrength;
if (_Crest_NormalMapTurbulenceEnabled)
{
normalMapStrength = NormalMapTurbulence
(
o_NormalWS,
normalMap,
normalMapStrength,
_Crest_NormalMapTurbulenceCoverage,
_Crest_NormalMapTurbulenceStrength,
i_ViewDirectionWS,
_determinant,
g_Crest_WaterCenter.y + i_WaterLevelOffset,
pixelZ,
lightDirection
);
}
o_NormalWS.xz += normalMap * normalMapStrength;
}
#endif // d_Crest_NormalMap
o_NormalWS = normalize(o_NormalWS);
WaterNormal
(
i_WaterLevelDerivatives,
i_ViewDirectionWS,
_Crest_MinimumReflectionDirectionY,
i_Underwater,
o_NormalWS
);
o_NormalWS = normalize(o_NormalWS);
o_NormalWS.xz *= _Crest_NormalsStrengthOverall;
o_NormalWS.y = lerp(1.0, o_NormalWS.y, _Crest_NormalsStrengthOverall);
if (i_Underwater)
{
// Flip when underwater.
o_NormalWS.xyz *= -1.0;
}
}
// Default for opaque render type.
float sceneDistance = 1000.0;
float3 scenePositionWS = i_PositionWS;
#if d_Crest_SimpleTransparency
sceneDistance = waterDepth;
// Increase ray for grazing angles.
sceneDistance += (1.0 - dot(i_ViewDirectionWS, o_NormalWS)) * waterDepth;
scenePositionWS.y = i_PositionWS.y - waterDepth;
// Cannot sample scene so go with average light.
o_Emission = i_Underwater ? 0.0 : (0.5 * (lightIntensity + additionalLight + ambientLight) * INV_PI);
#if CREST_HDRP
o_Emission /= GetCurrentExposureMultiplier();
#endif
#endif
bool caustics = !i_Underwater;
#if !d_Crest_SimpleTransparency
#if d_Transparent
#ifndef d_SkipRefraction
bool caustics;
RefractedScene
(
_Crest_RefractionStrength,
1.000293, // air
_Crest_RefractiveIndexOfWater,
o_NormalWS,
i_PositionWS,
i_ScreenPosition.xy,
i_ScreenPositionRaw,
pixelZ,
i_ViewDirectionWS,
i_SceneColor,
sceneZ,
i_SceneZRaw,
cascade0._Scale,
i_LodAlpha,
i_Underwater,
_Crest_TotalInternalReflectionIntensity,
sceneRawZ,
underwater,
o_Emission,
sceneDistance,
scenePositionWS,
scenePositionSS,
caustics
);
@@ -440,46 +329,45 @@ void Fragment
#endif
#endif // d_SkipRefraction
#endif // d_Transparent
#endif // d_Crest_SimpleTransparency
float refractedSeaLevel = g_Crest_WaterCenter.y;
float3 refractedSurfacePosition = float3(0, refractedSeaLevel, 0);
if (!underwater && slice1 < g_Crest_LodCount)
{
// Sample larger slice to avoid the first slice.
float4 displacement = Cascade::MakeAnimatedWaves(slice1).Sample(scenePositionWS.xz);
refractedSeaLevel = g_Crest_WaterCenter.y + displacement.w;
refractedSurfacePosition = displacement.xyz;
refractedSurfacePosition.y += refractedSeaLevel;
}
// Out-scattering.
if (!i_Underwater)
if (!underwater)
{
// Account for extinction of light as it travels down through volume.
o_Emission *= exp(-extinction * max(0.0, i_PositionWS.y - scenePositionWS.y));
// Account for average extinction of light as it travels down through volume. Assume flat water as anything else would be expensive.
half3 extinction = absorption.xyz + scattering.xyz;
o_Emission *= exp(-extinction * max(0.0, refractedSeaLevel - scenePositionWS.y));
}
#if d_Transparent
#ifndef d_SkipRefraction
// Caustics
if (_Crest_CausticsEnabled && !i_Underwater && caustics)
if (_Crest_CausticsEnabled && !underwater && caustics)
{
half lightOcclusion = 1.0;
#if !d_Crest_SimpleTransparency
lightOcclusion = PrimaryLightShadows(scenePositionWS, scenePositionSS);
#endif
#if d_Crest_SimpleTransparency
if (_Crest_RefractionStrength > 0.0)
{
// Gives a parallax like effect.
const half3 ray = refract(-i_ViewDirectionWS, o_NormalWS, 1.0 / _Crest_RefractiveIndexOfWater) * _Crest_RefractionStrength;
scenePositionWS += ray * waterDepth * 2.0;
}
#endif
half lightOcclusion = PrimaryLightShadows(scenePositionWS, positionSS);
half blur = 0.0;
#if d_Crest_FlowLod
#ifdef CREST_FLOW_ON
blur = _Crest_CausticsMotionBlur;
#endif
o_Emission *= Caustics
(
#if d_Crest_FlowLod
#ifdef CREST_FLOW_ON
flow,
#endif
scenePositionWS,
i_PositionWS.y,
refractedSurfacePosition.y,
lightIntensity,
lightDirection,
lightOcclusion,
@@ -492,7 +380,7 @@ void Fragment
_Crest_CausticsDistortionTiledTexture,
_Crest_CausticsDistortionStrength,
blur,
_Crest_CausticsForceDistortion
underwater
);
}
#endif // d_SkipRefraction
@@ -516,6 +404,7 @@ void Fragment
}
// Volume Lighting
const half3 extinction = VolumeExtinction(absorption, scattering);
const half3 volumeOpacity = VolumeOpacity(extinction, sceneDistance);
const half3 volumeLight = VolumeLighting
(
@@ -542,7 +431,7 @@ void Fragment
(
i_ViewDirectionWS,
o_NormalWS,
i_Underwater,
underwater,
1.0, // air
_Crest_RefractiveIndexOfWater,
_Crest_TotalInternalReflectionIntensity,
@@ -550,7 +439,7 @@ void Fragment
reflected
);
if (i_Underwater)
if (underwater)
{
o_Emission *= transmitted;
o_Emission += volumeLight * reflected;
@@ -563,12 +452,10 @@ void Fragment
}
}
#if _SPECULAR_SETUP
// Specular
{
o_Specular = _Crest_Specular * reflected * shadow.y;
}
#endif
// Smoothness
{
@@ -578,27 +465,24 @@ void Fragment
// Occlusion
{
o_Occlusion = i_Underwater ? _Crest_OcclusionUnderwater : _Crest_Occlusion;
o_Occlusion = underwater ? _Crest_OcclusionUnderwater : _Crest_Occlusion;
}
// Planar Reflections
#if d_Crest_PlanarReflections
if (_Crest_PlanarReflectionsEnabled)
{
half4 reflection = PlanarReflection
(
_Crest_ReflectionColorTexture,
sampler_Crest_ReflectionColorTexture,
_Crest_ReflectionTexture,
sampler_Crest_ReflectionTexture,
_Crest_PlanarReflectionsIntensity,
o_Smoothness,
_Crest_PlanarReflectionsRoughness,
_Crest_MinimumReflectionDirectionY,
pixelZ,
o_NormalWS,
_Crest_PlanarReflectionsDistortion,
i_ViewDirectionWS,
i_ScreenPosition.xy,
i_Underwater
underwater
);
half alpha = reflection.a;
@@ -607,14 +491,13 @@ void Fragment
// Results are darker than Unity's.
o_Occlusion *= 1.0 - alpha;
}
#endif // d_Crest_PlanarReflections
// Foam
if (_Crest_FoamEnabled)
{
half2 albedo = MultiScaleFoamAlbedo
half albedo = MultiScaleFoamAlbedo
(
#if d_Crest_FlowLod
#ifdef CREST_FLOW_ON
flow,
#endif
_Crest_FoamTiledTexture,
@@ -623,20 +506,19 @@ void Fragment
cascade0,
cascade1,
i_LodAlpha,
i_UndisplacedXZ,
_Crest_FoamBioluminescenceEnabled && _Crest_FoamBioluminescenceSparklesEnabled
i_UndisplacedXZ
);
half2 normal = MultiScaleFoamNormal
(
#if d_Crest_FlowLod
#ifdef CREST_FLOW_ON
flow,
#endif
_Crest_FoamTiledTexture,
_Crest_FoamFeather,
_Crest_FoamNormalStrength,
foam,
albedo.x,
albedo,
cascade0,
cascade1,
i_LodAlpha,
@@ -648,13 +530,13 @@ void Fragment
ApplyFoamToSurface
(
albedo.x,
albedo,
normal,
intensity,
_Crest_Occlusion,
_Crest_FoamSmoothness,
_Crest_Specular,
i_Underwater,
underwater,
o_Albedo,
o_NormalWS,
o_Emission,
@@ -664,71 +546,36 @@ void Fragment
);
// We will use this for shadow casting.
const half foamData = foam;
foam = albedo.r;
#if d_Crest_FoamBioluminescence
if (_Crest_FoamBioluminescenceEnabled)
{
half3 emission = FoamBioluminescence
(
foamData,
albedo.r,
_Crest_FoamBioluminescenceColor.rgb,
_Crest_FoamBioluminescenceIntensity,
_Crest_FoamBioluminescenceGlowCoverage,
_Crest_FoamBioluminescenceGlowIntensity,
_Crest_FoamBioluminescenceSparklesEnabled,
albedo.y,
_Crest_FoamBioluminescenceSparklesCoverage,
_Crest_FoamBioluminescenceSparklesIntensity,
_Crest_FoamBioluminescenceMaximumDepth,
waterDepth
);
emission *= _Crest_FoamBioluminescenceSeaLevelOnly ? saturate(1.0 - abs(i_WaterLevelOffset)) : 1.0;
#if d_Transparent
// Apply feathering to avoid hardening the edge.
emission *= feather * feather * feather;
#endif
o_Emission += emission;
}
#endif // d_Crest_FoamBioluminescence
foam = albedo;
}
// Albedo
#if d_Crest_AlbedoLod
if (_Crest_AlbedoEnabled)
{
const float foamMask = _Crest_AlbedoIgnoreFoam ? (1.0 - saturate(foam)) : 1.0;
o_Albedo = lerp(o_Albedo, albedo.rgb, albedo.a * foamMask);
o_Emission *= 1.0 - albedo.a * foamMask;
}
#endif
#if d_Crest_SimpleTransparency
o_Alpha = i_Underwater
? 1.0 - transmitted
: max(max(length(volumeOpacity), _Crest_TransparencyMinimumAlpha), max(foam, albedo.a));
#endif
// Alpha
{
#ifndef CREST_SHADOWPASS
#if d_Transparent
// Feather at intersection. Cannot be used for shadows since depth is not available.
o_Alpha = min(o_Alpha, feather);
o_Alpha = saturate((sceneZ - pixelZ) / 0.2);
#endif
#endif
// This keyword works for all RPs despite BIRP having prefixes in serialised data.
#if d_Crest_AlphaTest
#if _ALPHATEST_ON
#if CREST_SHADOWPASS
o_Alpha = min(o_Alpha, max(foam, albedo.a) - _Crest_ShadowCasterThreshold);
o_Alpha = max(foam, albedo.a) - _Crest_ShadowCasterThreshold;
#endif
#endif // d_Crest_AlphaTest
// Add 0.5 bias for LOD blending and texel resolution correction. This will help to
// tighten and smooth clipped edges.
o_Alpha -= ClipSurface(i_PositionWS.xz) > 0.5 ? 2.0 : 0.0;
#endif // _ALPHATEST_ON
// Specular in HDRP is still affected outside the 0-1 alpha range.
o_Alpha = min(o_Alpha, 1.0);
@@ -736,107 +583,22 @@ void Fragment
SetUpFog
(
i_Underwater,
underwater,
i_PositionWS,
1.0, // N/A: multiplier for fog nodes
pixelZ - i_NegativeFog,
sceneDistance - negativeFog,
i_ViewDirectionWS,
i_PositionSS
positionSS
);
}
// IMPORTANT!
// Do not branch on o_Alpha, as it is not robust. Rendering will break on stereo
// rendering in the form of losing additional lighting and/or broken reflection
// probe sampling. This is an issue with the shader compiler it seems.
void Fragment(m_Properties)
{
const float2 positionSS = i_ScreenPosition.xy * _ScreenSize.xy;
bool underwater = IsUnderWater(i_Facing, g_Crest_ForceUnderwater, positionSS);
float sceneRawZ = i_SceneDepthRaw;
float negativeFog = _ProjectionParams.y;
#if d_Crest_AlphaTest
#if !d_Crest_SimpleTransparency
#ifndef CREST_SHADOWPASS
#if (CREST_PORTALS != 0)
if (m_CrestPortal)
{
const float pixelRawZ = i_ScreenPositionRaw.z / i_ScreenPositionRaw.w;
o_Alpha = Portal::EvaluateSurface(i_ScreenPosition.xy, pixelRawZ, i_PositionWS, underwater, sceneRawZ, negativeFog) ? -1.0 : 1.0;
#ifndef SHADER_API_WEBGPU
clip(o_Alpha);
#endif
}
#endif
#endif
#endif
#endif
uint slice0;
uint slice1;
float alpha;
#if d_Crest_AlphaTest || d_Crest_CustomMesh
PosToSliceIndices(i_PositionWS.xz, 0.0, g_Crest_LodCount - 1.0, g_Crest_WaterScale, slice0, slice1, alpha);
#endif
#if d_Crest_AlphaTest
{
const Cascade cascade0 = Cascade::Make(slice0);
const Cascade cascade1 = Cascade::Make(slice1);
const float weight0 = (1.0 - alpha) * cascade0._Weight;
const float weight1 = (1.0 - weight0) * cascade1._Weight;
float clipSurface = 0.0;
if (weight0 > m_CrestSampleLodThreshold)
{
Cascade::MakeClip(slice0).SampleClip(i_PositionWS.xz, weight0, clipSurface);
}
if (weight1 > m_CrestSampleLodThreshold)
{
Cascade::MakeClip(slice1).SampleClip(i_PositionWS.xz, weight1, clipSurface);
}
// Add 0.5 bias for LOD blending and texel resolution correction. This will help to
// tighten and smooth clipped edges.
o_Alpha -= clipSurface > 0.5 ? 2.0 : 0.0;
#ifndef SHADER_API_WEBGPU
clip(o_Alpha);
#endif
}
#endif
{
#if !d_Crest_CustomMesh
slice0 = _Crest_LodIndex;
slice1 = _Crest_LodIndex + 1;
alpha = i_LodAlpha;
#endif
i_LodAlpha = alpha;
Fragment
(
m_Parameters,
slice0,
slice1,
positionSS,
underwater,
sceneRawZ,
negativeFog
);
}
}
m_CrestNameSpaceEnd
#endif // SHADERGRAPH_PREVIEW
void Fragment_float(m_Properties)
{
#if SHADERGRAPH_PREVIEW
o_Albedo = 0.0;
o_NormalWS = half3(0.0, 1.0, 0.0);
o_Specular = 0.0;
@@ -844,10 +606,32 @@ void Fragment_float(m_Properties)
o_Smoothness = 0.7;
o_Occlusion = 1.0;
o_Alpha = 1.0;
#if !SHADERGRAPH_PREVIEW
m_Crest::Fragment(m_Parameters);
#endif
#else // SHADERGRAPH_PREVIEW
m_Crest::Fragment
(
i_UndisplacedXZ,
i_LodAlpha,
i_WaterLevelOffset,
i_WaterLevelDerivatives,
i_Flow,
i_ViewDirectionWS,
i_Facing,
i_SceneColor,
i_SceneDepthRaw,
i_ScreenPosition,
i_ScreenPositionRaw,
i_PositionWS,
i_PositionVS,
i_StaticLightMapUV,
o_Albedo,
o_NormalWS,
o_Specular,
o_Emission,
o_Smoothness,
o_Occlusion,
o_Alpha
);
#endif // SHADERGRAPH_PREVIEW
}
#undef m_Properties