Skip to content

Commit

Permalink
Fix #1156 Use infinity water depth
Browse files Browse the repository at this point in the history
Fixes incorrect depth values when away from zero, and greatly simplifies
everything. Caution must be taken as infinity can cause issues.

Water depth sampling had to be moved to the fragment shader, as it had
artifacts possibly from interpolation.

Additionally, improved fading out of shallow SSS towards the end of
cascades.
  • Loading branch information
daleeidd committed Aug 14, 2024
1 parent e352343 commit 3a2cac1
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ namespace Crest
public class LodDataMgrSeaFloorDepth : LodDataMgr
{
// NOTE: Must match CREST_OCEAN_DEPTH_BASELINE in OceanConstants.hlsl.
internal const float k_DepthBaseline = 1_000f;
internal const float k_DepthBaseline = Mathf.Infinity;

public override string SimName => "SeaFloorDepth";
protected override GraphicsFormat RequestedTextureFormat => Settings._allowVaryingWaterLevel ? GraphicsFormat.R32G32_SFloat : GraphicsFormat.R16_SFloat;
protected override bool NeedToReadWriteTextureData => false;
// We want the clear colour to be the min terrain height (-1000m) in X, and sea level offset 0m in Y.
readonly static Color s_nullColor = Color.red * -k_DepthBaseline;
// Lowest possible scene height in X, and sea level offset 0m in Y.
readonly static Color s_nullColor = new Color(-k_DepthBaseline, 0, 0, 0);
static Texture2DArray s_nullTexture;
protected override Texture2DArray NullTexture => s_nullTexture;

Expand Down
4 changes: 1 addition & 3 deletions crest/Assets/Crest/Crest/Scripts/LodData/OceanDepthCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,7 @@ bool InitObjects(bool updateComponents)
_camDepthCache.transform.parent = transform;
_camDepthCache.transform.localEulerAngles = 90f * Vector3.right;
_camDepthCache.orthographic = true;
_camDepthCache.clearFlags = CameraClearFlags.SolidColor;
// Clear to 'very deep'
_camDepthCache.backgroundColor = Color.white * LodDataMgrSeaFloorDepth.k_DepthBaseline;
_camDepthCache.clearFlags = CameraClearFlags.Depth;
_camDepthCache.enabled = false;
_camDepthCache.allowMSAA = false;
_camDepthCache.allowDynamicResolution = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ public partial class SimSettingsAnimatedWaves : SimSettingsBase
public float AttenuationInShallows => _attenuationInShallows;

[Tooltip("Any water deeper than this will receive full wave strength. The lower the value, the less effective the depth cache will be at attenuating very large waves. Set to the maximum value (1,000) to disable.")]
[SerializeField, Range(1f, LodDataMgrSeaFloorDepth.k_DepthBaseline)]
float _shallowsMaxDepth = LodDataMgrSeaFloorDepth.k_DepthBaseline;
[SerializeField, Range(1f, 1000f)]
float _shallowsMaxDepth = 1000f;
public float MaximumAttenuationDepth => _shallowsMaxDepth;

public enum CollisionSources
Expand Down
36 changes: 27 additions & 9 deletions crest/Assets/Crest/Crest/Shaders/Ocean.shader
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,6 @@ Shader "Crest/Ocean"
// sample shape textures - always lerp between 2 LOD scales, so sample two textures
o.flow_shadow = half4(0.0, 0.0, 0.0, 0.0);

o.lodAlpha_worldXZUndisplaced_oceanDepth.w = CREST_OCEAN_DEPTH_BASELINE;
// Sample shape textures - always lerp between 2 LOD scales, so sample two textures

// Calculate sample weights. params.z allows shape to be faded out (used on last lod to support pop-less scale transitions)
Expand Down Expand Up @@ -410,11 +409,12 @@ Shader "Crest/Ocean"
// Data that needs to be sampled at the displaced position
half seaLevelOffset = 0.0;
o.seaLevelDerivs = 0.0;
half seaDepth = 0.0;
if (wt_smallerLod > 0.0001)
{
const float3 uv_slice_smallerLodDisp = WorldToUV(o.worldPos.xz, cascadeData0, _LD_SliceIndex);

SampleSeaDepth(_LD_TexArray_SeaFloorDepth, uv_slice_smallerLodDisp, wt_smallerLod, o.lodAlpha_worldXZUndisplaced_oceanDepth.w, seaLevelOffset, cascadeData0, o.seaLevelDerivs);
SampleSeaDepth(_LD_TexArray_SeaFloorDepth, uv_slice_smallerLodDisp, wt_smallerLod, seaDepth, seaLevelOffset, cascadeData0, o.seaLevelDerivs);

#if _SHADOWS_ON
// The minimum sampling weight is lower than others to fix shallow water colour popping.
Expand All @@ -428,7 +428,7 @@ Shader "Crest/Ocean"
{
const float3 uv_slice_biggerLodDisp = WorldToUV(o.worldPos.xz, cascadeData1, _LD_SliceIndex + 1);

SampleSeaDepth(_LD_TexArray_SeaFloorDepth, uv_slice_biggerLodDisp, wt_biggerLod, o.lodAlpha_worldXZUndisplaced_oceanDepth.w, seaLevelOffset, cascadeData1, o.seaLevelDerivs);
SampleSeaDepth(_LD_TexArray_SeaFloorDepth, uv_slice_biggerLodDisp, wt_biggerLod, seaDepth, seaLevelOffset, cascadeData1, o.seaLevelDerivs);

#if _SHADOWS_ON
// The minimum sampling weight is lower than others to fix shallow water colour popping.
Expand Down Expand Up @@ -526,10 +526,6 @@ Shader "Crest/Ocean"
half3 screenPos = input.screenPosXYW;
half2 uvDepth = screenPos.xy / screenPos.z;

#if _CLIPUNDERTERRAIN_ON
clip(input.lodAlpha_worldXZUndisplaced_oceanDepth.w + 2.0);
#endif

half3 view = normalize(_WorldSpaceCameraPos - input.worldPos);

// water surface depth, and underlying scene opaque surface depth
Expand Down Expand Up @@ -563,6 +559,8 @@ Shader "Crest/Ocean"
#if _ALBEDO_ON
half4 albedo = 0.0;
#endif

float seaDepth = 0.0;
if (wt_smallerLod > 0.001)
{
const float3 uv_slice_smallerLod = WorldToUV(positionXZWSUndisplaced, cascadeData0, _LD_SliceIndex);
Expand All @@ -575,6 +573,10 @@ Shader "Crest/Ocean"
#if _ALBEDO_ON
SampleAlbedo(_LD_TexArray_Albedo, uv_slice_smallerLod, wt_smallerLod, albedo);
#endif

#if defined(_SUBSURFACESHALLOWCOLOUR_ON) || defined(_CLIPUNDERTERRAIN_ON)
SampleSeaDepth(_LD_TexArray_SeaFloorDepth, uv_slice_smallerLod, wt_smallerLod, seaDepth);
#endif
}
if (wt_biggerLod > 0.001)
{
Expand All @@ -588,8 +590,24 @@ Shader "Crest/Ocean"
#if _ALBEDO_ON
SampleAlbedo(_LD_TexArray_Albedo, uv_slice_biggerLod, wt_biggerLod, albedo);
#endif

#if defined(_SUBSURFACESHALLOWCOLOUR_ON) || defined(_CLIPUNDERTERRAIN_ON)
SampleSeaDepth(_LD_TexArray_SeaFloorDepth, uv_slice_biggerLod, wt_biggerLod, seaDepth);
#endif
}

#if _SUBSURFACESHALLOWCOLOUR_ON
seaDepth = min(_SubSurfaceDepthMax, seaDepth);
if (_LD_SliceIndex == ((uint)_SliceCount - 1))
{
seaDepth = lerp(_SubSurfaceDepthMax, seaDepth, wt_smallerLod);
}
#endif

#if _CLIPUNDERTERRAIN_ON
clip(seaDepth + 2.0);
#endif

#if _SUBSURFACESCATTERING_ON
// Extents need the default SSS to avoid popping and not being noticeably different.
if (_LD_SliceIndex == ((uint)_SliceCount - 1))
Expand Down Expand Up @@ -668,7 +686,7 @@ Shader "Crest/Ocean"
// Compute color of ocean - in-scattered light + refracted scene
half3 scatterCol = ScatterColour
(
input.lodAlpha_worldXZUndisplaced_oceanDepth.w,
seaDepth,
shadow.x,
sss,
view,
Expand Down Expand Up @@ -752,7 +770,7 @@ Shader "Crest/Ocean"
// global shadow value.
scatterCol = ScatterColour
(
input.lodAlpha_worldXZUndisplaced_oceanDepth.w,
seaDepth,
UnderwaterShadowSSS(_WorldSpaceCameraPos.xz),
sss,
view,
Expand Down
3 changes: 2 additions & 1 deletion crest/Assets/Crest/Crest/Shaders/OceanConstants.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

// NOTE: Must match k_DepthBaseline in LodDataMgrSeaFloorDepth.cs.
// Bias ocean floor depth so that default (0) values in texture are not interpreted as shallow and generating foam everywhere
#define CREST_OCEAN_DEPTH_BASELINE 1000.0
#define CREST_OCEAN_DEPTH_BASELINE 1.#INF
#define CREST_MAXIMUM_ATTENUATION_DEPTH 1000.0

// Soft shadows is red, hard shadows is green.
#define CREST_SHADOW_INDEX_SOFT 0
Expand Down
7 changes: 3 additions & 4 deletions crest/Assets/Crest/Crest/Shaders/OceanHelpersNew.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,20 @@ void SampleSeaDepth(in Texture2DArray i_oceanDepthSampler, in float3 i_uv_slice,
{
const half2 terrainHeight_seaLevelOffset = i_oceanDepthSampler.SampleLevel(LODData_linear_clamp_sampler, i_uv_slice.xyz, 0.0).xy;
const half waterDepth = _OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y;
io_oceanDepth += i_wt * (waterDepth - CREST_OCEAN_DEPTH_BASELINE);
io_oceanDepth += i_wt * waterDepth;
}

void SampleSingleSeaDepth(Texture2DArray i_oceanDepthSampler, float3 i_uv_slice, inout half io_oceanDepth, inout half io_seaLevelOffset)
{
const half2 terrainHeight_seaLevelOffset = i_oceanDepthSampler.SampleLevel(LODData_linear_clamp_sampler, i_uv_slice, 0.0).xy;
const half waterDepth = _OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y;
io_oceanDepth = waterDepth - CREST_OCEAN_DEPTH_BASELINE;
io_oceanDepth = _OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y;
io_seaLevelOffset = terrainHeight_seaLevelOffset.y;
}

void SampleSeaDepth(in Texture2DArray i_oceanDepthSampler, in float3 i_uv_slice, in float i_wt, inout half io_oceanDepth, inout half io_seaLevelOffset, const CascadeParams i_cascadeParams, inout float2 io_seaLevelDerivs)
{
const half2 terrainHeight_seaLevelOffset = i_oceanDepthSampler.SampleLevel( LODData_linear_clamp_sampler, i_uv_slice, 0.0 ).xy;
io_oceanDepth += i_wt * (_OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y - CREST_OCEAN_DEPTH_BASELINE);
io_oceanDepth += i_wt * (_OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y);
io_seaLevelOffset += i_wt * terrainHeight_seaLevelOffset.y;

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Shader "Crest/Inputs/Shape Waves/Sample Spectrum"
const half depth = _OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y;
// Attenuate if depth is less than half of the average wavelength.
half weight = saturate(2.0 * depth / _AverageWavelength);
if (_MaximumAttenuationDepth < CREST_OCEAN_DEPTH_BASELINE)
if (_MaximumAttenuationDepth < CREST_MAXIMUM_ATTENUATION_DEPTH)
{
weight = lerp(weight, 1.0, saturate(depth / _MaximumAttenuationDepth));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Shader "Hidden/Crest/Inputs/Animated Waves/Gerstner Global"
_LD_TexArray_SeaFloorDepth.SampleLevel(LODData_linear_clamp_sampler, float3(input.uv_uvWaves.xy, _LD_SliceIndex), 0.0).xy;
const half depth = _OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y;
half depth_wt = saturate(2.0 * depth / _AverageWavelength);
if (_MaximumAttenuationDepth < CREST_OCEAN_DEPTH_BASELINE)
if (_MaximumAttenuationDepth < CREST_MAXIMUM_ATTENUATION_DEPTH)
{
depth_wt = lerp(depth_wt, 1.0, saturate(depth / _MaximumAttenuationDepth));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Shader "Crest/Inputs/Animated Waves/Gerstner Geometry"
const half2 terrainHeight_seaLevelOffset = _LD_TexArray_SeaFloorDepth.SampleLevel(LODData_linear_clamp_sampler, input.uv_slice, 0.0).xy;
const half depth = _OceanCenterPosWorld.y - terrainHeight_seaLevelOffset.x + terrainHeight_seaLevelOffset.y;
half depth_wt = saturate(2.0 * depth / _AverageWavelength);
if (_MaximumAttenuationDepth < CREST_OCEAN_DEPTH_BASELINE)
if (_MaximumAttenuationDepth < CREST_MAXIMUM_ATTENUATION_DEPTH)
{
depth_wt = lerp(depth_wt, 1.0, saturate(depth / _MaximumAttenuationDepth));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Shader "Crest/Underwater Curtain"
const half shadow = 1.0;
const half sss = 0.0;

half seaFloorDepth = CREST_OCEAN_DEPTH_BASELINE;
half seaFloorDepth = 0.0;
#if _SUBSURFACESHALLOWCOLOUR_ON
{
// compute scatter colour from cam pos. two scenarios this can be called:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ half3 ApplyUnderwaterEffect
}
#endif // _SHADOWS_ON

half seaFloorDepth = CREST_OCEAN_DEPTH_BASELINE;
half seaFloorDepth = 0.0;
#if _SUBSURFACESHALLOWCOLOUR_ON
{
// compute scatter colour from cam pos. two scenarios this can be called:
Expand Down

0 comments on commit 3a2cac1

Please sign in to comment.