修改水

This commit is contained in:
2026-01-01 22:00:33 +08:00
parent 040a222bd6
commit 9ceffccd39
1800 changed files with 103929 additions and 139495 deletions

View File

@@ -0,0 +1,151 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#ifndef CREST_UNDERWATER_MASK_SHARED_INCLUDED
#define CREST_UNDERWATER_MASK_SHARED_INCLUDED
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl"
#if (CREST_PORTALS != 0)
#include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Library/Portals.hlsl"
#endif
// Variable mask for when fog is applied before transparent pass and water tile might be culled.
half _Crest_MaskBelowSurface;
m_CrestNameSpace
struct Attributes
{
// The old unity macros require this name and type.
float4 vertex : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings Vertex(Attributes v)
{
// This will work for all pipelines.
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
const Cascade cascade0 = Cascade::Make(_Crest_LodIndex);
const Cascade cascade1 = Cascade::Make(_Crest_LodIndex + 1);
float3 worldPos = mul(UNITY_MATRIX_M, float4(v.vertex.xyz, 1.0)).xyz;
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
worldPos.xz += _WorldSpaceCameraPos.xz;
#endif
// Vertex snapping and lod transition
float lodAlpha;
SnapAndTransitionVertLayout(_Crest_ChunkMeshScaleAlpha, cascade0, _Crest_ChunkGeometryGridWidth, worldPos, lodAlpha);
{
// Scale up by small "epsilon" to solve numerical issues. Expand slightly about tile center.
// :WaterGridPrecisionErrors
float2 tileCenterXZ = UNITY_MATRIX_M._m03_m23;
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
tileCenterXZ += _WorldSpaceCameraPos.xz;
#endif
const float2 cameraPositionXZ = abs(_WorldSpaceCameraPos.xz);
// Scale "epsilon" by distance from zero. There is an issue where overlaps can cause SV_IsFrontFace
// to be flipped (needs to be investigated). Gaps look bad from above surface, and overlaps look bad
// from below surface. We want to close gaps without introducing overlaps. A fixed "epsilon" will
// either not solve gaps at large distances or introduce too many overlaps at small distances. Even
// with scaling, there are still unsolvable overlaps underwater (especially at large distances).
// 100,000 (0.00001) is the maximum position before Unity warns the user of precision issues.
worldPos.xz = lerp(tileCenterXZ, worldPos.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001));
}
// Calculate sample weights. params.z allows shape to be faded out (used on last lod to support pop-less scale transitions)
const float wt_smallerLod = (1.0 - lodAlpha) * cascade0._Weight;
const float wt_biggerLod = (1.0 - wt_smallerLod) * cascade1._Weight;
// Sample displacement textures, add results to current world pos / normal / foam
const float2 positionWS_XZ_before = worldPos.xz;
// Data that needs to be sampled at the undisplaced position
if (wt_smallerLod > m_CrestSampleLodThreshold)
{
Cascade::MakeAnimatedWaves(_Crest_LodIndex).SampleDisplacement(positionWS_XZ_before, wt_smallerLod, worldPos);
}
if (wt_biggerLod > m_CrestSampleLodThreshold)
{
Cascade::MakeAnimatedWaves(_Crest_LodIndex + 1).SampleDisplacement(positionWS_XZ_before, wt_biggerLod, worldPos);
}
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
worldPos.xz -= _WorldSpaceCameraPos.xz;
#endif
output.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
return output;
}
half4 Fragment(const Varyings input, const bool i_isFrontFace)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
half4 result = 0.0;
#if (CREST_PORTALS != 0)
#if !d_Tunnel
bool masked = false;
if (m_CrestPortal)
{
masked = ApplyVolumeToWaterMask(input.positionCS);
}
#endif
#endif
if (IsUnderwater(i_isFrontFace, g_Crest_ForceUnderwater))
{
result = (half4)_Crest_MaskBelowSurface;
}
else
{
result = (half4)CREST_MASK_ABOVE_SURFACE;
}
#if (CREST_PORTALS != 0)
#if d_Tunnel
const float rawFrontFaceZ = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeFrontFaceTexture, input.positionCS.xy);
const float rawBackFaceZ = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, input.positionCS.xy);
if (rawFrontFaceZ <= 0.0 && rawBackFaceZ > 0.0)
{
result = (half4)CREST_MASK_ABOVE_SURFACE;
}
#else
if (m_CrestPortal)
{
result *= masked ? 2 : 1;
}
#endif
#endif
return result;
}
m_CrestNameSpaceEnd
m_CrestVertex
m_CrestFragmentWithFrontFace(half4)
#endif // CREST_UNDERWATER_MASK_SHARED_INCLUDED

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b891a37e4cd634b03888a64e8965920b
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,253 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
Shader "Hidden/Crest/Underwater/Water Surface Mask"
{
SubShader
{
PackageRequirements
{
"com.unity.render-pipelines.high-definition"
}
Tags { "RenderPipeline"="HDRenderPipeline" }
Pass
{
Name "Water Surface Mask"
// We always disable culling when rendering water mask, as we only
// use it for underwater rendering features.
Cull Off
Stencil
{
Ref [_StencilRef]
Comp [_Crest_StencilComparison]
}
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
// for VFACE
#pragma target 3.0
#pragma multi_compile_local __ d_Tunnel
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl"
ENDHLSL
}
Pass
{
Name "Water Surface Mask (Depth Only)"
Cull Off
ColorMask 0
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
// for VFACE
#pragma target 3.0
#define m_Discard discard
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl"
ENDHLSL
}
Pass
{
Name "Water Horizon Mask"
Cull Off
ZWrite Off
// Horizon must be rendered first or it will overwrite the mask with incorrect values. ZTest not needed.
ZTest Always
Stencil
{
Ref [_StencilRef]
Comp [_Crest_StencilComparison]
}
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl"
ENDHLSL
}
}
SubShader
{
PackageRequirements
{
"com.unity.render-pipelines.universal"
}
Tags { "RenderPipeline"="UniversalPipeline" }
Pass
{
Name "Water Surface Mask"
// We always disable culling when rendering water mask, as we only
// use it for underwater rendering features.
Cull Off
Stencil
{
Ref [_StencilRef]
Comp [_Crest_StencilComparison]
}
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
// for VFACE
#pragma target 3.0
#pragma multi_compile_local __ d_Tunnel
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl"
ENDHLSL
}
Pass
{
Name "Water Surface Mask (Depth Only)"
Cull Off
ColorMask 0
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
// for VFACE
#pragma target 3.0
#define m_Discard discard
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl"
ENDHLSL
}
Pass
{
Name "Water Horizon Mask"
Cull Off
ZWrite Off
// Horizon must be rendered first or it will overwrite the mask with incorrect values. ZTest not needed.
ZTest Always
Stencil
{
Ref [_StencilRef]
Comp [_Crest_StencilComparison]
}
HLSLPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl"
ENDHLSL
}
}
SubShader
{
Pass
{
Name "Water Surface Mask"
// We always disable culling when rendering water mask, as we only
// use it for underwater rendering features.
Cull Off
Stencil
{
Ref [_StencilRef]
Comp [_Crest_StencilComparison]
}
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
// for VFACE
#pragma target 3.0
#pragma multi_compile_local __ d_Tunnel
#include "UnityCG.cginc"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl"
ENDCG
}
Pass
{
Name "Water Surface Mask (Depth Only)"
Cull Off
ColorMask 0
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
// for VFACE
#pragma target 3.0
#define m_Discard discard
#include "UnityCG.cginc"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Mask.hlsl"
ENDCG
}
Pass
{
Name "Water Horizon Mask"
Cull Off
ZWrite Off
// Horizon must be rendered first or it will overwrite the mask with incorrect values. ZTest not needed.
ZTest Always
Stencil
{
Ref [_StencilRef]
Comp [_Crest_StencilComparison]
}
CGPROGRAM
#pragma vertex Vertex
#pragma fragment Fragment
#include "UnityCG.cginc"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/MaskHorizon.hlsl"
ENDCG
}
}
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: edb653e62cc924b99b0a1086ffb39be7
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,61 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
// Checks both orthogonal and diagonal pixels to fill artefacts in the mask. If checked pixels are all the same then it
// assumes that the current pixel should also be the same and fixes it.
#pragma kernel FillMaskArtefacts
// Built-in will not handle this for us unlike other RPs.
#pragma multi_compile __ STEREO_INSTANCING_ON
#include "UnityCG.cginc"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Core.hlsl"
RW_TEXTURE2D_X(float, _Crest_WaterMaskTexture);
[numthreads(8, 8, 1)]
void FillMaskArtefacts(const uint3 id : SV_DispatchThreadID)
{
UNITY_XR_ASSIGN_VIEW_INDEX(id.z);
const uint3 offset = uint3(1, -1, 0);
// Check orthogonal pixels.
{
const float4 pixels = float4
(
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.xz)],
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.yz)],
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.zy)],
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.zx)]
);
// If these pixels are all the same, then it is valid that this pixel also equals them.
if (pixels.x == pixels.y && pixels.y == pixels.z && pixels.z == pixels.w)
{
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy)] = pixels.x;
return;
}
}
// Check diagonal pixels.
{
const float4 pixels = float4
(
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.xx)],
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.yy)],
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.xy)],
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy + offset.yx)]
);
// If these pixels are all the same, then it is valid that this pixel also equals them.
if (pixels.x == pixels.y && pixels.y == pixels.z && pixels.z == pixels.w)
{
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy)] = pixels.x;
return;
}
}
_Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy)] = _Crest_WaterMaskTexture[COORD_TEXTURE2D_X(id.xy)];
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 08549c36146ad4899a07193754b21ea2
ComputeShaderImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
// Renders the water horizon line into the mask.
#ifndef CREST_UNDERWATER_MASK_HORIZON_SHARED_INCLUDED
#define CREST_UNDERWATER_MASK_HORIZON_SHARED_INCLUDED
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl"
// Driven by scripting. It is a non-linear converted from a linear 0-1 value.
float _Crest_FarPlaneOffset;
struct Attributes
{
uint id : SV_VertexID;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings Vertex(Attributes input)
{
// This will work for all pipelines.
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
output.positionCS = GetFullScreenTriangleVertexPosition(input.id, _Crest_FarPlaneOffset);
output.uv = GetFullScreenTriangleTexCoord(input.id);
return output;
}
half4 Fragment(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float3 positionWS = ComputeWorldSpacePosition(input.uv, _Crest_FarPlaneOffset, UNITY_MATRIX_I_VP);
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionWS.y += _WorldSpaceCameraPos.y;
#endif
return (half4) positionWS.y > g_Crest_WaterCenter.y
? CREST_MASK_ABOVE_SURFACE
: CREST_MASK_BELOW_SURFACE;
}
#endif // CREST_UNDERWATER_MASK_HORIZON_SHARED_INCLUDED

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5f5a4cb92ecd4468e84893f8257be090
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,162 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/UnderwaterShared.hlsl"
#ifndef SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER
#define FoveatedRemapLinearToNonUniform(uv) uv
#endif
m_CrestNameSpace
struct Attributes
{
#if CREST_WATER_VOLUME
float3 positionOS : POSITION;
#else
uint id : SV_VertexID;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings Vertex(Attributes input)
{
Varyings output;
ZERO_INITIALIZE(Varyings, output);
UNITY_SETUP_INSTANCE_ID(input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
#if CREST_WATER_VOLUME
// Use actual geometry instead of full screen triangle.
output.positionCS = TransformObjectToHClip(input.positionOS);
#else
output.positionCS = GetFullScreenTriangleVertexPosition(input.id, UNITY_RAW_FAR_CLIP_VALUE);
#endif
return output;
}
half4 Fragment(Varyings input)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
uint2 positionSS = input.positionCS.xy;
float mask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, positionSS).x;
const float2 uv = FoveatedRemapLinearToNonUniform(positionSS / _ScreenSize.xy);
#if !_DEBUG_VISUALIZE_MASK
#if !d_Meniscus
// Preserve alpha channel.
if (mask > CREST_MASK_BELOW_SURFACE)
{
discard;
}
#endif
#endif
float rawDepth = LoadCameraDepth(positionSS);
half3 sceneColour = LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, positionSS).rgb;
const float rawMaskDepth = LOAD_TEXTURE2D_X(_Crest_WaterMaskDepthTexture, positionSS).x;
#if _DEBUG_VISUALIZE_STENCIL
return DebugRenderStencil(sceneColour);
#endif
bool isWaterSurface; bool isUnderwater; bool hasCaustics; bool hasMeniscus; float sceneZ; float meniscusRawDepth;
GetWaterSurfaceAndUnderwaterData(input.positionCS, positionSS, rawMaskDepth, mask, rawDepth, meniscusRawDepth, isWaterSurface, isUnderwater, hasCaustics, hasMeniscus, sceneZ);
float wt = 1.0;
if (hasMeniscus)
{
wt = ComputeMeniscusWeight(positionSS, mask, _Crest_HorizonNormal, sceneZ);
}
#if !_DEBUG_VISUALIZE_MASK
#if d_Meniscus
// Preserve alpha channel.
if (!isUnderwater && wt >= 1.0)
{
discard;
}
#endif
#endif
float fogDistance = sceneZ;
float meniscusDepth = 0.0;
#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN)
ApplyWaterVolumeToUnderwaterFogAndMeniscus(input.positionCS, meniscusRawDepth, fogDistance, meniscusDepth);
#endif
#if _DEBUG_VISUALIZE_MASK
return DebugRenderWaterMask(isWaterSurface, isUnderwater, mask, sceneColour);
#endif
if (isUnderwater)
{
float3 positionWS = ComputeWorldSpacePosition(uv, rawDepth, UNITY_MATRIX_I_VP);
const half3 view = GetWorldSpaceNormalizeViewDir(positionWS);
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionWS += _WorldSpaceCameraPos;
#endif
sceneColour = ApplyUnderwaterEffect(sceneColour, rawDepth, sceneZ, fogDistance, view, positionSS, positionWS, hasCaustics);
}
return half4(wt * sceneColour, 1.0);
}
half4 FragmentPlanarReflections(Varyings input)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
const uint2 positionSS = input.positionCS.xy;
float depth = LoadCameraDepth(positionSS);
// TODO: Do something nicer. Could zero alpha if scene depth is above threshold.
if (depth == 0.0)
{
return half4(_Crest_Scattering.xyz, 1.0);
}
half3 color = LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, positionSS).rgb;
// Calculate position and account for possible NaNs discovered during testing.
float3 positionWS;
{
float4 positionCS = ComputeClipSpacePosition(positionSS / _ScreenSize.xy, depth);
float4 hpositionWS = mul(UNITY_MATRIX_I_VP, positionCS);
// w is sometimes zero when using oblique projection.
// Zero is better than NaN.
positionWS = hpositionWS.w > 0.0 ? hpositionWS.xyz / hpositionWS.w : 0.0;
}
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionWS += _WorldSpaceCameraPos;
#endif
const half3 view = GetWorldSpaceNormalizeViewDir(positionWS);
const bool hasCaustics = depth > 0.0;
color = ApplyUnderwaterEffect(color, depth, 0.0, 0.0, view, positionSS, positionWS, hasCaustics);
return half4(color, 1.0);
}
m_CrestNameSpaceEnd
m_CrestVertex
m_CrestFragment(half4)
half4 FragmentPlanarReflections(m_Crest::Varyings input) : SV_Target
{
return m_Crest::FragmentPlanarReflections(input);
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2636ae353ea154204861c022e68003df
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,735 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
Shader "Crest/Underwater"
{
Properties
{
_Crest_ExtinctionMultiplier("Density Factor", Range(0, 1)) = 1
_Crest_SunBoost("Sun Boost", Range(0, 100)) = 2
_Crest_OutScatteringFactor("Out-Scattering Factor", Range(0, 1)) = 0.2
_Crest_OutScatteringExtinctionFactor("Out-Scattering Extinction Factor", Range(0, 1)) = 0.2
[Space(10)]
[Toggle(d_Dithering)]
_Crest_DitheringEnabled("Dithering", Integer) = 1
_Crest_DitheringIntensity("Dithering Intensity", Range(0, 10)) = 1
[Space(10)]
[Toggle(d_Meniscus)]
_Crest_MeniscusEnabled("Meniscus", Integer) = 1
[Header(Advanced)]
[Space(6)]
// This adds an offset to the cascade index when sampling water data, in effect smoothing/blurring it. Default
// to shifting the maximum amount (shift from lod 0 to penultimate lod - dont use last lod as it cross-fades
// data in/out), as more filtering was better in testing.
[CrestIntegerRange]
_Crest_DataSliceOffset("Filter Water Data", Integer) = 13
[HideInInspector]
_Crest_Version("Version", Integer) = 0
[Header(Copied From Water Surface)]
[Space(6)]
[PerRendererData] _Crest_AbsorptionColor("Absorption Color", Color) = (0.3416268, 0.6954546, 0.85, 0.1019608)
[PerRendererData] _Crest_Scattering("Scattering", Color) = (0, 0.09803922, 0.2, 1)
[PerRendererData] _Crest_Anisotropy("Anisotropy", Range(0, 1)) = 0.5
[PerRendererData] _Crest_DirectTerm("Direct Term", Float) = 1
[PerRendererData] _Crest_AmbientTerm("Ambient Term", Float) = 1
[PerRendererData] _Crest_ShadowsAffectsAmbientFactor("Shadows Affects Ambient Factor", Float) = 0.5
// Caustics
[PerRendererData] [ToggleUI] _Crest_CausticsEnabled("Caustics Enabled", Float) = 1
[PerRendererData] [NoScaleOffset] _Crest_CausticsTexture("Caustics Texture", 2D) = "black" {}
[PerRendererData] _Crest_CausticsStrength("Caustics Strength", Range(0, 10)) = 3.2
[PerRendererData] _Crest_CausticsTextureScale("Caustics Scale", Range(0.01, 100)) = 50
[PerRendererData] _Crest_CausticsScrollSpeed("Caustics Scroll Speed", Range(0, 10)) = 1
[PerRendererData] _Crest_CausticsTextureAverage("Caustics Grey Point", Range(0, 1)) = 0.07
[PerRendererData] _Crest_CausticsFocalDepth("Caustics Focal Depth", Range(0, 25)) = 2
[PerRendererData] _Crest_CausticsDepthOfField("Caustics Depth of Field", Range(0.01, 10)) = 6
[PerRendererData] [NoScaleOffset] _Crest_CausticsDistortionTexture("Caustics Distortion Texture", 2D) = "grey" {}
[PerRendererData] _Crest_CausticsDistortionStrength("Caustics Distortion Strength", Range(0, 0.25)) = 0.16
[PerRendererData] _Crest_CausticsDistortionScale("Caustics Distortion Scale", Range(0.01, 1000)) = 250
[PerRendererData] _Crest_CausticsMotionBlur("Caustics Motion Blur", Range(0, 10)) = 1
[PerRendererData] [Toggle] CREST_FLOW("Flow Enabled", Float) = 0
}
HLSLINCLUDE
#pragma vertex Vertex
// #pragma enable_d3d11_debug_symbols
// Also on the water shader.
#pragma multi_compile_local_fragment __ CREST_FLOW_ON
#pragma shader_feature_local_fragment __ d_Meniscus
#pragma shader_feature_local_fragment __ d_Dithering
#pragma multi_compile_local_fragment __ _DEBUG_VISUALIZE_MASK
#pragma multi_compile_local_fragment __ _DEBUG_VISUALIZE_STENCIL
ENDHLSL
SubShader
{
PackageRequirements
{
"com.unity.render-pipelines.high-definition"
}
Tags { "RenderPipeline"="HDRenderPipeline" }
ZWrite Off
Blend Off
Pass
{
Name "Full Screen"
Cull Off
ZTest Always
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
// Both "__" and "_FULL_SCREEN_EFFECT" are fullscreen triangles. The latter only denotes an optimisation of
// whether to skip the horizon calculation.
#pragma multi_compile_local_fragment __ _FULL_SCREEN_EFFECT
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
Name "Reflection"
Cull Off
ZTest Always
HLSLPROGRAM
#define CREST_REFLECTION 1
#include_with_pragmas "UnderwaterHDRP.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment FragmentPlanarReflections
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (2D)"
Cull Back
ZTest LEqual
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (3D)"
Cull Back
ZTest LEqual
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_HAS_BACKFACE 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (Fly-Through)"
Cull Back
ZTest LEqual
Stencil
{
// Must match k_StencilValueVolume in:
// Portals.cs
Ref 5
Comp Always
Pass Replace
ZFail IncrSat
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_HAS_BACKFACE 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
// Back face will only render if view is within the volume and there is no scene in front. It will only add
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// fog to the back face (and in effect anything behind it). No caustics.
Name "Volume: Back Face"
Cull Front
ZTest LEqual
Stencil
{
// Must match k_StencilValueVolume in:
// Portals.cs
Ref 5
Comp NotEqual
Pass Replace
ZFail IncrSat
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_BACK_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// When inside a volume, this pass will render to the scene within the volume.
Name "Volume: Scene (Full Screen)"
Cull Back
ZTest Always
Stencil
{
// We want to render over the scene that's inside the volume, but not over already fogged areas. It will
// handle all of the scene within the geometry once the camera is within the volume.
// 0 = Outside of geometry as neither face passes have touched it.
// 1 = Only back face z failed which means scene is in front of back face but not front face.
// 2 = Both front and back face z failed which means outside geometry.
Ref 1
Comp Equal
Pass Replace
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
#define CREST_WATER_VOLUME_FULLSCREEN 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
Name "Volume: Negative (Full Screen)"
Cull Off
ZTest Always
HLSLPROGRAM
#include_with_pragmas "UnderwaterHDRP.hlsl"
#define CREST_WATER_VOLUME_FULLSCREEN 1
#define CREST_WATER_VOLUME_NEGATIVE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
}
Subshader
{
PackageRequirements
{
"com.unity.render-pipelines.universal"
}
Tags { "RenderPipeline"="UniversalPipeline" }
ZWrite Off
Pass
{
Name "Full Screen"
Cull Off
ZTest Always
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
// Both "__" and "_FULL_SCREEN_EFFECT" are fullscreen triangles. The latter only denotes an optimisation of
// whether to skip the horizon calculation.
#pragma multi_compile_local_fragment __ _FULL_SCREEN_EFFECT
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
Name "Reflection"
Cull Off
ZTest Always
HLSLPROGRAM
#define CREST_REFLECTION 1
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment FragmentPlanarReflections
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (2D)"
Cull Back
ZTest LEqual
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (3D)"
Cull Back
ZTest LEqual
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_HAS_BACKFACE 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (Fly-Through)"
Cull Back
ZTest LEqual
Stencil
{
// Must match k_StencilValueVolume in:
// Portals.cs
Ref 5
Comp Always
Pass Replace
ZFail IncrSat
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_HAS_BACKFACE 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
// Back face will only render if view is within the volume and there is no scene in front. It will only add
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// fog to the back face (and in effect anything behind it). No caustics.
Name "Volume: Back Face"
Cull Front
ZTest LEqual
Stencil
{
// Must match k_StencilValueVolume in:
// Portals.cs
Ref 5
Comp NotEqual
Pass Replace
ZFail IncrSat
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_BACK_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// When inside a volume, this pass will render to the scene within the volume.
Name "Volume: Scene (Full Screen)"
Cull Back
ZTest Always
Stencil
{
// We want to render over the scene that's inside the volume, but not over already fogged areas. It will
// handle all of the scene within the geometry once the camera is within the volume.
// 0 = Outside of geometry as neither face passes have touched it.
// 1 = Only back face z failed which means scene is in front of back face but not front face.
// 2 = Both front and back face z failed which means outside geometry.
Ref 1
Comp Equal
Pass Replace
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#define CREST_WATER_VOLUME_FULLSCREEN 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
Name "Volume: Negative (Full Screen)"
Cull Off
ZTest Always
HLSLPROGRAM
#include_with_pragmas "UnderwaterURP.hlsl"
#include_with_pragmas "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRenderingKeywords.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/FoveatedRendering.hlsl"
#define CREST_WATER_VOLUME_FULLSCREEN 1
#define CREST_WATER_VOLUME_NEGATIVE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
}
SubShader
{
ZWrite Off
Pass
{
Name "Full Screen"
Cull Off
ZTest Always
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
// Both "__" and "_FULL_SCREEN_EFFECT" are fullscreen triangles. The latter only denotes an optimisation of
// whether to skip the horizon calculation.
#pragma multi_compile_local_fragment __ _FULL_SCREEN_EFFECT
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
Name "Reflection"
Cull Off
ZTest Always
HLSLPROGRAM
#define CREST_REFLECTION 1
#include_with_pragmas "UnderwaterBIRP.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment FragmentPlanarReflections
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (2D)"
Cull Back
ZTest LEqual
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (3D)"
Cull Back
ZTest LEqual
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_HAS_BACKFACE 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// Only adds fog to the front face and in effect anything behind it.
Name "Volume: Front Face (Fly-Through)"
Cull Back
ZTest LEqual
Stencil
{
// Must match k_StencilValueVolume in:
// Portals.cs
Ref 5
Comp Always
Pass Replace
ZFail IncrSat
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_HAS_BACKFACE 1
#define CREST_WATER_VOLUME_FRONT_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
// Back face will only render if view is within the volume and there is no scene in front. It will only add
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// fog to the back face (and in effect anything behind it). No caustics.
Name "Volume: Back Face"
Cull Front
ZTest LEqual
Stencil
{
// Must match k_StencilValueVolume in:
// Portals.cs
Ref 5
Comp NotEqual
Pass Replace
ZFail IncrSat
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
#define CREST_WATER_VOLUME 1
#define CREST_WATER_VOLUME_BACK_FACE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
// When inside a volume, this pass will render to the scene within the volume.
Name "Volume: Scene (Full Screen)"
Cull Back
ZTest Always
Stencil
{
// We want to render over the scene that's inside the volume, but not over already fogged areas. It will
// handle all of the scene within the geometry once the camera is within the volume.
// 0 = Outside of geometry as neither face passes have touched it.
// 1 = Only back face z failed which means scene is in front of back face but not front face.
// 2 = Both front and back face z failed which means outside geometry.
Ref 1
Comp Equal
Pass Replace
}
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
#define CREST_WATER_VOLUME_FULLSCREEN 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
Pass
{
PackageRequirements
{
"com.waveharmonic.crest.portals"
}
Name "Volume: Negative (Full Screen)"
Cull Off
ZTest Always
HLSLPROGRAM
#include_with_pragmas "UnderwaterBIRP.hlsl"
#define CREST_WATER_VOLUME_FULLSCREEN 1
#define CREST_WATER_VOLUME_NEGATIVE 1
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Underwater.hlsl"
#pragma fragment Fragment
ENDHLSL
}
}
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
}

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 034b985bd9c344992af148e26d2cdb24
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#define BUILTIN_TARGET_API 1
#define CREST_BIRP 1
#define CREST_SHADERGRAPH_CONSTANTS_H
#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Shim/Shims.hlsl"
#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/Editor/ShaderGraph/Includes/LegacySurfaceVertex.hlsl"
#include "Packages/com.unity.shadergraph/Editor/Generation/Targets/BuiltIn/ShaderLibrary/ShaderGraphFunctions.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Legacy/Common.hlsl"
TEXTURE2D_X(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);
m_CrestNameSpace
float LoadCameraDepth(uint2 pixelCoords)
{
return LOAD_TEXTURE2D_X(_CameraDepthTexture, pixelCoords).r;
}
m_CrestNameSpaceEnd

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 765d2ceee80af4bd5a637f79488a3433
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,18 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#pragma target 4.5
// Low appears good enough as it has filtering which is necessary when close to a shadow.
#define SHADOW_LOW
#define AREA_SHADOW_LOW
// In shared SG code we target the forward pass to avoid shader compilation errors.
#define CREST_HDRP 1
#define SHADERPASS SHADERPASS_FORWARD
#define CREST_HDRP_FORWARD_PASS 1
#define CREST_SHADERGRAPH_CONSTANTS_H
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b3db686f3a7746698c6193fcdc22ff2
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,485 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#ifndef CREST_UNDERWATER_EFFECT_SHARED_INCLUDED
#define CREST_UNDERWATER_EFFECT_SHARED_INCLUDED
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Settings.Crest.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Depth.hlsl"
#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN)
#include "Packages/com.waveharmonic.crest.portals/Runtime/Shaders/Library/Portals.hlsl"
#endif
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Texture.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Lighting.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/VolumeLighting.hlsl"
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Caustics.hlsl"
// These are set via call to CopyPropertiesFromMaterial() and must have the same
// names as the surface material parameters.
CBUFFER_START(CrestPerMaterial)
//
// Surface Shared
//
half4 _Crest_Absorption;
half4 _Crest_Scattering;
half _Crest_Anisotropy;
bool _Crest_CausticsEnabled;
float _Crest_CausticsTextureScale;
float _Crest_CausticsScrollSpeed;
float _Crest_CausticsTextureAverage;
float _Crest_CausticsStrength;
float _Crest_CausticsFocalDepth;
float _Crest_CausticsDepthOfField;
float _Crest_CausticsDistortionStrength;
float _Crest_CausticsDistortionScale;
half _Crest_CausticsMotionBlur;
float4 _Crest_CausticsTexture_TexelSize;
float4 _Crest_CausticsDistortionTexture_TexelSize;
half _Crest_DirectTerm;
half _Crest_AmbientTerm;
half _Crest_ShadowsAffectsAmbientFactor;
//
// Volume Only
//
float2 _Crest_HorizonNormal;
// Out-scattering. Driven by the Water Renderer and Underwater Environmental Lighting.
float _Crest_VolumeExtinctionLength;
float _Crest_UnderwaterEnvironmentalLightingWeight;
// Also applied to transparent objects.
half _Crest_ExtinctionMultiplier;
half _Crest_SunBoost;
float _Crest_OutScatteringFactor;
float _Crest_OutScatteringExtinctionFactor;
half3 _Crest_AmbientLighting;
int _Crest_DataSliceOffset;
half _Crest_DitheringIntensity;
CBUFFER_END
TEXTURE2D_X(_Crest_WaterMaskTexture);
TEXTURE2D_X(_Crest_WaterMaskDepthTexture);
TEXTURE2D_X(_Crest_CameraColorTexture);
TEXTURE2D(_Crest_CausticsTexture);
SAMPLER(sampler_Crest_CausticsTexture);
TEXTURE2D(_Crest_CausticsDistortionTexture);
SAMPLER(sampler_Crest_CausticsDistortionTexture);
// NOTE: Cannot put this in namespace due to compiler bug. Fixed when using DXC.
static const m_Crest::TiledTexture _Crest_CausticsTiledTexture =
m_Crest::TiledTexture::Make(_Crest_CausticsTexture, sampler_Crest_CausticsTexture, _Crest_CausticsTexture_TexelSize, _Crest_CausticsTextureScale, _Crest_CausticsScrollSpeed);
static const m_Crest::TiledTexture _Crest_CausticsDistortionTiledTexture =
m_Crest::TiledTexture::Make(_Crest_CausticsDistortionTexture, sampler_Crest_CausticsDistortionTexture, _Crest_CausticsDistortionTexture_TexelSize, _Crest_CausticsDistortionScale, 1.0);
m_CrestNameSpace
float LinearToDeviceDepth(float linearDepth, float4 zBufferParam)
{
//linear = 1.0 / (zBufferParam.z * device + zBufferParam.w);
float device = (1.0 / linearDepth - zBufferParam.w) / zBufferParam.z;
return device;
}
#if d_Dithering
// Adapted from:
// https://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
float3 ScreenSpaceDither(const float2 i_ScreenPosition)
{
// Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR.
float3 dither = dot(float2(171.0, 231.0), i_ScreenPosition.xy);
dither.rgb = frac(dither.rgb / float3(103.0, 71.0, 97.0)) - float3(0.5, 0.5, 0.5);
return (dither.rgb / 255.0);
}
#endif
float4 DebugRenderWaterMask(const bool isWaterSurface, const bool isUnderwater, const float mask, const float3 sceneColour)
{
// Red: surface front face when above water
// Green: surface back face when below water
// Cyan: background when above water
// Magenta: background when below water
if (isWaterSurface)
{
return float4(sceneColour * float3(mask >= CREST_MASK_ABOVE_SURFACE, mask <= CREST_MASK_BELOW_SURFACE, 0.0), 1.0);
}
else
{
return float4(sceneColour * float3(isUnderwater * 0.5, (1.0 - isUnderwater) * 0.5, 1.0), 1.0);
}
}
float4 DebugRenderStencil(float3 sceneColour)
{
float3 stencil = 1.0;
#if CREST_WATER_VOLUME_FRONT_FACE
stencil = float3(1.0, 0.0, 0.0);
#elif CREST_WATER_VOLUME_BACK_FACE
stencil = float3(0.0, 1.0, 0.0);
#elif CREST_WATER_VOLUME_FULLSCREEN
stencil = float3(0.0, 0.0, 1.0);
#endif
return float4(sceneColour * stencil, 1.0);
}
float MeniscusSampleWaterMask(const float mask, const int2 positionSS, const float2 offset, const float magnitude, const float scale)
{
float2 uv = positionSS + offset * magnitude
#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN)
* scale
#endif
;
float newMask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, uv).r;
#if CREST_UNDERWATER_BEFORE_TRANSPARENT
// Normalize mask.
newMask = clamp(newMask, -1.0, 1.0);
#endif
#if CREST_WATER_VOLUME
// No mask means no underwater effect so ignore the value.
return (newMask == CREST_MASK_NONE ? mask : newMask);
#endif
return newMask;
}
half ComputeMeniscusWeight(const int2 positionSS, float mask, const float2 horizonNormal, const float meniscusDepth)
{
float weight = 1.0;
#if d_Meniscus
#if !_FULL_SCREEN_EFFECT
#if CREST_UNDERWATER_BEFORE_TRANSPARENT
// Normalize mask.
mask = clamp(mask, -1.0, 1.0);
#endif
// Render meniscus by checking the mask along the horizon normal which is flipped using the surface normal from
// mask. Adding the mask value will flip the UV when mask is below surface.
float2 offset = (float2)-mask * horizonNormal;
float multiplier = 0.9;
#if defined(CREST_WATER_VOLUME) || defined(CREST_WATER_VOLUME_FULLSCREEN)
// The meniscus at the boundary can be at a distance. We need to scale the offset as 1 pixel at a distance is much
// larger than 1 pixel up close.
const float scale = 1.0 - saturate(meniscusDepth / MENISCUS_MAXIMUM_DISTANCE);
// Exit early.
if (scale == 0.0)
{
return 1.0;
}
#else
// Dummy value.
const float scale = 0.0;
#endif
// Sample three pixels along the normal. If the sample is different than the current mask, apply meniscus.
// Offset must be added to positionSS as floats.
weight *= (MeniscusSampleWaterMask(mask, positionSS, offset, 1.0, scale) != mask) ? multiplier : 1.0;
weight *= (MeniscusSampleWaterMask(mask, positionSS, offset, 2.0, scale) != mask) ? multiplier : 1.0;
weight *= (MeniscusSampleWaterMask(mask, positionSS, offset, 3.0, scale) != mask) ? multiplier : 1.0;
#endif // _FULL_SCREEN_EFFECT
#endif // d_Meniscus
return weight;
}
void GetWaterSurfaceAndUnderwaterData
(
const float4 positionCS,
const int2 positionSS,
const float rawMaskDepth,
const float mask,
inout float rawDepth,
inout float rawMeniscusDepth,
inout bool isWaterSurface,
inout bool isUnderwater,
inout bool hasCaustics,
inout bool hasMeniscus,
inout float sceneZ
)
{
const float rawSceneDepth = rawDepth;
hasCaustics = rawDepth != 0.0;
isWaterSurface = false;
isUnderwater = mask <= CREST_MASK_BELOW_SURFACE;
hasMeniscus = true;
rawMeniscusDepth = positionCS.z;
#if defined(CREST_WATER_VOLUME_HAS_BACKFACE) || defined(CREST_WATER_VOLUME_BACK_FACE) || defined(CREST_WATER_VOLUME_NEGATIVE)
const float rawGeometryDepth =
#if CREST_WATER_VOLUME_HAS_BACKFACE
// 3D has a back face texture for the depth.
LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, positionSS);
#elif CREST_WATER_VOLUME_NEGATIVE
LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeFrontFaceTexture, positionSS);
#else
// Volume is rendered using the back face so that is the depth.
positionCS.z;
#endif // CREST_WATER_VOLUME_HAS_BACKFACE
;
if ((rawMaskDepth > 0.0 && rawMaskDepth <= rawSceneDepth) || (rawGeometryDepth > 0.0 && rawGeometryDepth <= rawSceneDepth))
{
hasMeniscus = false;
}
// Use backface depth if closest.
if (rawDepth < rawGeometryDepth)
{
// Cancels out caustics.
hasCaustics = false;
rawDepth = rawGeometryDepth;
}
#if CREST_WATER_VOLUME_NEGATIVE
rawMeniscusDepth = rawGeometryDepth;
if (rawGeometryDepth == 0.0)
{
const float rawBackFaceDepth = LOAD_DEPTH_TEXTURE_X(_Crest_WaterVolumeBackFaceTexture, positionSS);
// We are in the negative volume. Already handled by front face.
if (rawBackFaceDepth > 0.0)
{
if (rawBackFaceDepth <= rawSceneDepth)
{
hasMeniscus = false;
}
isUnderwater = false;
}
}
#endif // CREST_WATER_VOLUME_NEGATIVE
#endif // CREST_WATER_VOLUME
#if CREST_WATER_VOLUME_FRONT_FACE
// If negative volume, we keep the mask intact, and just mark it.
if (mask >= CREST_MASK_ABOVE_SURFACE_KEPT)
{
isUnderwater = true;
}
else if (mask <= CREST_MASK_BELOW_SURFACE_KEPT)
{
isUnderwater = false;
}
#endif
// Merge water depth with scene depth.
if (rawDepth < rawMaskDepth)
{
#if CREST_UNDERWATER_BEFORE_TRANSPARENT
// Apply fog to culled tiles otherwise there will be no fog as water shader can only fog enabled tiles. And
// only apply fog to culled tiles otherwise it will be fogged twice (second by water shader).
isUnderwater = mask <= CREST_MASK_BELOW_SURFACE_CULLED;
#endif
isWaterSurface = true;
hasCaustics = false;
rawDepth = rawMaskDepth;
}
sceneZ = Utility::CrestLinearEyeDepth(rawDepth);
}
void ApplyWaterVolumeToUnderwaterFogAndMeniscus(float4 positionCS, const float meniscusRawDepth, inout float fogDistance, inout float meniscusDepth)
{
#if CREST_WATER_VOLUME_FRONT_FACE
float depth = Utility::CrestLinearEyeDepth(positionCS.z);
// Meniscus is rendered at the boundary so use the geometry z.
meniscusDepth = depth;
fogDistance -= depth;
#else
float depth = Utility::CrestLinearEyeDepth(meniscusRawDepth);
// Meniscus is rendered at the boundary so use the geometry z.
meniscusDepth = depth;
#endif
}
half3 ApplyUnderwaterEffect(
half3 sceneColour,
const float rawDepth,
const float sceneZ,
const float fogDistance,
const half3 view,
const uint2 i_positionSS,
const float3 i_positionWS,
const bool hasCaustics
) {
const bool isUnderwater = true;
float3 lightDirection; float3 lightColor;
PrimaryLight(i_positionWS, lightColor, lightDirection);
// Uniform effect calculated from camera position.
half3 volumeLight = 0.0;
half3 volumeOpacity = 1.0;
{
half3 absorption = _Crest_Absorption.xyz;
half3 scattering = _Crest_Scattering.xyz;
// We sample shadows at the camera position. Pass a user defined slice offset for smoothing out detail.
// Offset slice so that we dont get high freq detail. But never use last lod as this has crossfading.
int sliceIndex = clamp(_Crest_DataSliceOffset, 0, g_Crest_LodCount - 2);
if (g_Crest_SampleAbsorptionSimulation) absorption = Cascade::MakeAbsorption(sliceIndex).Sample(_WorldSpaceCameraPos.xz).xyz;
if (g_Crest_SampleScatteringSimulation) scattering = Cascade::MakeScattering(sliceIndex).Sample(_WorldSpaceCameraPos.xz).xyz;
const float waterLevel = g_Crest_WaterCenter.y + Cascade::MakeAnimatedWaves(sliceIndex).Sample(_WorldSpaceCameraPos.xz).w;
half shadow = 1.0;
{
// #if CREST_SHADOWS_ON
// Camera should be at center of LOD system so no need for blending (alpha, weights, etc). This might not be
// the case if there is large horizontal displacement, but the _Crest_DataSliceOffset should help by setting a
// large enough slice as minimum.
half2 shadowSoftHard = Cascade::MakeShadow(sliceIndex).SampleShadow(_WorldSpaceCameraPos.xz);
// Soft in red, hard in green. But hard not computed in HDRP.
shadow = 1.0 - shadowSoftHard.x;
// #endif
}
half3 ambientLighting = _Crest_AmbientLighting;
#if CREST_HDRP
ApplyIndirectLightingMultiplier(ambientLighting);
#endif
// Out-Scattering Term.
{
float3 positionWS = i_positionWS;
#if !CREST_REFLECTION
// Project point onto sphere at the extinction length.
float3 toSphere = -view * _Crest_VolumeExtinctionLength * _Crest_OutScatteringExtinctionFactor;
float3 toScene = i_positionWS - _WorldSpaceCameraPos.xyz;
positionWS = _WorldSpaceCameraPos.xyz + toSphere;
// Get closest position.
positionWS = dot(toScene, toScene) < dot(toSphere, toSphere) ? i_positionWS : positionWS;
#endif
// Account for average extinction of light as it travels down through volume. Assume flat water as anything
// else would be expensive.
half3 extinction = (absorption + scattering) * _Crest_ExtinctionMultiplier;
float waterDepth = max(0.0, (waterLevel - positionWS.y));
#if CREST_REFLECTION
waterDepth *= 2.0;
if (rawDepth == 0.0) waterDepth = _Crest_VolumeExtinctionLength;
#else
// Full strength seems too extreme. Third strength seems reasonable.
waterDepth *= _Crest_OutScatteringFactor;
#endif
float3 outScatteringTerm = exp(-extinction * waterDepth);
// Transition between the Underwater Environmental Lighting (if present) and this. This will give us the
// benefit of both approaches.
outScatteringTerm = lerp(outScatteringTerm, 1.0, _Crest_UnderwaterEnvironmentalLightingWeight);
// Darken scene and light.
sceneColour *= outScatteringTerm;
#if !CREST_REFLECTION
lightColor *= outScatteringTerm;
ambientLighting *= outScatteringTerm;
#endif
}
VolumeLighting
(
absorption * _Crest_ExtinctionMultiplier,
scattering * _Crest_ExtinctionMultiplier,
_Crest_Anisotropy,
shadow,
view,
ambientLighting,
lightDirection,
lightColor,
half3(0.0, 0.0, 0.0),
_Crest_AmbientTerm,
_Crest_DirectTerm,
fogDistance,
_Crest_SunBoost,
_Crest_ShadowsAffectsAmbientFactor,
volumeLight,
volumeOpacity
);
}
#ifndef k_DisableCaustics
if (_Crest_CausticsEnabled && hasCaustics)
{
float3 position = i_positionWS;
#if CREST_BIRP
position = float3(i_positionSS, 0);
#endif
half lightOcclusion = PrimaryLightShadows(position);
half blur = 0.0;
const uint slice0 = PositionToSliceIndex(i_positionWS.xz, 0, g_Crest_WaterScale);
#ifdef CREST_FLOW_ON
half2 flowData = Cascade::MakeFlow(slice0).SampleFlow(i_positionWS.xz);
const Flow flow = Flow::Make(flowData, g_Crest_Time);
blur = _Crest_CausticsMotionBlur;
#endif
const float4 displacement = Cascade::MakeAnimatedWaves(slice0).Sample(i_positionWS.xz);
const float surfaceHeight = displacement.y + g_Crest_WaterCenter.y + displacement.w;
sceneColour *= Caustics
(
#ifdef CREST_FLOW_ON
flow,
#endif
i_positionWS,
surfaceHeight,
lightColor,
lightDirection,
lightOcclusion,
sceneZ,
_Crest_CausticsTiledTexture,
_Crest_CausticsTextureAverage,
_Crest_CausticsStrength,
_Crest_CausticsFocalDepth,
_Crest_CausticsDepthOfField,
_Crest_CausticsDistortionTiledTexture,
_Crest_CausticsDistortionStrength,
blur,
isUnderwater
);
}
#endif
#if CREST_HDRP
volumeLight *= GetCurrentExposureMultiplier();
#endif
#ifndef k_DisableDithering
#if d_Dithering
// Increasing intensity can be required for HDRP.
volumeLight += ScreenSpaceDither(i_positionSS) * _Crest_DitheringIntensity;
#endif
#endif
return lerp(sceneColour, volumeLight, volumeOpacity);
}
m_CrestNameSpaceEnd
#endif // CREST_UNDERWATER_EFFECT_SHARED_INCLUDED

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: decff59e1280c4df1bd50de3e83a28a6
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#pragma multi_compile_fragment _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#pragma multi_compile_fragment _ _SHADOWS_SOFT
#define CREST_URP 1
#define CREST_SHADERGRAPH_CONSTANTS_H
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D_X(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
m_CrestNameSpace
// Shim as HDRP uses this.
float LoadCameraDepth(uint2 pixelCoords)
{
return LOAD_TEXTURE2D_X(_CameraDepthTexture, pixelCoords).r;
}
m_CrestNameSpaceEnd

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 40ef61909a559462ab3c6dd2143a77f8
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: