128 lines
4.0 KiB
HLSL
128 lines
4.0 KiB
HLSL
// Crest Water System
|
|
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
|
|
|
#ifndef CREST_WATER_NORMAL_H
|
|
#define CREST_WATER_NORMAL_H
|
|
|
|
#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/Texture.hlsl"
|
|
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Flow.hlsl"
|
|
|
|
#if (CREST_SHIFTING_ORIGIN != 0)
|
|
#include "Packages/com.waveharmonic.crest.shifting-origin/Runtime/Shaders/ShiftingOrigin.hlsl"
|
|
#endif
|
|
|
|
// These are per cascade, set per chunk instance.
|
|
float _Crest_ChunkFarNormalsWeight;
|
|
float2 _Crest_ChunkNormalScrollSpeed;
|
|
|
|
m_CrestNameSpace
|
|
|
|
half2 SampleNormalMaps
|
|
(
|
|
const TiledTexture i_NormalMap,
|
|
const half i_Strength,
|
|
const float2 i_UndisplacedXZ,
|
|
const float i_LodAlpha,
|
|
const Cascade i_CascadeData
|
|
)
|
|
{
|
|
float2 worldXZUndisplaced = i_UndisplacedXZ;
|
|
|
|
#if (CREST_SHIFTING_ORIGIN != 0)
|
|
// Apply tiled floating origin offset. Always needed.
|
|
worldXZUndisplaced -= ShiftingOriginOffset(i_NormalMap, i_CascadeData);
|
|
#endif
|
|
|
|
const float2 v0 = float2(0.94, 0.34), v1 = float2(-0.85, -0.53);
|
|
float scale = i_NormalMap._scale * i_CascadeData._Scale / 10.0;
|
|
const float spdmulL = _Crest_ChunkNormalScrollSpeed.x * i_NormalMap._speed;
|
|
half2 norm =
|
|
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v0 * g_Crest_Time * spdmulL) / scale)).xy +
|
|
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v1 * g_Crest_Time * spdmulL) / scale)).xy;
|
|
|
|
// blend in next higher scale of normals to obtain continuity
|
|
const half nblend = i_LodAlpha * _Crest_ChunkFarNormalsWeight;
|
|
if (nblend > 0.001)
|
|
{
|
|
// next lod level
|
|
scale *= 2.0;
|
|
const float spdmulH = _Crest_ChunkNormalScrollSpeed.y * i_NormalMap._speed;
|
|
norm = lerp(norm,
|
|
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v0 * g_Crest_Time * spdmulH) / scale)).xy +
|
|
UnpackNormal(i_NormalMap.Sample((worldXZUndisplaced + v1 * g_Crest_Time * spdmulH) / scale)).xy,
|
|
nblend);
|
|
}
|
|
|
|
// approximate combine of normals. would be better if normals applied in local frame.
|
|
return i_Strength * norm;
|
|
}
|
|
|
|
half2 SampleNormalMaps
|
|
(
|
|
const Flow i_Flow,
|
|
const TiledTexture i_NormalMap,
|
|
const half i_Strength,
|
|
const float2 i_UndisplacedXZ,
|
|
const float i_LodAlpha,
|
|
const Cascade i_CascadeData
|
|
)
|
|
{
|
|
return SampleNormalMaps
|
|
(
|
|
i_NormalMap,
|
|
i_Strength,
|
|
i_UndisplacedXZ - i_Flow._Flow * (i_Flow._Offset0 - i_Flow._Period * 0.5),
|
|
i_LodAlpha,
|
|
i_CascadeData
|
|
) * i_Flow._Weight0 + SampleNormalMaps
|
|
(
|
|
i_NormalMap,
|
|
i_Strength,
|
|
i_UndisplacedXZ - i_Flow._Flow * (i_Flow._Offset1 - i_Flow._Period * 0.5),
|
|
i_LodAlpha,
|
|
i_CascadeData
|
|
) * i_Flow._Weight1;
|
|
}
|
|
|
|
void WaterNormal
|
|
(
|
|
const float2 i_WaterLevelDerivatives,
|
|
const half3 i_ViewDirectionWS,
|
|
const half i_MinimumReflectionDirectionY,
|
|
const bool i_Underwater,
|
|
inout half3 io_NormalWS
|
|
)
|
|
{
|
|
// Account for water level changes which change angle of water surface, impacting normal.
|
|
io_NormalWS.xz += -i_WaterLevelDerivatives;
|
|
|
|
// Finalise normal
|
|
io_NormalWS = normalize(io_NormalWS);
|
|
|
|
if (i_Underwater)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Limit how close to horizontal reflection ray can get, useful to avoid unsightly below-horizon reflections.
|
|
{
|
|
float3 refl = reflect(-i_ViewDirectionWS, io_NormalWS);
|
|
if (refl.y < i_MinimumReflectionDirectionY)
|
|
{
|
|
// Find the normal that keeps the reflection direction above the horizon. Compute
|
|
// the reflection dir that does work, normalize it, and then normal is half vector
|
|
// between this good reflection direction and view direction.
|
|
float3 FL = refl;
|
|
FL.y = i_MinimumReflectionDirectionY;
|
|
FL = normalize(FL);
|
|
io_NormalWS = normalize(FL + i_ViewDirectionWS);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_CrestNameSpaceEnd
|
|
|
|
#endif
|