Files
2026-01-08 22:30:55 +08:00

153 lines
4.4 KiB
HLSL

// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#ifndef d_WaveHarmonic_Crest_Mask
#define d_WaveHarmonic_Crest_Mask
#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
m_CrestNameSpace
struct Attributes
{
// The old unity macros require this name and type.
float4 positionCS : POSITION;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
#if d_LodInput
float3 positionWS : TEXCOORD;
#endif
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings Vertex(const Attributes i_Input)
{
// This will work for all pipelines.
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(i_Input);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
const uint slice0 = _Crest_LodIndex;
const uint slice1 = _Crest_LodIndex + 1;
const Cascade cascade0 = Cascade::Make(slice0);
const Cascade cascade1 = Cascade::Make(slice1);
float3 positionWS = mul(UNITY_MATRIX_M, float4(i_Input.positionCS.xyz, 1.0)).xyz;
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionWS.xz += _WorldSpaceCameraPos.xz;
#endif
float alpha;
SnapAndTransitionVertLayout(_Crest_ChunkMeshScaleAlpha, cascade0, _Crest_ChunkGeometryGridWidth, positionWS, alpha);
{
// 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);
positionWS.xz = lerp(tileCenterXZ, positionWS.xz, lerp(1.0, 1.01, max(cameraPositionXZ.x, cameraPositionXZ.y) * 0.00001));
}
const float weight0 = (1.0 - alpha) * cascade0._Weight;
const float weight1 = (1.0 - weight0) * cascade1._Weight;
const float2 positionXZ = positionWS.xz;
// Data that needs to be sampled at the undisplaced position.
if (weight0 > m_CrestSampleLodThreshold)
{
Cascade::MakeAnimatedWaves(slice0).SampleDisplacement(positionXZ, weight0, positionWS);
}
if (weight1 > m_CrestSampleLodThreshold)
{
Cascade::MakeAnimatedWaves(slice1).SampleDisplacement(positionXZ, weight1, positionWS);
}
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionWS.xz -= _WorldSpaceCameraPos.xz;
#endif
output.positionCS = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
#if d_LodInput
output.positionWS = positionWS;
#endif
return output;
}
half4 Fragment(const Varyings i_Input, const bool i_FrontFace)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i_Input);
#if d_LodInput
return half4(i_Input.positionWS.y - g_Crest_WaterCenter.y, 0, 0, 1);
#endif
half result = 0.0;
#if (CREST_PORTALS != 0)
#if !d_Tunnel
if (m_CrestPortal)
{
Portal::EvaluateMask(i_Input.positionCS);
}
#endif
#endif
if (IsUnderWater(i_FrontFace, g_Crest_ForceUnderwater))
{
result = CREST_MASK_BELOW_SURFACE;
}
else
{
result = CREST_MASK_ABOVE_SURFACE;
}
#if (CREST_PORTALS != 0)
#if d_Crest_NegativeVolumePass
result = Portal::FixMaskForNegativeVolume(result, i_Input.positionCS.xy);
#endif
#if d_Tunnel
const float2 positionSS = i_Input.positionCS.xy;
const float ffz = LOAD_DEPTH_TEXTURE_X(_Crest_PortalFogBeforeTexture, positionSS);
const float bfz = LOAD_DEPTH_TEXTURE_X(_Crest_PortalFogAfterTexture, positionSS);
if (ffz <= 0.0 && bfz > 0.0)
{
result = CREST_MASK_ABOVE_SURFACE;
}
#endif
#endif
return (half4)result;
}
m_CrestNameSpaceEnd
m_CrestVertex
m_CrestFragmentWithFrontFace(half4)
#endif // d_WaveHarmonic_Crest_Mask