升级6.4.升级水,升级天气
This commit is contained in:
@@ -63,7 +63,7 @@ Shader "Crest/Inputs/Albedo/Color"
|
||||
float3 positionWS = mul(unity_ObjectToWorld, float4(input.vertex, 1.0)).xyz;
|
||||
positionWS.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
output.vertex = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
output.uv = input.uv;
|
||||
output.uv = TRANSFORM_TEX(input.uv, _Crest_Texture);
|
||||
output.color = input.color;
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ Shader "Crest/Inputs/Dynamic Waves/Add Bump"
|
||||
y = pow(y, 0.05);
|
||||
y *= _Crest_Amplitude;
|
||||
|
||||
y /= g_Crest_LodCount;
|
||||
y /= (float)g_Crest_LodCount;
|
||||
|
||||
// Feather edges to reduce streaking without introducing reflections.
|
||||
y *= FeatherWeightFromUV(input.uv, 0.1);
|
||||
@@ -107,4 +107,5 @@ Shader "Crest/Inputs/Dynamic Waves/Add Bump"
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestTransferWaves
|
||||
|
||||
#pragma multi_compile_local __ d_Texture d_TextureBlend
|
||||
@@ -11,6 +13,7 @@
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Filtering.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/Globals.hlsl"
|
||||
@@ -23,6 +26,7 @@ Texture2DArray _Crest_WaveBuffer;
|
||||
RWTexture2DArray<float4> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float _Crest_WaveBufferAttenuation[k_Crest_WaveOctaveCount];
|
||||
float4 _Crest_WaveBufferParameters[MAX_LOD_COUNT];
|
||||
float2 _Crest_AxisX;
|
||||
float _Crest_Weight;
|
||||
@@ -32,12 +36,15 @@ float _Crest_RespectShallowWaterAttenuation;
|
||||
float _Crest_MaximumAttenuationDepth;
|
||||
float _Crest_WaveResolutionMultiplier;
|
||||
float _Crest_TransitionalWavelengthThreshold;
|
||||
uint _Crest_Resolution;
|
||||
bool _Crest_SeaLevelOnly;
|
||||
|
||||
// Texture
|
||||
#if d_Texture
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float2 _Crest_Multiplier;
|
||||
bool _Crest_NegativeValues;
|
||||
int _Crest_Blend;
|
||||
#endif
|
||||
@@ -60,6 +67,8 @@ void TransferWaves(uint3 id)
|
||||
const uint last = parameters.y;
|
||||
const half transition = parameters.w;
|
||||
|
||||
const uint2 resolution = uint2(_Crest_Resolution, _Crest_Resolution);
|
||||
|
||||
#if !d_TextureBlend
|
||||
// Additive only. All wavelengths filtered out for this LOD so nothing to do.
|
||||
if (parameters.x < 0 || parameters.y < 0)
|
||||
@@ -95,7 +104,7 @@ void TransferWaves(uint3 id)
|
||||
float2 axis; float axisLength = 0.0; float t = 0.0;
|
||||
float2 axisX0 = 0.0; float2 axisX1 = 0.0; float2 axisZ0 = 0.0; float2 axisZ1 = 0.0;
|
||||
{
|
||||
axis = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uvPainted, 0).xy;
|
||||
axis = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uvPainted, 0).xy * _Crest_Multiplier;
|
||||
|
||||
if (!_Crest_NegativeValues)
|
||||
{
|
||||
@@ -154,11 +163,12 @@ void TransferWaves(uint3 id)
|
||||
axisZ1.x = -axisX1.y; axisZ1.y = axisX1.x;
|
||||
}
|
||||
#else
|
||||
|
||||
const float2 positionWaves = float2(dot(positionWS, _Crest_AxisX), dot(positionWS, float2(-_Crest_AxisX.y, _Crest_AxisX.x)));
|
||||
#endif // d_Texture
|
||||
|
||||
const half depth = Cascade::MakeDepth(slice0).SampleSignedDepthFromSeaLevel(positionWS) +
|
||||
Cascade::MakeLevel(slice0).SampleLevel(positionWS);
|
||||
const half level = Cascade::MakeLevel(slice0).SampleLevel(positionWS);
|
||||
const half depth = Cascade::MakeDepth(slice0).SampleSignedDepthFromSeaLevel(positionWS) + level;
|
||||
|
||||
half3 _displacement = 0.0;
|
||||
|
||||
@@ -198,8 +208,7 @@ void TransferWaves(uint3 id)
|
||||
weight = lerp(weight, 1.0, saturate(depth / _Crest_MaximumAttenuationDepth));
|
||||
}
|
||||
|
||||
|
||||
const float attenuationAmount = _Crest_AttenuationInShallows * _Crest_RespectShallowWaterAttenuation;
|
||||
const float attenuationAmount = _Crest_AttenuationInShallows * _Crest_RespectShallowWaterAttenuation * _Crest_WaveBufferAttenuation[i];
|
||||
attenuation = attenuationAmount * weight + (1.0 - attenuationAmount);
|
||||
}
|
||||
|
||||
@@ -217,8 +226,8 @@ void TransferWaves(uint3 id)
|
||||
const float2 uv1 = float2(dot(positionScaledWS, axisX1), dot(positionScaledWS, axisZ1));
|
||||
|
||||
// Sample displacement, rotate into frame.
|
||||
float3 displacement0 = _Crest_WaveBuffer.SampleLevel(sampler_Crest_linear_repeat, float3(uv0, waveBufferIndex), 0).xyz;
|
||||
float3 displacement1 = _Crest_WaveBuffer.SampleLevel(sampler_Crest_linear_repeat, float3(uv1, waveBufferIndex), 0).xyz;
|
||||
const float3 displacement0 = Utility::SampleBicubicRepeat(_Crest_WaveBuffer, uv0, resolution, waveBufferIndex).xyz;
|
||||
const float3 displacement1 = Utility::SampleBicubicRepeat(_Crest_WaveBuffer, uv1, resolution, waveBufferIndex).xyz;
|
||||
|
||||
float3 displacement = lerp(displacement0, displacement1, t);
|
||||
displacement.xz = displacement.x * axis + displacement.z * float2(-axis.y, axis.x);
|
||||
@@ -227,7 +236,9 @@ void TransferWaves(uint3 id)
|
||||
|
||||
#else // !d_Texture
|
||||
// Sample displacement, rotate into frame defined by global wind direction.
|
||||
half3 displacement = _Crest_WaveBuffer.SampleLevel(sampler_Crest_linear_repeat, float3(positionWaves / waveBufferSize, waveBufferIndex), 0).xyz;
|
||||
// Hardware bilinear produces small noise artifacts. Custom bilinear solves that,
|
||||
// but we still get texel artifacts that show up in normals, so use bicubic.
|
||||
float3 displacement = Utility::SampleBicubicRepeat(_Crest_WaveBuffer, positionWaves / waveBufferSize, resolution, waveBufferIndex).xyz;
|
||||
displacement.xz = displacement.x * _Crest_AxisX + displacement.z * float2(-_Crest_AxisX.y, _Crest_AxisX.x);
|
||||
_displacement += displacement * weight;
|
||||
#endif // d_Texture
|
||||
@@ -239,6 +250,13 @@ void TransferWaves(uint3 id)
|
||||
_Crest_Target[id] *= 1.0 - saturate(alpha);
|
||||
#endif
|
||||
|
||||
#if !d_Texture
|
||||
if (_Crest_SeaLevelOnly)
|
||||
{
|
||||
_displacement *= saturate(1.0 - abs(level));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Always write full alpha so textures show up in previews.
|
||||
_Crest_Target[id] += float4(_displacement, 1.0);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#pragma multi_compile_local d_Sphere d_Cube d_Rectangle
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Adds clipping from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
// afterwards. It is converted to world-space in another shader before writing into
|
||||
// the LOD data.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestCopy
|
||||
#pragma kernel CrestFill
|
||||
|
||||
@@ -17,7 +19,7 @@
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
|
||||
|
||||
Texture2D<float> _CamDepthBuffer;
|
||||
RWTexture2D<float2> _Crest_Target;
|
||||
RWTexture2D<m_Float2> _Crest_Target;
|
||||
|
||||
#if d_Crest_BackFaceInclusion
|
||||
Texture2D<float> _Crest_CameraDepthBufferBackfaces;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// from an ODC, then they are in object-space and are converted to world-space as
|
||||
// the LOD data stores world-space height.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#pragma multi_compile_local __ d_CrestSDF
|
||||
@@ -22,14 +24,14 @@
|
||||
|
||||
#if d_CrestSDF
|
||||
#undef m_CrestType
|
||||
#define m_CrestType float2
|
||||
#define m_CrestType m_Float2
|
||||
#endif
|
||||
|
||||
Texture2D<m_CrestType> _Crest_Texture;
|
||||
RWTexture2DArray<m_CrestType> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestInputTexture)
|
||||
float2 _Crest_Multiplier;
|
||||
m_CrestType _Crest_Multiplier;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Adds flow from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
@@ -15,7 +17,7 @@
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
RWTexture2DArray<float2> _Crest_Target;
|
||||
RWTexture2DArray<m_Float2> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
int _Crest_Blend;
|
||||
@@ -62,7 +64,8 @@ void Execute(uint3 id)
|
||||
}
|
||||
|
||||
const float2 target = _Crest_Target[id];
|
||||
_Crest_Target[id] = Blend(_Crest_Blend, weight, 1.0, source, target);
|
||||
const float2 result = Blend(_Crest_Blend, weight, 1.0, source, target);
|
||||
_Crest_Target[id] = m_Float2FromFloat2(result);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Adds foam from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
// An implementation of the Jump Flood algorithm by Rong and Tan
|
||||
// Source: https://www.comp.nus.edu.sg/~tants/jfa.html
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestInitialize
|
||||
#pragma kernel CrestExecute
|
||||
#pragma kernel CrestApply
|
||||
@@ -27,13 +29,13 @@ float _Crest_WaterLevel;
|
||||
CBUFFER_END
|
||||
|
||||
// Holds scene depth for initialization.
|
||||
Texture2D<float2> _Crest_Source;
|
||||
RWTexture2D<float2> _Crest_Target;
|
||||
Texture2D<m_Float2> _Crest_Source;
|
||||
RWTexture2D<m_Float2> _Crest_Target;
|
||||
|
||||
// Setting this to zero means that geometry at exactly the origin won't be handled
|
||||
// gracefully - but it would only affect a single-pixel in the worst-case and would
|
||||
// doubtfully be noticable anyway. Use infinity instead.
|
||||
#define m_CrestUninitializedPosition float2(m_Crest_PositiveInfinity, m_Crest_PositiveInfinity)
|
||||
#define m_CrestUninitializedPosition m_Float2Constructor(m_Crest_PositiveInfinity, m_Crest_PositiveInfinity)
|
||||
|
||||
#if d_Crest_Inverted
|
||||
#define m_DepthCheck depth > 0.0
|
||||
@@ -62,11 +64,11 @@ void Initialize(const uint3 id)
|
||||
#ifndef d_Crest_Standalone
|
||||
// Add height offset.
|
||||
uint slice0; uint slice1; float alpha;
|
||||
PosToSliceIndices(position, 0, g_Crest_LodCount - 1, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
PositionToSliceIndices(position, 0, g_Crest_LodCount - 1, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
depth += lerp(Cascade::MakeLevel(slice0).SampleLevel(position), Cascade::MakeLevel(slice1).SampleLevel(position), alpha);
|
||||
#endif
|
||||
|
||||
_Crest_Target[id.xy] = m_DepthCheck ? position : m_CrestUninitializedPosition;
|
||||
_Crest_Target[id.xy] = m_DepthCheck ? m_Float2FromFloat2(position) : m_CrestUninitializedPosition;
|
||||
}
|
||||
|
||||
void Execute(const uint3 id)
|
||||
@@ -111,7 +113,7 @@ void Execute(const uint3 id)
|
||||
}
|
||||
}
|
||||
|
||||
_Crest_Target[id.xy] = nearest;
|
||||
_Crest_Target[id.xy] = m_Float2FromFloat2(nearest);
|
||||
}
|
||||
|
||||
void Apply(const uint3 id)
|
||||
@@ -125,7 +127,7 @@ void Apply(const uint3 id)
|
||||
#ifndef d_Crest_Standalone
|
||||
// Get depth including height offset.
|
||||
uint slice0; uint slice1; float alpha;
|
||||
PosToSliceIndices(position, 0, g_Crest_LodCount - 1, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
PositionToSliceIndices(position, 0, g_Crest_LodCount - 1, g_Crest_WaterScale, slice0, slice1, alpha);
|
||||
depth += lerp(Cascade::MakeLevel(slice0).SampleLevel(position), Cascade::MakeLevel(slice1).SampleLevel(position), alpha);
|
||||
#endif
|
||||
|
||||
@@ -144,7 +146,7 @@ void Apply(const uint3 id)
|
||||
|
||||
result.y = distance;
|
||||
|
||||
_Crest_Target[id.xy] = result;
|
||||
_Crest_Target[id.xy] = m_Float2FromFloat2(result);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Adds height from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#pragma multi_compile_local __ d_CatmullRom
|
||||
@@ -27,7 +29,7 @@ float _Crest_Multiplier;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float2 _Crest_Resolution;
|
||||
float2 _Crest_TextureResolution;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
@@ -49,7 +51,7 @@ void Execute(uint3 id)
|
||||
}
|
||||
|
||||
#if d_CatmullRom
|
||||
const float source = Utility::SampleTextureCatmullRom(_Crest_Texture, LODData_linear_clamp_sampler, uv, _Crest_Resolution)
|
||||
const float source = Utility::SampleTextureCatmullRom(_Crest_Texture, LODData_linear_clamp_sampler, uv, _Crest_TextureResolution)
|
||||
#else
|
||||
const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0.0)
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
@@ -12,7 +14,7 @@
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
RWTexture2DArray<float2> _Crest_Target;
|
||||
RWTexture2DArray<m_Float2> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float3 _Crest_Position;
|
||||
@@ -116,7 +118,7 @@ void Execute(uint3 id)
|
||||
// Helps interaction to work at different scales
|
||||
acceleration /= minimumWavelength;
|
||||
|
||||
_Crest_Target[id] = float2(_Crest_Target[id].x, _Crest_Target[id].y + acceleration * _Crest_SimDeltaTime);
|
||||
_Crest_Target[id] = m_Float2Constructor(_Crest_Target[id].x, _Crest_Target[id].y + acceleration * _Crest_SimDeltaTime);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -110,7 +110,7 @@ Shader "Crest/Inputs/All/Scale"
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
#if d_Texture
|
||||
float scale = _Crest_Texture.Sample(sampler_Crest_Texture, input.uv).r;
|
||||
float scale = _Crest_Texture.Sample(sampler_Crest_Texture, TRANSFORM_TEX(input.uv, _Crest_Texture)).r;
|
||||
#else
|
||||
float scale = _Crest_Scale;
|
||||
#endif
|
||||
|
||||
@@ -50,6 +50,7 @@ Shader "Crest/Inputs/Shape Waves/Add From Geometry"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
|
||||
Texture2DArray _Crest_WaveBuffer;
|
||||
SamplerState sampler_Crest_linear_repeat;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_RespectShallowWaterAttenuation;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestPackLevel
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestQueryDisplacement d_CrestDisplacement
|
||||
#pragma kernel CrestQueryFlow d_CrestFlow
|
||||
#pragma kernel CrestQueryDepth d_CrestDepth
|
||||
@@ -40,13 +42,13 @@ RWStructuredBuffer<float3> _Crest_Target;
|
||||
m_CrestNameSpace
|
||||
|
||||
|
||||
float3 Compute(const float2 i_Position, const float i_MinimumSlice, const float i_BaseScale)
|
||||
float3 Compute(const float2 i_Position, const uint i_MinimumSlice, const float i_BaseScale)
|
||||
{
|
||||
// Do not use last slice - this is a 'transition' slice used to cross-fade waves
|
||||
// between LOD resolutions to avoid pops. That being said, this will have clamped
|
||||
// samples leading to objects floating on waves that do not exist.
|
||||
uint slice0, slice1; float alpha;
|
||||
PosToSliceIndices(i_Position, i_MinimumSlice, g_Crest_LodCount - 2.0, i_BaseScale, slice0, slice1, alpha);
|
||||
PositionToSliceIndices(i_Position, i_MinimumSlice, g_Crest_LodCount - 2, i_BaseScale, slice0, slice1, alpha);
|
||||
|
||||
const Cascade cascade0 = Cascade::d_CrestMake(slice0);
|
||||
const Cascade cascade1 = Cascade::d_CrestMake(slice1);
|
||||
@@ -64,15 +66,9 @@ float3 Compute(const float2 i_Position, const float i_MinimumSlice, const float
|
||||
void Query(const uint3 id)
|
||||
{
|
||||
const float3 data = _Crest_QueryPositions_MinimumGridSizes[id.x];
|
||||
const float minimumGridSize = data.z;
|
||||
const uint minimumSlice = data.z;
|
||||
float2 position = data.xy;
|
||||
|
||||
const float gridSizeSlice0 = Cascade::d_CrestMake(0)._Texel;
|
||||
// Displacements should not utilize the last slice which is used for transitioning
|
||||
// waves between sampling resolutions. While it might be ok to use the last slice
|
||||
// for other targets, we avoid using it to be consistent with displacements.
|
||||
const float minimumSlice = clamp(floor(log2(max(minimumGridSize / gridSizeSlice0, 1.0))), 0.0, g_Crest_LodCount - 2.0);
|
||||
|
||||
#if d_CrestDisplacement
|
||||
// Perform iteration to invert the displacement vector field - find position that displaces to query position,
|
||||
// and return displacement at that point.
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Merged into Query.compute.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
[numthreads(1, 1, 1)]
|
||||
void CrestExecute(uint3 id : SV_DispatchThreadID) { }
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Merged into Query.compute.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
[numthreads(1, 1, 1)]
|
||||
void CrestExecute(uint3 id : SV_DispatchThreadID) { }
|
||||
|
||||
@@ -1,91 +1,48 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Compute shader to perform combine of displacements. Reads and writes to texture array which saves
|
||||
// needing to do ping pong of render targets. Unfortunately reading/writing float4s is not supported
|
||||
// on pre-DX11.3 hardware (aka typed UAV loads), so this path is not the default, for now..
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel ShapeCombine
|
||||
#pragma kernel ShapeCombine_DISABLE_COMBINE _DISABLE_COMBINE
|
||||
#pragma kernel ShapeCombine_FLOW_ON _FLOW_ON
|
||||
#pragma kernel ShapeCombine_FLOW_ON_DISABLE_COMBINE _FLOW_ON _DISABLE_COMBINE
|
||||
#pragma kernel ShapeCombine_DYNAMIC_WAVE_SIM_ON _DYNAMIC_WAVE_SIM_ON
|
||||
#pragma kernel ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE _DYNAMIC_WAVE_SIM_ON _DISABLE_COMBINE
|
||||
#pragma kernel ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON _FLOW_ON _DYNAMIC_WAVE_SIM_ON
|
||||
#pragma kernel ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE _FLOW_ON _DYNAMIC_WAVE_SIM_ON _DISABLE_COMBINE
|
||||
#pragma kernel ShapeCombineDynamicWaves
|
||||
#pragma kernel ShapeCombineDynamicWaves_DISABLE_COMBINE _DISABLE_COMBINE
|
||||
#pragma kernel ShapeCombineCopyDynamicWaves
|
||||
#pragma kernel CrestShapeCombineAnimatedWaves
|
||||
#pragma kernel CrestShapeCopyAnimatedWaves
|
||||
#pragma kernel CrestShapeCombineDynamicWaves d_CombineDynamicWaves
|
||||
|
||||
#pragma multi_compile_local _ d_Combine
|
||||
#pragma multi_compile_local _ d_DynamicWaves
|
||||
#pragma multi_compile _ CREST_FLOW_ON_INTERNAL
|
||||
|
||||
#if d_CombineDynamicWaves
|
||||
#define d_DynamicWaves 1
|
||||
#endif
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Keywords.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/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
#if d_Combine
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Filtering.hlsl"
|
||||
#endif
|
||||
|
||||
#if d_Crest_FlowLod
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Flow.hlsl"
|
||||
#endif
|
||||
|
||||
float _Crest_HorizontalDisplace;
|
||||
float _Crest_DisplaceClamp;
|
||||
|
||||
Texture2DArray _Crest_WaveBuffer;
|
||||
RWTexture2DArray<float4> _Crest_Target;
|
||||
RWTexture2DArray<float4> _Crest_DynamicWavesTarget;
|
||||
RWTexture2DArray<float4> _Crest_AnimatedWavesTarget;
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Flow(const float texel, out float2 offsets, out float2 weights)
|
||||
void ShapeCombine(uint3 id)
|
||||
{
|
||||
const float period = max(3.0 * texel, 1.0);
|
||||
const float half_period = period / 2.0;
|
||||
offsets = fmod(float2(g_Crest_Time, g_Crest_Time + half_period), period);
|
||||
weights.x = offsets.x / half_period;
|
||||
if (weights.x > 1.0) weights.x = 2.0 - weights.x;
|
||||
weights.y = 1.0 - weights.x;
|
||||
}
|
||||
|
||||
void SampleDisplacementsCompute(
|
||||
in RWTexture2DArray<float4> i_dispSampler,
|
||||
in float i_resolution, in float3 i_uv_slice,
|
||||
in float i_wt, inout float3 io_worldPos
|
||||
) {
|
||||
// NOTE: We have to roll our own bilinear filter in Compute shaders when
|
||||
// reading from a RWTexture. The documentation below explains how SRV
|
||||
// and UAV mappings of the same texture cannot exist at the same time.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/sm5-object-rwtexture2d
|
||||
|
||||
// Convert from UV to coordinates
|
||||
const float2 pixelCoord = i_uv_slice.xy * i_resolution;
|
||||
|
||||
// Make relative to pixel centers
|
||||
float2 pixelCoordCenters = pixelCoord - 0.5;
|
||||
|
||||
// Clamp from below and above (desired?)
|
||||
pixelCoordCenters = clamp(pixelCoordCenters, 0.0, i_resolution - 1.0);
|
||||
|
||||
// Compute integral and fractional parts
|
||||
const uint2 pixelCoordCentersBotLeft = floor(pixelCoordCenters);
|
||||
const uint sliceIndex = i_uv_slice.z;
|
||||
const float2 pixelCoordCentersFrac = frac(pixelCoordCenters);
|
||||
|
||||
const half4 dataBotLeft = i_dispSampler[uint3(pixelCoordCentersBotLeft, sliceIndex)];
|
||||
const half4 dataBotRight = i_dispSampler[uint3(pixelCoordCentersBotLeft + uint2(1, 0), sliceIndex)];
|
||||
const half4 dataTopLeft = i_dispSampler[uint3(pixelCoordCentersBotLeft + uint2(0, 1), sliceIndex)];
|
||||
const half4 dataTopRight = i_dispSampler[uint3(pixelCoordCentersBotLeft + uint2(1, 1), sliceIndex)];
|
||||
|
||||
const float4 dataLerped = lerp(
|
||||
lerp(dataBotLeft, dataBotRight, pixelCoordCentersFrac.x),
|
||||
lerp(dataTopLeft, dataTopRight, pixelCoordCentersFrac.x),
|
||||
pixelCoordCentersFrac.y
|
||||
);
|
||||
|
||||
io_worldPos += i_wt * dataLerped.xyz;
|
||||
}
|
||||
|
||||
void ShapeCombineBase(uint3 id)
|
||||
{
|
||||
const uint slice0 = _Crest_LodIndex;
|
||||
const uint slice0 = id.z;
|
||||
const Cascade cascade = Cascade::MakeAnimatedWaves(slice0);
|
||||
|
||||
const float3 uv = cascade.IDToUV(id.xy);
|
||||
@@ -93,87 +50,68 @@ void ShapeCombineBase(uint3 id)
|
||||
|
||||
float3 result = 0.0;
|
||||
|
||||
#if !d_CombineDynamicWaves
|
||||
// Sample in waves for this cascade.
|
||||
{
|
||||
#if _FLOW_ON
|
||||
const half2 flow = Cascade::MakeFlow(slice0).SampleFlow(positionWSXZ);
|
||||
#if d_Crest_FlowLod
|
||||
const Flow f = Flow::Make
|
||||
(
|
||||
Cascade::MakeFlow(slice0).SampleFlow(positionWSXZ),
|
||||
g_Crest_Time,
|
||||
max(3.0 * cascade._Texel, 1.0)
|
||||
);
|
||||
|
||||
float2 offsets, weights;
|
||||
Flow(cascade._Texel, offsets, weights);
|
||||
|
||||
result += cascade.Sample(_Crest_WaveBuffer, positionWSXZ - offsets[0] * flow).xyz * weights[0];
|
||||
result += cascade.Sample(_Crest_WaveBuffer, positionWSXZ - offsets[1] * flow).xyz * weights[1];
|
||||
result += cascade.SampleAnimatedWavesOverflow(_Crest_WaveBuffer, positionWSXZ - f._Offset0 * f._Flow, 1.0).xyz * f._Weight0;
|
||||
result += cascade.SampleAnimatedWavesOverflow(_Crest_WaveBuffer, positionWSXZ - f._Offset1 * f._Flow, 1.0).xyz * f._Weight1;
|
||||
#else
|
||||
result += cascade.Sample(_Crest_WaveBuffer, uv).xyz;
|
||||
#endif // _FLOW_ON
|
||||
}
|
||||
|
||||
// Disabled for last LOD.
|
||||
#if !_DISABLE_COMBINE
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeAnimatedWaves(slice0 + 1);
|
||||
// Sample the shape 1 texture at this world position.
|
||||
const float3 uv = cascade.WorldToUV(positionWSXZ);
|
||||
// Waves to combine down from the next lod up the chain.
|
||||
SampleDisplacementsCompute(_Crest_Target, cascade._Resolution, uv, 1.0, result);
|
||||
result += _Crest_WaveBuffer[id].xyz;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _DYNAMIC_WAVE_SIM_ON
|
||||
// Disabled for last LOD.
|
||||
#if d_Combine
|
||||
{
|
||||
const uint slice1 = slice0 + 1;
|
||||
const Cascade cascade = Cascade::MakeAnimatedWaves(slice1);
|
||||
// Sample the shape 1 texture at this world position.
|
||||
const float3 uv = cascade.WorldToUV(positionWSXZ);
|
||||
// Waves to combine down from the next lod up the chain.
|
||||
result += Utility::SampleBilinear(_Crest_Target, uv.xy, slice1, cascade._Resolution);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_DynamicWaves
|
||||
{
|
||||
// Convert dynamic wave sim to displacements.
|
||||
result += Cascade::MakeDynamicWaves(slice0)
|
||||
.SampleDynamicWavesDisplacement(positionWSXZ, _Crest_HorizontalDisplace, _Crest_DisplaceClamp);
|
||||
}
|
||||
#endif // _DYNAMIC_WAVE_SIM_ON
|
||||
#endif
|
||||
|
||||
_Crest_Target[uint3(id.xy, slice0)] = float4(result, 0.0);
|
||||
_Crest_Target[id] = float4(result, 0.0);
|
||||
}
|
||||
|
||||
void ShapeCombineAnimatedWaves(uint3 id)
|
||||
{
|
||||
id.z = _Crest_LodIndex;
|
||||
ShapeCombine(id);
|
||||
}
|
||||
|
||||
void ShapeCopyAnimatedWaves(uint3 id)
|
||||
{
|
||||
ShapeCombine(id);
|
||||
}
|
||||
|
||||
void ShapeCombineDynamicWaves(uint3 id)
|
||||
{
|
||||
const uint slice0 = _Crest_LodIndex;
|
||||
const Cascade cascade = Cascade::MakeAnimatedWaves(slice0);
|
||||
const float3 uv = cascade.IDToUV(id.xy);
|
||||
const float2 positionWSXZ = cascade.UVToWorld(uv);
|
||||
float3 result = 0.0;
|
||||
|
||||
// Disabled for last LOD.
|
||||
#if !_DISABLE_COMBINE
|
||||
{
|
||||
// We are sampling from the target which matches Animated Waves descriptor.
|
||||
const Cascade cascade = Cascade::MakeAnimatedWaves(slice0 + 1);
|
||||
const float3 uv = cascade.WorldToUV(positionWSXZ);
|
||||
// Waves to combine down from the next lod up the chain.
|
||||
SampleDisplacementsCompute(_Crest_DynamicWavesTarget, cascade._Resolution, uv, 1.0, result);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
// We are sampling from Dynamic Waves.
|
||||
const Cascade cascade = Cascade::MakeDynamicWaves(slice0);
|
||||
const float3 uv = cascade.WorldToUV(positionWSXZ);
|
||||
result += cascade.SampleDynamicWavesDisplacement(uv, _Crest_HorizontalDisplace, _Crest_DisplaceClamp);
|
||||
}
|
||||
|
||||
_Crest_DynamicWavesTarget[uint3(id.xy, slice0)] = float4(result, 0.0);
|
||||
}
|
||||
|
||||
void ShapeCombineCopyDynamicWaves(uint3 id)
|
||||
{
|
||||
_Crest_AnimatedWavesTarget[id] += _Crest_DynamicWavesTarget[id];
|
||||
// We are combining from the target which matches the Animated Waves descriptor.
|
||||
id.z = _Crest_LodIndex;
|
||||
ShapeCombine(id);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_FLOW_ON(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_FLOW_ON_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_DYNAMIC_WAVE_SIM_ON(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineBase(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombineDynamicWaves(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineDynamicWaves(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombineDynamicWaves_DISABLE_COMBINE(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineDynamicWaves(id); }
|
||||
[numthreads(THREAD_GROUP_SIZE_X, THREAD_GROUP_SIZE_Y, 1)] void ShapeCombineCopyDynamicWaves(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineCopyDynamicWaves(id); }
|
||||
m_CrestKernelDefault(ShapeCombineAnimatedWaves)
|
||||
m_CrestKernelDefault(ShapeCopyAnimatedWaves)
|
||||
m_CrestKernelDefault(ShapeCombineDynamicWaves)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestShorelineColor
|
||||
|
||||
#pragma multi_compile_local __ d_Crest_ShorelineColorSource_ShorelineDistance
|
||||
|
||||
@@ -3,16 +3,26 @@
|
||||
|
||||
// Solves 2D wave equation
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestUpdateDynamicWaves
|
||||
|
||||
#pragma multi_compile _ CREST_FLOW_ON_INTERNAL
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
// Cascade macros expect this to be available.
|
||||
#define g_Crest_CascadeDynamicWavesSource _Crest_Source
|
||||
Texture2DArray _Crest_Source;
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Keywords.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/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
RWTexture2DArray<float2> _Crest_Target;
|
||||
RWTexture2DArray<m_Float2> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float _Crest_Damping;
|
||||
@@ -37,15 +47,15 @@ float ComputeWaveSpeed(float wavelength, float g)
|
||||
void UpdateDynamicWaves(uint3 id)
|
||||
{
|
||||
// Slice to sample previous frames data from. LOD change takes into account shifting of the cascades in scale.
|
||||
const float sliceIndexSource = id.z + _Crest_LodChange;
|
||||
const uint sliceIndexSource = id.z + _Crest_LodChange;
|
||||
const Cascade cascadeSource = Cascade::MakeDynamicWavesSource(sliceIndexSource);
|
||||
|
||||
// Off either end of the cascade. Not useful to sample anything from previous
|
||||
// frame, as we do not produce any new data from sources of waves.
|
||||
if (sliceIndexSource < 0.0 || sliceIndexSource >= cascadeSource._Count)
|
||||
if (sliceIndexSource < 0 || sliceIndexSource >= g_Crest_LodCount)
|
||||
{
|
||||
// Always initialise with 0 values.
|
||||
_Crest_Target[id] = (float2)0;
|
||||
_Crest_Target[id] = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,12 +82,17 @@ void UpdateDynamicWaves(uint3 id)
|
||||
// Wave reflections off geometry.
|
||||
if (waterDepth <= 0.0)
|
||||
{
|
||||
_Crest_Target[id] = float2(0.0, 0.0);
|
||||
_Crest_Target[id] = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
float2 worldPosXZFlowed = worldPosXZ;
|
||||
|
||||
#if d_Crest_FlowLod
|
||||
const half2 velocity = Cascade::MakeFlow(sliceIndex).SampleFlow(worldPosXZ);
|
||||
const float2 worldPosXZFlowed = worldPosXZ - dt * velocity;
|
||||
worldPosXZFlowed -= velocity * dt;
|
||||
#endif
|
||||
|
||||
const float3 uv_source = cascadeSource.WorldToUV(worldPosXZFlowed);
|
||||
|
||||
// weighting for source position - weight 0 for off texture accesses to stop streaky artifacts
|
||||
@@ -142,7 +157,7 @@ void UpdateDynamicWaves(uint3 id)
|
||||
vtp = 0.0;
|
||||
}
|
||||
|
||||
_Crest_Target[id] = float2(ftp, vtp);
|
||||
_Crest_Target[id] = m_Float2Constructor(ftp, vtp);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestUpdateFoam
|
||||
|
||||
#pragma multi_compile _ CREST_FLOW_ON_INTERNAL
|
||||
|
||||
// Cascade macros expect this to be available.
|
||||
#define g_Crest_CascadeFoamSource _Crest_Source
|
||||
Texture2DArray _Crest_Source;
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Keywords.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/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
RWTexture2DArray<float> _Crest_Target;
|
||||
@@ -21,7 +31,6 @@ float _Crest_WaveFoamCoverage;
|
||||
float _Crest_ShorelineFoamMaxDepth;
|
||||
float _Crest_ShorelineFoamStrength;
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_SimDeltaTimePrev;
|
||||
float _Crest_LodChange;
|
||||
bool _Crest_NeedsPrewarming;
|
||||
uint _Crest_MinimumWavesSlice;
|
||||
@@ -39,10 +48,14 @@ void UpdateFoam(uint3 id)
|
||||
|
||||
// Sample from previous frame.
|
||||
{
|
||||
float2 positionXZ = worldPosXZ;
|
||||
|
||||
#if d_Crest_FlowLod
|
||||
const half2 velocity = Cascade::MakeFlow(slice0).SampleFlow(worldPosXZ);
|
||||
const float2 positionXZ = worldPosXZ - _Crest_SimDeltaTime * velocity;
|
||||
positionXZ -= velocity * _Crest_SimDeltaTime;
|
||||
#endif
|
||||
// Slice to sample previous frames data from. LOD change takes into account shifting of the cascades in scale.
|
||||
const float sliceIndexSource = clamp(id.z + _Crest_LodChange, 0.0, cascade._Count - 1.0);
|
||||
const uint sliceIndexSource = ComputeSlice(slice0, _Crest_LodChange, g_Crest_LodCount - 1);
|
||||
foam = Cascade::MakeFoamSource(sliceIndexSource).SampleFoamOverflow(positionXZ, 1.0);
|
||||
}
|
||||
|
||||
@@ -53,9 +66,16 @@ void UpdateFoam(uint3 id)
|
||||
// accumulation of foam and causes overshoots when _Crest_WaveFoamStrength is less than 1.0.
|
||||
float simDeltaTime = _Crest_NeedsPrewarming ? max(_Crest_SimDeltaTime, min(1.0, _Crest_WaveFoamStrength - 1.0) / _Crest_FoamFadeRate) : _Crest_SimDeltaTime;
|
||||
|
||||
// Limit wave contributions at low water scales only where filtering is needed.
|
||||
uint filteredSlice = slice0;
|
||||
if (g_Crest_WaterScale <= 8)
|
||||
{
|
||||
filteredSlice = max(_Crest_MinimumWavesSlice, filteredSlice);
|
||||
}
|
||||
|
||||
// The determinant of the displacement Jacobian is a good measure for turbulence.
|
||||
float det;
|
||||
const half3 displacement = Cascade::MakeAnimatedWaves(max(_Crest_MinimumWavesSlice, slice0)).SampleDisplacement(worldPosXZ, det);
|
||||
const half3 displacement = Cascade::MakeAnimatedWaves(filteredSlice).SampleDisplacement(worldPosXZ, det);
|
||||
foam += 5.0 * simDeltaTime * _Crest_WaveFoamStrength * saturate( _Crest_WaveFoamCoverage - det );
|
||||
|
||||
// Prewarm shoreline foam. 1.0 / _Crest_FoamFadeRate perfectly matches a paused water in edit mode which is fine for
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
// Soft shadow term is red, hard shadow term is green.
|
||||
|
||||
#pragma exclude_renderers glcore gles3
|
||||
|
||||
#pragma kernel CrestUpdateShadowsBRP _BRP
|
||||
#pragma kernel CrestUpdateShadowsHRP _HRP
|
||||
#pragma kernel CrestUpdateShadowsURP _URP
|
||||
@@ -11,13 +13,19 @@
|
||||
#pragma multi_compile __ SHADOWS_SPLIT_SPHERES
|
||||
#pragma multi_compile __ SHADOWS_SINGLE_CASCADE
|
||||
|
||||
// Cascade macros expect this to be available.
|
||||
#define g_Crest_CascadeShadowSource _Crest_Source
|
||||
Texture2DArray _Crest_Source;
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Compute.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/RP/Shadows.hlsl"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Keywords.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/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
// Noise functions used for jitter.
|
||||
@@ -33,7 +41,7 @@ bool _Crest_SampleColorMap;
|
||||
float3 _Crest_Absorption;
|
||||
float3 _Crest_Scattering;
|
||||
|
||||
RWTexture2DArray<float2> _Crest_Target;
|
||||
RWTexture2DArray<m_Float2> _Crest_Target;
|
||||
|
||||
|
||||
m_CrestNameSpace
|
||||
@@ -79,7 +87,7 @@ void UpdateShadows(const uint3 id)
|
||||
positionWS.y = g_Crest_WaterCenter.y;
|
||||
|
||||
// Shadow from last frame. Manually implement black border.
|
||||
const float sliceIndexSource = clamp((int)slice0 + g_Crest_LodChange, 0.0, g_Crest_LodCount - 1.0);
|
||||
const uint sliceIndexSource = ComputeSlice(slice0, g_Crest_LodChange, g_Crest_LodCount - 1);
|
||||
half2 shadow = Cascade::MakeShadowSource(sliceIndexSource).SampleShadowOverflow(positionWS.xz, 1.0);
|
||||
|
||||
// Add displacement so shorelines do not receive shadows incorrectly.
|
||||
@@ -108,15 +116,19 @@ void UpdateShadows(const uint3 id)
|
||||
half3 absorption = _Crest_Absorption;
|
||||
half3 scattering = _Crest_Scattering;
|
||||
|
||||
#if d_Crest_AbsorptionLod
|
||||
if (g_Crest_SampleAbsorptionSimulation)
|
||||
{
|
||||
absorption = Cascade::MakeAbsorption(slice0).SampleAbsorption(positionWS.xz);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if d_Crest_ScatteringLod
|
||||
if (g_Crest_SampleScatteringSimulation)
|
||||
{
|
||||
scattering = Cascade::MakeScattering(slice0).SampleScattering(positionWS.xz);
|
||||
}
|
||||
#endif
|
||||
|
||||
half3 extinction = absorption + scattering;
|
||||
half factor = saturate(min(min(extinction.x, extinction.y), extinction.z) * g_Crest_DynamicSoftShadowsFactor);
|
||||
@@ -146,7 +158,7 @@ void UpdateShadows(const uint3 id)
|
||||
shadow = lerp(shadow, shadowThisFrame, _Crest_JitterDiameters_CurrentFrameWeights.zw * _Crest_SimDeltaTime * 60.0);
|
||||
}
|
||||
|
||||
_Crest_Target[id] = shadow;
|
||||
_Crest_Target[id] = m_Float2FromFloat2(shadow);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
@@ -1,176 +1,4 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Soft shadow term is red, hard shadow term is green. In HDRP, hard shadows are not computed and y channel will be 0.
|
||||
|
||||
#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/Globals.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
// Noise functions used for jitter.
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Noise/Noise.hlsl"
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
// Settings._jitterDiameterSoft, Settings._jitterDiameterHard, Settings._currentFrameWeightSoft, Settings._currentFrameWeightHard
|
||||
float4 _Crest_JitterDiameters_CurrentFrameWeights;
|
||||
float _Crest_SimDeltaTime;
|
||||
|
||||
bool _Crest_ClearShadows;
|
||||
|
||||
float3 _Crest_CenterPos;
|
||||
float3 _Crest_Scale;
|
||||
float4x4 _Crest_MainCameraProjectionMatrix;
|
||||
|
||||
bool _Crest_SampleColorMap;
|
||||
float3 _Crest_Absorption;
|
||||
float3 _Crest_Scattering;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
uint id : SV_VertexID;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float3 positionWS : 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);
|
||||
float2 uv = GetFullScreenTriangleTexCoord(input.id);
|
||||
|
||||
// World position from UV.
|
||||
output.positionWS.xyz = float3(uv.x - 0.5, 0.0, uv.y - 0.5) * _Crest_Scale * 4.0 + _Crest_CenterPos;
|
||||
output.positionWS.y = g_Crest_WaterCenter.y;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
half SampleShadows(const float4 i_positionWS);
|
||||
half ComputeShadowFade(const float4 i_positionWS);
|
||||
|
||||
// Compiler shows warning when using intermediate returns, disable this.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4000)
|
||||
half ComputeShadow(const float4 i_positionWS, const float i_jitterDiameter, const half i_terrainHeight)
|
||||
{
|
||||
float4 positionWS = i_positionWS;
|
||||
|
||||
if (i_jitterDiameter > 0.0)
|
||||
{
|
||||
// Add jitter.
|
||||
positionWS.xz += i_jitterDiameter * (hash33(uint3(abs(positionWS.xz * 10.0), _Time.y * 120.0)) - 0.5).xy;
|
||||
|
||||
// Shadow Bleeding.
|
||||
// If we are not within a terrain, then check for shadow bleeding.
|
||||
if (i_positionWS.y > i_terrainHeight)
|
||||
{
|
||||
// WorldToSafeUV
|
||||
half terrainHeight = Cascade::MakeDepth(_Crest_LodIndex).SampleSceneHeight(positionWS.xz);
|
||||
|
||||
// If our current position is below the jittered terrain height, then we have landed within a terrain and
|
||||
// we do not want to sample those shadows.
|
||||
if (i_positionWS.y < terrainHeight)
|
||||
{
|
||||
// Return no shadows.
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SampleShadows(positionWS);
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
half2 Fragment(Varyings input)
|
||||
{
|
||||
float4 positionWS = float4(input.positionWS.xyz, 1.0);
|
||||
|
||||
// Shadow from last frame. Manually implement black border.
|
||||
const float sliceIndexSource = clamp((int)_Crest_LodIndex + g_Crest_LodChange, 0.0, g_Crest_LodCount - 1.0);
|
||||
half2 shadow = Cascade::MakeShadowSource(sliceIndexSource).SampleShadowOverflow(positionWS.xz, 1.0);
|
||||
|
||||
// Add displacement so shorelines do not receive shadows incorrectly.
|
||||
positionWS.xyz += Cascade::MakeAnimatedWaves(_Crest_LodIndex).SampleDisplacement(positionWS.xz);
|
||||
|
||||
// This was calculated in vertex but we have to sample sea level offset in fragment.
|
||||
float4 mainCameraCoordinates = mul(_Crest_MainCameraProjectionMatrix, positionWS);
|
||||
|
||||
// Check if the current sample is visible in the main camera (and therefore the shadow map can be sampled). This is
|
||||
// required as the shadow buffer is world aligned and surrounds viewer.
|
||||
float3 projected = mainCameraCoordinates.xyz / mainCameraCoordinates.w;
|
||||
if (projected.z < 1.0 && projected.z > 0.0 && abs(projected.x) < 1.0 && abs(projected.y) < 1.0)
|
||||
{
|
||||
half2 shadowThisFrame = 1.0;
|
||||
|
||||
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
|
||||
positionWS.xyz -= _WorldSpaceCameraPos.xyz;
|
||||
#endif
|
||||
|
||||
half terrainHeight = Cascade::MakeDepth(_Crest_LodIndex).SampleSceneHeight(positionWS.xz);
|
||||
|
||||
half softJitter = _Crest_JitterDiameters_CurrentFrameWeights[CREST_SHADOW_INDEX_SOFT];
|
||||
|
||||
if (_Crest_SampleColorMap)
|
||||
{
|
||||
half3 absorption = _Crest_Absorption;
|
||||
half3 scattering = _Crest_Scattering;
|
||||
|
||||
if (g_Crest_SampleAbsorptionSimulation)
|
||||
{
|
||||
absorption = Cascade::MakeAbsorption(_Crest_LodIndex).SampleAbsorption(positionWS.xz);
|
||||
}
|
||||
|
||||
if (g_Crest_SampleScatteringSimulation)
|
||||
{
|
||||
scattering = Cascade::MakeScattering(_Crest_LodIndex).SampleScattering(positionWS.xz);
|
||||
}
|
||||
|
||||
half3 extinction = absorption + scattering;
|
||||
half factor = saturate(min(min(extinction.x, extinction.y), extinction.z) * g_Crest_DynamicSoftShadowsFactor);
|
||||
softJitter = (1.0 - factor) * k_Crest_MaximumShadowJitter;
|
||||
}
|
||||
|
||||
// Add soft shadowing data.
|
||||
shadowThisFrame[CREST_SHADOW_INDEX_SOFT] = ComputeShadow
|
||||
(
|
||||
positionWS,
|
||||
softJitter,
|
||||
terrainHeight
|
||||
);
|
||||
|
||||
#ifdef CREST_SAMPLE_SHADOW_HARD
|
||||
// Add hard shadowing data.
|
||||
shadowThisFrame[CREST_SHADOW_INDEX_HARD] = ComputeShadow
|
||||
(
|
||||
positionWS,
|
||||
_Crest_JitterDiameters_CurrentFrameWeights[CREST_SHADOW_INDEX_HARD],
|
||||
terrainHeight
|
||||
);
|
||||
#endif
|
||||
|
||||
shadowThisFrame = (half2)1.0 - saturate(shadowThisFrame + ComputeShadowFade(positionWS));
|
||||
|
||||
shadow = lerp(shadow, shadowThisFrame, _Crest_JitterDiameters_CurrentFrameWeights.zw * _Crest_SimDeltaTime * 60.0);
|
||||
}
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestVertex
|
||||
m_CrestFragment(half2)
|
||||
// Replaced with UpdateShadow.compute.
|
||||
|
||||
Reference in New Issue
Block a user