208 lines
5.7 KiB
HLSL
208 lines
5.7 KiB
HLSL
// 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"
|
|
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Volume/Debug.hlsl"
|
|
|
|
#if (CREST_LEGACY_UNDERWATER == 1) || defined(CREST_URP)
|
|
#define d_Crest_SampleColor 1
|
|
#else
|
|
#define d_Crest_SampleColor 0
|
|
#endif
|
|
|
|
#ifndef SUPPORTS_FOVEATED_RENDERING_NON_UNIFORM_RASTER
|
|
#define FoveatedRemapLinearToNonUniform(uv) uv
|
|
#endif
|
|
|
|
#if (CREST_LEGACY_UNDERWATER != 0) || d_Crest_CustomColorTexture
|
|
TEXTURE2D_X(_Crest_CameraColorTexture);
|
|
#endif
|
|
|
|
#if d_Crest_ComputeMask
|
|
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Data.hlsl"
|
|
#endif
|
|
|
|
m_CrestNameSpace
|
|
|
|
#if (CREST_LEGACY_UNDERWATER != 0) || d_Crest_CustomColorTexture
|
|
float3 SampleSceneColor(float2 i_UV)
|
|
{
|
|
return LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, i_UV * _ScreenSize.xy).rgb;
|
|
}
|
|
#endif
|
|
|
|
struct Attributes
|
|
{
|
|
#if d_Crest_Geometry
|
|
float3 positionOS : POSITION;
|
|
#else
|
|
uint id : SV_VertexID;
|
|
#endif
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionCS : SV_POSITION;
|
|
#if d_Crest_ComputeMask
|
|
float3 positionWS : TEXCOORD;
|
|
#endif
|
|
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 d_Crest_Geometry
|
|
// Use actual geometry instead of full screen triangle.
|
|
output.positionCS = TransformObjectToHClip(input.positionOS);
|
|
#if d_Crest_ComputeMask
|
|
output.positionWS = TransformObjectToWorld(input.positionOS);
|
|
#endif
|
|
#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;
|
|
const float2 positionNDC = (positionSS + 0.5) / _ScreenSize.xy;
|
|
float mask = -1.0;
|
|
|
|
#if !d_Crest_NoMaskColor
|
|
#if d_Crest_ComputeMask
|
|
{
|
|
float3 positionWS = input.positionWS;
|
|
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
|
positionWS.xyz += _WorldSpaceCameraPos.xyz;
|
|
#endif
|
|
mask = positionWS.y <= SampleWaterLineHeight(positionWS.xz) ? -1 : 1;
|
|
}
|
|
#else
|
|
mask = LOAD_TEXTURE2D_X(_Crest_WaterMaskTexture, positionSS).x;
|
|
#endif
|
|
|
|
#if !_DEBUG_VISUALIZE_MASK
|
|
// Preserve alpha channel.
|
|
if (mask > CREST_MASK_BELOW_SURFACE)
|
|
{
|
|
discard;
|
|
}
|
|
#endif
|
|
#endif // !d_Crest_NoMaskColor
|
|
|
|
float rawDepth = LoadSceneDepth(positionSS);
|
|
|
|
half3 sceneColour;
|
|
|
|
#if d_Crest_CustomColorTexture
|
|
if (m_CrestPortalNegativeVolume)
|
|
{
|
|
sceneColour = LOAD_TEXTURE2D_X(_Crest_CameraColorTexture, positionSS).rgb;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
// Use sample in case texture is downsampled.
|
|
sceneColour = SampleSceneColor(positionNDC).rgb;
|
|
}
|
|
|
|
#if d_Crest_NoMaskDepth
|
|
const float rawMaskDepth = 0.0;
|
|
#else
|
|
const float rawMaskDepth = LOAD_TEXTURE2D_X(_Crest_WaterMaskDepthTexture, positionSS).x;
|
|
#endif
|
|
|
|
#if _DEBUG_VISUALIZE_STENCIL
|
|
return DebugRenderStencil(sceneColour);
|
|
#endif
|
|
|
|
bool isWaterSurface; bool isUnderwater; bool hasCaustics; float sceneZ; bool outScatterScene; bool applyLighting;
|
|
GetWaterSurfaceAndUnderwaterData(input.positionCS, positionSS, rawMaskDepth, mask, rawDepth, isWaterSurface, isUnderwater, hasCaustics, outScatterScene, applyLighting, sceneZ);
|
|
|
|
#if !_DEBUG_VISUALIZE_MASK
|
|
// Preserve alpha channel.
|
|
if (!isUnderwater)
|
|
{
|
|
discard;
|
|
}
|
|
#endif
|
|
|
|
float fogDistance = sceneZ;
|
|
ApplyWaterVolumeToUnderwaterFog(input.positionCS, fogDistance);
|
|
|
|
#if _DEBUG_VISUALIZE_MASK
|
|
return DebugRenderWaterMask(isWaterSurface, isUnderwater, mask, sceneColour);
|
|
#endif
|
|
|
|
if (isUnderwater)
|
|
{
|
|
const float2 uv = FoveatedRemapLinearToNonUniform(positionNDC);
|
|
float3 positionWS = ComputeWorldSpacePosition(uv, rawDepth, UNITY_MATRIX_I_VP);
|
|
const half3 view = GetWorldSpaceNormalizeViewDir(positionWS);
|
|
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
|
positionWS += _WorldSpaceCameraPos;
|
|
#endif
|
|
half3 vo =0; half3 vl = 0;
|
|
sceneColour = ApplyUnderwaterEffect(sceneColour, rawDepth, sceneZ, fogDistance, view, positionSS, positionWS, hasCaustics, outScatterScene, applyLighting, 1.0, vo, vl);
|
|
}
|
|
|
|
return half4(sceneColour, 1.0);
|
|
}
|
|
|
|
half4 FragmentPlanarReflections(Varyings input)
|
|
{
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
const uint2 positionSS = input.positionCS.xy;
|
|
const float2 positionNDC = (positionSS + 0.5) / _ScreenSize.xy;
|
|
float depth = LoadSceneDepth(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);
|
|
}
|
|
|
|
#if d_Crest_SampleColor
|
|
half3 color = SampleSceneColor(positionNDC).rgb;
|
|
#else
|
|
half3 color = LoadSceneColor(positionSS).rgb;
|
|
#endif
|
|
|
|
// Calculate position and account for possible NaNs discovered during testing.
|
|
float3 positionWS = Utility::SafeComputeWorldSpacePosition(positionNDC, depth, UNITY_MATRIX_I_VP);
|
|
|
|
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
|
positionWS += _WorldSpaceCameraPos;
|
|
#endif
|
|
|
|
const half3 view = GetWorldSpaceNormalizeViewDir(positionWS);
|
|
const bool hasCaustics = depth > 0.0;
|
|
|
|
half3 vo = 0; half3 vl = 0;
|
|
color = ApplyUnderwaterEffect(color, depth, 0.0, 0.0, view, positionSS, positionWS, hasCaustics, true, true, 1.0, vo, vl);
|
|
|
|
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);
|
|
}
|