修改水
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9c719886e7504196818710a8c627eb3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,85 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Absorption/Color"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_AbsorptionColor("Absorption", Color) = (0.3416268229484558, 0.6954545974731445, 0.8500000238418579, 0.10196078568696976)
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Absorption("Absorption", Vector) = (0.0, 0.09803921729326248, 0.20000000298023225, 0.0)
|
||||
|
||||
[Toggle(d_Feather)]
|
||||
_Crest_Feather("Feather At UV Extents", Float) = 0
|
||||
_Crest_FeatherWidth("Feather Width", Range(0.001, 0.5)) = 0.1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
ZWrite Off
|
||||
ColorMask RGB
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#pragma shader_feature_local d_Feather
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 vertex : POSITION;
|
||||
#if d_Feather
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
#if d_Feather
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
half4 _Crest_Absorption;
|
||||
half _Crest_FeatherWidth;
|
||||
CBUFFER_END
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings output;
|
||||
float3 positionWS = mul(unity_ObjectToWorld, float4(input.vertex, 1.0)).xyz;
|
||||
output.vertex = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
#if d_Feather
|
||||
output.uv = input.uv;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 Fragment(Varyings input) : SV_Target
|
||||
{
|
||||
half4 color = _Crest_Absorption;
|
||||
color.a = 1.0;
|
||||
#if d_Feather
|
||||
color.a *= WaveHarmonic::Crest::FeatherWeightFromUV(input.uv, _Crest_FeatherWidth);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a866ef153cd246c58ef554043275848
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Albedo/Color"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[MainTexture] _Crest_Texture("Albedo", 2D) = "white" {}
|
||||
_Crest_Color("Color", Color) = (1.0, 1.0, 1.0, 1.0)
|
||||
_Crest_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
|
||||
|
||||
[Enum(UnityEngine.Rendering.BlendMode)]
|
||||
_Crest_BlendModeSource("Source Blend Mode", Int) = 5
|
||||
[Enum(UnityEngine.Rendering.BlendMode)]
|
||||
_Crest_BlendModeTarget("Target Blend Mode", Int) = 10
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend [_Crest_BlendModeSource] [_Crest_BlendModeTarget]
|
||||
|
||||
ZWrite Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 vertex : POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
fixed4 color : COLOR;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
SamplerState sampler_Crest_Texture;
|
||||
float4 _Crest_Texture_ST;
|
||||
|
||||
half4 _Crest_Color;
|
||||
half _Crest_Cutoff;
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings output;
|
||||
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.color = input.color;
|
||||
return output;
|
||||
}
|
||||
|
||||
fixed4 Fragment(Varyings i) : SV_Target
|
||||
{
|
||||
fixed4 color = _Crest_Texture.Sample(sampler_Crest_Texture, i.uv) * _Crest_Color;
|
||||
clip(color.a - _Crest_Cutoff + 0.0001);
|
||||
return color * i.color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa7b1bc481cf34f229ffd793be4a01c3
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,85 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Animated Waves/Add From Texture"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[MainTexture] _Crest_Texture("Texture", 2D) = "black" {}
|
||||
_Crest_Strength( "Strength", float ) = 1
|
||||
|
||||
[Toggle(d_HeightsOnly)]
|
||||
_Crest_HeightsOnly("Heights Only", Float) = 1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Blend One One
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#pragma shader_feature_local d_HeightsOnly
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
SamplerState sampler_Crest_Texture;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float4 _Crest_Texture_ST;
|
||||
float _Crest_Strength;
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
|
||||
|
||||
o.uv = TRANSFORM_TEX(input.uv, _Crest_Texture);
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
half3 texSample = _Crest_Texture.Sample(sampler_Crest_Texture, input.uv).xyz;
|
||||
|
||||
half3 displacement = (half3)0.0;
|
||||
#if d_HeightsOnly
|
||||
displacement.y = texSample.x * _Crest_Strength;
|
||||
#else
|
||||
displacement.xyz = texSample * _Crest_Strength;
|
||||
#endif
|
||||
|
||||
return _Crest_Weight * half4(displacement, 0.0);
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62ff65b047d684524b06152100f725bb
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Push water under the geometry. Needs to be rendered into all LODs - set Octave Wave length to 0.
|
||||
|
||||
Shader "Crest/Inputs/Animated Waves/Push Water Under Convex Hull"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
BlendOp Min
|
||||
Cull Front
|
||||
ColorMask G
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.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"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float3 worldPos : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
o.worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(o.worldPos, 1.0));
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 Fragment(Varyings input)
|
||||
{
|
||||
// Write displacement to get from sea level of water to the y value of this geometry.
|
||||
half seaLevelOffset = Cascade::MakeLevel(_Crest_LodIndex).SampleLevel(input.worldPos.xz);
|
||||
return half4(0.0, _Crest_Weight * (input.worldPos.y - g_Crest_WaterCenter.y - seaLevelOffset), 0.0, 0.0);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestVertex
|
||||
m_CrestFragment(half4)
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 170672f06b4574545ba8305cb7d11091
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// This writes straight into the displacement texture and sets the water height to the y value of the geometry.
|
||||
|
||||
Shader "Crest/Inputs/Animated Waves/Set Water Height Using Geometry"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[Enum(ColorWriteMask)]
|
||||
_Crest_ColorMask("Color Mask", Int) = 15
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend Off
|
||||
ColorMask [_Crest_ColorMask]
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.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"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float3 worldPos : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
o.worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(o.worldPos, 1.0));
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 Fragment(Varyings input)
|
||||
{
|
||||
half seaLevelOffset = Cascade::MakeLevel(_Crest_LodIndex).SampleLevel(input.worldPos.xz);
|
||||
|
||||
// Write displacement to get from sea level of water to the y value of this geometry
|
||||
float height = input.worldPos.y - g_Crest_WaterCenter.y - seaLevelOffset;
|
||||
return half4(0.0, _Crest_Weight * height, 0.0, 0.0);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestVertex
|
||||
m_CrestFragment(half4)
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3acaa68c12f5e435290dbeebd2684241
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,87 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Animated Waves/Wave Particle"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_Amplitude( "Amplitude", float ) = 1
|
||||
_Crest_Radius( "Radius", float) = 3
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "DisableBatching" = "True" }
|
||||
|
||||
Pass
|
||||
{
|
||||
Blend One One
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_Radius;
|
||||
float _Crest_Amplitude;
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 worldOffsetScaledXZ : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
float3 centerPos = unity_ObjectToWorld._m03_m13_m23;
|
||||
o.worldOffsetScaledXZ = worldPos.xz - centerPos.xz;
|
||||
|
||||
// shape is symmetric around center with known radius - fix the vert positions to perfectly wrap the shape.
|
||||
o.worldOffsetScaledXZ = sign(o.worldOffsetScaledXZ);
|
||||
float4 newWorldPos = float4(centerPos, 1.0);
|
||||
newWorldPos.xz += o.worldOffsetScaledXZ * _Crest_Radius;
|
||||
|
||||
// Correct for displacement
|
||||
newWorldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, newWorldPos);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
// power 4 smoothstep - no normalize needed
|
||||
// credit goes to stubbe's shadertoy: https://www.shadertoy.com/view/4ldSD2
|
||||
float r2 = dot( input.worldOffsetScaledXZ, input.worldOffsetScaledXZ);
|
||||
if( r2 > 1.0 )
|
||||
return (float4)0.0;
|
||||
|
||||
r2 = 1.0 - r2;
|
||||
|
||||
float y = r2 * r2 * _Crest_Amplitude;
|
||||
|
||||
return float4(0.0, y * _Crest_Weight, 0.0, 0.0);
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c1519a4fd6d8a4a62b59870be79b3857
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,107 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Dynamic Waves/Add Bump"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_Amplitude( "Amplitude", float ) = 1
|
||||
_Crest_Radius( "Radius", float) = 3
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend One One
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_Radius;
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_Amplitude;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float2 texcoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 worldOffsetScaled : TEXCOORD0;
|
||||
float2 uv : TEXCOORD1;
|
||||
};
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
o.positionCS = UnityObjectToClipPos(input.positionOS);
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0));
|
||||
float3 centerPos = unity_ObjectToWorld._m03_m13_m23;
|
||||
o.worldOffsetScaled.xy = worldPos.xz - centerPos.xz;
|
||||
|
||||
// shape is symmetric around center with known radius - fix the vert positions to perfectly wrap the shape.
|
||||
o.worldOffsetScaled.xy = sign(o.worldOffsetScaled.xy);
|
||||
float4 newWorldPos = float4(centerPos, 1.0);
|
||||
newWorldPos.xz += o.worldOffsetScaled.xy * _Crest_Radius;
|
||||
|
||||
// Correct for displacement
|
||||
newWorldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, newWorldPos);
|
||||
o.uv = Cascade::MakeDynamicWaves(_Crest_LodIndex).WorldToUV(newWorldPos.xz);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Fragment(Varyings input)
|
||||
{
|
||||
// power 4 smoothstep - no normalize needed
|
||||
// credit goes to stubbe's shadertoy: https://www.shadertoy.com/view/4ldSD2
|
||||
float r2 = dot(input.worldOffsetScaled.xy, input.worldOffsetScaled.xy);
|
||||
if (r2 > 1.0)
|
||||
return (float4)0.0;
|
||||
|
||||
r2 = 1.0 - r2;
|
||||
|
||||
float y = r2 * r2;
|
||||
y = pow(y, 0.05);
|
||||
y *= _Crest_Amplitude;
|
||||
|
||||
y /= g_Crest_LodCount;
|
||||
|
||||
// Feather edges to reduce streaking without introducing reflections.
|
||||
y *= FeatherWeightFromUV(input.uv, 0.1);
|
||||
|
||||
// accelerate velocities
|
||||
return float4(0.0, _Crest_SimDeltaTime * y, 0.0, 0.0);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestVertex
|
||||
m_CrestFragment(float4)
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7e8ca175bc339b74880584aa1544100e
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Dynamic Waves/Dampen Circle"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_Radius("Radius", float) = 3
|
||||
_Crest_Strength("Strength", Range(0, 100)) = 10
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_Radius;
|
||||
float _Crest_Strength;
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 worldOffsetScaled : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
o.positionCS = UnityObjectToClipPos(input.positionOS);
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
float3 centerPos = unity_ObjectToWorld._m03_m13_m23;
|
||||
o.worldOffsetScaled.xy = worldPos.xz - centerPos.xz;
|
||||
|
||||
// shape is symmetric around center with known radius - fix the vert positions to perfectly wrap the shape.
|
||||
o.worldOffsetScaled.xy = sign(o.worldOffsetScaled.xy);
|
||||
float4 newWorldPos = float4(centerPos, 1.0);
|
||||
newWorldPos.xz += o.worldOffsetScaled.xy * _Crest_Radius;
|
||||
|
||||
// Correct for displacement
|
||||
newWorldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, newWorldPos);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
// power 4 smoothstep - no normalize needed
|
||||
// credit goes to stubbe's shadertoy: https://www.shadertoy.com/view/4ldSD2
|
||||
float r2 = dot(input.worldOffsetScaled.xy, input.worldOffsetScaled.xy);
|
||||
if (r2 > 1.0) return (float4)0.0;
|
||||
r2 = 1.0 - r2;
|
||||
float val = r2 * r2;
|
||||
|
||||
float weight = val * _Crest_Strength * _Crest_SimDeltaTime * _Crest_Weight;
|
||||
return float4(0.0, 0.0, 0.0, weight);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7ab71b44865e403cb0a074713fb3ff7
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,110 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Flow/Add From Texture"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[MainTexture] _Crest_Texture("Flow Map", 2D) = "white" {}
|
||||
_Crest_Strength( "Strength", float ) = 1
|
||||
|
||||
[Toggle(d_FlipX)]
|
||||
_Crest_FlipX("Flip X", Float) = 0
|
||||
[Toggle(d_FlipZ)]
|
||||
_Crest_FlipZ("Flip Z", Float) = 0
|
||||
[Toggle(d_NegativeValues)]
|
||||
_Crest_NegativeValues("Has Negative Values", Float) = 0
|
||||
|
||||
[Toggle(d_Feather)]
|
||||
_Crest_Feather("Feather At UV Extents", Float) = 0
|
||||
_Crest_FeatherWidth("Feather Width", Range(0.001, 0.5)) = 0.1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Blend One One
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#pragma shader_feature_local d_FlipX
|
||||
#pragma shader_feature_local d_FlipZ
|
||||
#pragma shader_feature_local d_Feather
|
||||
#pragma shader_feature_local d_NegativeValues
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#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"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
SamplerState sampler_Crest_Texture;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float4 _Crest_Texture_ST;
|
||||
float _Crest_Strength;
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
half _Crest_FeatherWidth;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
|
||||
|
||||
o.uv = TRANSFORM_TEX(input.uv, _Crest_Texture);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 flow = _Crest_Texture.Sample(sampler_Crest_Texture, input.uv).xy;
|
||||
|
||||
#if !d_NegativeValues
|
||||
// From 0..1 to -1..1.
|
||||
flow = flow * 2.0 - 1.0;
|
||||
#endif
|
||||
|
||||
#if d_Feather
|
||||
flow *= WaveHarmonic::Crest::FeatherWeightFromUV(input.uv, _Crest_FeatherWidth);
|
||||
#endif
|
||||
|
||||
#if d_FlipX
|
||||
flow.x *= -1.0;
|
||||
#endif
|
||||
#if d_FlipZ
|
||||
flow.y *= -1.0;
|
||||
#endif
|
||||
|
||||
return float4(flow * _Crest_Strength * _Crest_Weight, 0.0, 0.0);
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8958e526a8d9b403e878e13b80405796
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,101 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Flow/Fixed Direction"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_Speed("Speed", Range(0.0, 30.0)) = 1.0
|
||||
_Crest_Direction("Direction", Range(0.0, 1.0)) = 0.0
|
||||
|
||||
[Toggle(d_Feather)]
|
||||
_Crest_Feather("Feather At UV Extents", Float) = 0
|
||||
_Crest_FeatherWidth("Feather Width", Range(0.001, 0.5)) = 0.1
|
||||
|
||||
[Toggle(d_ApplyRotation)]
|
||||
_Crest_ApplyRotation("Apply Transform XZ Rotation", Float) = 0
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#pragma shader_feature_local d_Feather
|
||||
#pragma shader_feature_local d_ApplyRotation
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#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"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_Speed;
|
||||
float _Crest_Direction;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
half _Crest_FeatherWidth;
|
||||
half _Crest_Weight;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
#if d_Feather
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 vel : TEXCOORD0;
|
||||
#if d_Feather
|
||||
float2 uv : TEXCOORD1;
|
||||
#endif
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
|
||||
|
||||
o.vel = _Crest_Speed * float2(cos(_Crest_Direction * 6.283185), sin(_Crest_Direction * 6.283185));
|
||||
|
||||
#if d_Feather
|
||||
o.uv = input.uv;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 flow = input.vel;
|
||||
|
||||
#if d_Feather
|
||||
flow *= WaveHarmonic::Crest::FeatherWeightFromUV(input.uv, _Crest_FeatherWidth);
|
||||
#endif
|
||||
|
||||
#if d_ApplyRotation
|
||||
const float2 rotation = normalize(unity_ObjectToWorld._m00_m20.xy);
|
||||
flow = flow.x * rotation + flow.y * float2(-rotation.y, rotation.x);
|
||||
#endif
|
||||
|
||||
return float4(flow * _Crest_Weight, 0.0, 0.0);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5198aecab500144dbb5ee73bad91640a
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Foam/Add From Texture"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[MainTexture] _Crest_Texture("Texture", 2D) = "white" {}
|
||||
_Crest_Strength( "Strength", float ) = 1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Blend One One
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
SamplerState sampler_Crest_Texture;
|
||||
float _Crest_Strength;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_SimDeltaTime;
|
||||
float4 _Crest_Texture_ST;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
half _Crest_Weight;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
|
||||
|
||||
o.uv = TRANSFORM_TEX(input.uv, _Crest_Texture);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
return _Crest_Texture.Sample(sampler_Crest_Texture, input.uv) * _Crest_Weight * _Crest_Strength * _Crest_SimDeltaTime;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 955fe6ade516e42e0ab0b0bbb116170a
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Foam/Add From Vertex Colors"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_Strength("Strength", float) = 1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Blend One One
|
||||
|
||||
Pass
|
||||
{
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_Strength;
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
float4 col : COLOR0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float4 col : COLOR0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(worldPos, 1.0));
|
||||
|
||||
o.col = input.col;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
return _Crest_Strength * input.col.x * _Crest_SimDeltaTime * _Crest_Weight;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f51a8e7d464dd4fb0a51d0c61b8ca417
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a69be96a1d36c4f8b9f29717e0a95d94
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
RWTexture2DArray<float3> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
int _Crest_Blend;
|
||||
float _Crest_Weight;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float _Crest_FeatherWidth;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeAbsorption(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
half weight = _Crest_Weight;
|
||||
|
||||
// Feather boundaries.
|
||||
weight *= FeatherWeightFromUV(uv, _Crest_FeatherWidth);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const half4 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0);
|
||||
const half3 target = _Crest_Target[id];
|
||||
weight *= source.a;
|
||||
|
||||
_Crest_Target[id] = Blend(_Crest_Blend, weight, 1.0, source.xyz, target);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82d4c3f5aac084c2bad20d0a31f1168a
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,248 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestTransferWaves
|
||||
|
||||
#pragma multi_compile_local __ d_Texture d_TextureBlend
|
||||
|
||||
#if defined(d_TextureBlend)
|
||||
#define d_Texture 1
|
||||
#endif
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
Texture2DArray _Crest_WaveBuffer;
|
||||
RWTexture2DArray<float4> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float4 _Crest_WaveBufferParameters[MAX_LOD_COUNT];
|
||||
float2 _Crest_AxisX;
|
||||
float _Crest_Weight;
|
||||
float _Crest_FeatherWidth;
|
||||
float _Crest_AttenuationInShallows;
|
||||
float _Crest_RespectShallowWaterAttenuation;
|
||||
float _Crest_MaximumAttenuationDepth;
|
||||
float _Crest_WaveResolutionMultiplier;
|
||||
float _Crest_TransitionalWavelengthThreshold;
|
||||
|
||||
// Texture
|
||||
#if d_Texture
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
bool _Crest_NegativeValues;
|
||||
int _Crest_Blend;
|
||||
#endif
|
||||
CBUFFER_END
|
||||
|
||||
#if d_Texture
|
||||
#define m_None 0
|
||||
#define m_FromZero 4
|
||||
#define m_FromZeroNormalized 5
|
||||
#endif // d_Texture
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void TransferWaves(uint3 id)
|
||||
{
|
||||
const uint slice0 = id.z;
|
||||
|
||||
const float4 parameters = _Crest_WaveBufferParameters[slice0];
|
||||
const uint first = parameters.x;
|
||||
const uint last = parameters.y;
|
||||
const half transition = parameters.w;
|
||||
|
||||
#if !d_TextureBlend
|
||||
// Additive only. All wavelengths filtered out for this LOD so nothing to do.
|
||||
if (parameters.x < 0 || parameters.y < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const Cascade cascade = Cascade::MakeAnimatedWaves(slice0);
|
||||
const float2 positionWS = cascade.IDToWorld(id.xy);
|
||||
|
||||
half _weight = _Crest_Weight;
|
||||
half alpha = 0.0;
|
||||
|
||||
#if d_Texture
|
||||
float2 uvPainted = (positionWS - _Crest_TexturePosition) / _Crest_TextureSize;
|
||||
// Clockwise transform rotation.
|
||||
uvPainted = uvPainted.x * float2(_Crest_TextureRotation.y, -_Crest_TextureRotation.x) + uvPainted.y * _Crest_TextureRotation;
|
||||
uvPainted += 0.5;
|
||||
|
||||
// Feather boundaries.
|
||||
_weight *= FeatherWeightFromUV(uvPainted, _Crest_FeatherWidth);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (_weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
alpha = _weight;
|
||||
|
||||
// Initialize or "use of potentially uninitialized variable" due to early return.
|
||||
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;
|
||||
|
||||
if (!_Crest_NegativeValues)
|
||||
{
|
||||
// -1.0 to 1.0
|
||||
axis = axis * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
float axisLength2 = dot(axis, axis);
|
||||
|
||||
// Zero data so exit early and apply blending if needed.
|
||||
if (!(axisLength2 > 0.00001))
|
||||
{
|
||||
#if d_TextureBlend
|
||||
if (_Crest_Blend > m_None)
|
||||
{
|
||||
// If zero affects blend weight, then reduce alpha by axis length so that it
|
||||
// accounts for zero data.
|
||||
alpha = 0.0;
|
||||
}
|
||||
|
||||
_Crest_Target[id] *= 1.0 - alpha;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
axisLength = sqrt(axisLength2);
|
||||
|
||||
// Alpha blending based on data.
|
||||
if (_Crest_Blend == m_FromZeroNormalized)
|
||||
{
|
||||
// Normalize so even small amounts fully removes existing waves.
|
||||
alpha *= length(normalize(axis));
|
||||
}
|
||||
else if (_Crest_Blend == m_FromZero)
|
||||
{
|
||||
alpha *= axisLength;
|
||||
}
|
||||
|
||||
// Rotate axis with transform rotation to keep axis in local space.
|
||||
axis = axis.x * _Crest_TextureRotation.yx + axis.y * float2(-_Crest_TextureRotation.x, _Crest_TextureRotation.y);
|
||||
|
||||
// Add wind (counterclockwise).
|
||||
axis = axis.x * _Crest_AxisX + axis.y * float2(-_Crest_AxisX.y, _Crest_AxisX.x);
|
||||
|
||||
// Quantize wave direction.
|
||||
const float axisHeading = atan2(axis.y, axis.x) + 2.0 * 3.141592654;
|
||||
const float dTheta = 0.5 * 0.314159265;
|
||||
const float rem = fmod(axisHeading, dTheta);
|
||||
const float angle0 = axisHeading - rem;
|
||||
const float angle1 = angle0 + dTheta;
|
||||
t = rem / dTheta;
|
||||
|
||||
sincos(angle0, axisX0.y, axisX0.x);
|
||||
sincos(angle1, axisX1.y, axisX1.x);
|
||||
axisZ0.x = -axisX0.y; axisZ0.y = axisX0.x;
|
||||
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);
|
||||
|
||||
half3 _displacement = 0.0;
|
||||
|
||||
// Loop through wave buffer slices.
|
||||
for (uint i = first; i <= last; i++)
|
||||
{
|
||||
const uint waveBufferIndex = i;
|
||||
const float waveBufferSize = 0.5f * (1 << waveBufferIndex);
|
||||
|
||||
half weight = _weight;
|
||||
|
||||
uint WAVE_SAMPLE_FACTOR = 8;
|
||||
half minimumWL = waveBufferSize / WAVE_SAMPLE_FACTOR / _Crest_WaveResolutionMultiplier;
|
||||
half averageWL = minimumWL * 1.5f * _Crest_WaveResolutionMultiplier;
|
||||
|
||||
// If approaching end of lod chain, start smoothly transitioning any large
|
||||
// wavelengths across last two LODs.
|
||||
if (minimumWL >= _Crest_TransitionalWavelengthThreshold)
|
||||
{
|
||||
// The transition weight must not be applied to the alpha otherwise popping.
|
||||
weight *= transition;
|
||||
}
|
||||
|
||||
// Attenuation.
|
||||
float attenuation;
|
||||
{
|
||||
// Attenuate waves based on water depth. If depth is greater than half the
|
||||
// wavelength, water is considered deep and wave is unaffected. If depth is less
|
||||
// than this, wave velocity decreases. Waves will then bunch up and grow in
|
||||
// amplitude and eventually break. Deep water model is approximated by simply
|
||||
// ramping down waves in non-deep water with a linear multiplier.
|
||||
// http://hyperphysics.phy-astr.gsu.edu/hbase/Waves/watwav2.html
|
||||
// http://hyperphysics.phy-astr.gsu.edu/hbase/watwav.html#c1
|
||||
half weight = saturate(2.0 * depth / averageWL);
|
||||
if (_Crest_MaximumAttenuationDepth < k_Crest_MaximumWaveAttenuationDepth)
|
||||
{
|
||||
weight = lerp(weight, 1.0, saturate(depth / _Crest_MaximumAttenuationDepth));
|
||||
}
|
||||
|
||||
|
||||
const float attenuationAmount = _Crest_AttenuationInShallows * _Crest_RespectShallowWaterAttenuation;
|
||||
attenuation = attenuationAmount * weight + (1.0 - attenuationAmount);
|
||||
}
|
||||
|
||||
// NOTE: Could not get attenuation applied to alpha to work. Incurred popping.
|
||||
weight *= attenuation;
|
||||
|
||||
// Sample Wave Buffers.
|
||||
if (weight > 0.0)
|
||||
{
|
||||
#if d_Texture
|
||||
// Interpolate waves.
|
||||
float2 positionScaledWS = positionWS / waveBufferSize;
|
||||
|
||||
const float2 uv0 = float2(dot(positionScaledWS, axisX0), dot(positionScaledWS, axisZ0));
|
||||
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;
|
||||
|
||||
float3 displacement = lerp(displacement0, displacement1, t);
|
||||
displacement.xz = displacement.x * axis + displacement.z * float2(-axis.y, axis.x);
|
||||
displacement.y *= axisLength;
|
||||
_displacement += displacement * weight;
|
||||
|
||||
#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;
|
||||
displacement.xz = displacement.x * _Crest_AxisX + displacement.z * float2(-_Crest_AxisX.y, _Crest_AxisX.x);
|
||||
_displacement += displacement * weight;
|
||||
#endif // d_Texture
|
||||
}
|
||||
}
|
||||
|
||||
#if d_TextureBlend
|
||||
// Global waves are always additive.
|
||||
_Crest_Target[id] *= 1.0 - saturate(alpha);
|
||||
#endif
|
||||
|
||||
// Always write full alpha so textures show up in previews.
|
||||
_Crest_Target[id] += float4(_displacement, 1.0);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(TransferWaves)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a487d04e47a14907809657d5ccf1917
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Renders convex hull to the clip surface texture.
|
||||
|
||||
Shader "Hidden/Crest/Inputs/Clip/Convex Hull"
|
||||
{
|
||||
CGINCLUDE
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
// For SV_IsFrontFace.
|
||||
#pragma target 3.0
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#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"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Surface/Geometry.hlsl"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
bool _Crest_Inverted;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float3 positionWS : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
o.positionCS = UnityObjectToClipPos(input.positionOS);
|
||||
o.positionWS = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0));
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Fragment(Varyings input, const bool isFrontFace)
|
||||
{
|
||||
float3 surfacePositionWS = Cascade::MakeAnimatedWaves(_Crest_LodIndex)
|
||||
.SampleDisplacementFromUndisplaced(input.positionWS.xz);
|
||||
|
||||
// Move to sea level.
|
||||
surfacePositionWS.y += g_Crest_WaterCenter.y;
|
||||
|
||||
// Clip if above water.
|
||||
if (input.positionWS.y > surfacePositionWS.y)
|
||||
{
|
||||
clip(-1.0);
|
||||
}
|
||||
|
||||
// To add clipping, back face must write one and front face must write zero.
|
||||
return float4(isFrontFace == _Crest_Inverted ? 1.0 : 0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestVertex
|
||||
m_CrestFragmentWithFrontFace(float4)
|
||||
|
||||
ENDCG
|
||||
|
||||
SubShader
|
||||
{
|
||||
ZWrite Off
|
||||
ColorMask R
|
||||
|
||||
Pass
|
||||
{
|
||||
Cull Front
|
||||
// Here so CGINCLUDE works.
|
||||
CGPROGRAM
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Cull Back
|
||||
// Here so CGINCLUDE works.
|
||||
CGPROGRAM
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f5d1e029c7564da8855bf97e3b9247a
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#pragma multi_compile_local d_Sphere d_Cube d_Rectangle
|
||||
#pragma multi_compile_local __ d_Inverted
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Cascade.hlsl"
|
||||
|
||||
RWTexture2DArray<float1> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float3 _Crest_Position;
|
||||
float _Crest_Diameter;
|
||||
float4x4 _Crest_Matrix;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
// Also covers elipsoids etc.
|
||||
float SphereSDF(float3 position)
|
||||
{
|
||||
// Distance from center.
|
||||
return length(position);
|
||||
}
|
||||
|
||||
// Also covers rectangular prisms etc.
|
||||
float CubeSDF(float3 position)
|
||||
{
|
||||
// Restrict to one quadrant of a box.
|
||||
position = abs(position);
|
||||
// Get furthest distance from center.
|
||||
return max(position.x, max(position.y, position.z));
|
||||
}
|
||||
|
||||
float RectangleSDF(float2 position)
|
||||
{
|
||||
// Restrict to one quadrant of a box.
|
||||
position = abs(position);
|
||||
// Get furthest distance from center.
|
||||
return max(position.x, position.y);
|
||||
}
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeClip(id.z);
|
||||
const float2 positionXZ = cascade.IDToWorld(id.xy);
|
||||
|
||||
// TODO: Optimize with something better than spherical culling.
|
||||
// Spherical culling. Check diameter for buffered area.
|
||||
if (length(positionXZ - _Crest_Position.xz) > _Crest_Diameter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float3 position = 0.0;
|
||||
position.xz = positionXZ;
|
||||
|
||||
#if !d_Rectangle
|
||||
// Only need height as clip surface is sampled at the displaced position.
|
||||
const float3 surface = Cascade::MakeAnimatedWaves(id.z).SampleDisplacementFromUndisplaced(positionXZ);
|
||||
position.y = g_Crest_WaterCenter.y + surface.y;
|
||||
#endif
|
||||
|
||||
// SDF operate in local space.
|
||||
position = mul(_Crest_Matrix, float4(position, 1.0)).xyz;
|
||||
|
||||
float sdf = 0;
|
||||
|
||||
#if d_Sphere
|
||||
sdf = SphereSDF(position);
|
||||
#endif
|
||||
|
||||
#if d_Cube
|
||||
sdf = CubeSDF(position);
|
||||
#endif
|
||||
|
||||
#if d_Rectangle
|
||||
sdf = RectangleSDF(position.xz);
|
||||
#endif
|
||||
|
||||
#if d_Inverted
|
||||
_Crest_Target[id.xyz] = min(_Crest_Target[id.xyz], sdf);
|
||||
#else
|
||||
sdf = 1.0 - sdf;
|
||||
_Crest_Target[id.xyz] = max(_Crest_Target[id.xyz], sdf);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad943abdbda794e98b8decce3329fcd8
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,47 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adds clipping from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
RWTexture2DArray<float> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeClip(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (!WithinUV(uv))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float result = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).x;
|
||||
|
||||
// Painted clip defines a minimum value of the clip.
|
||||
_Crest_Target[id] = max(_Crest_Target[id], result);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb559b0e067b5464792b8e434189347c
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,4 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Hidden/Crest" { }
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdf2728920d024e9fb0e708e1dc364bb
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,128 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Copies the depth buffer into the cache as object-space height. Object-space is
|
||||
// used instead of world-space to allow relative movement of baked depth caches
|
||||
// afterwards. It is converted to world-space in another shader before writing into
|
||||
// the LOD data.
|
||||
|
||||
#pragma kernel CrestCopy
|
||||
#pragma kernel CrestFill
|
||||
|
||||
#pragma multi_compile_local __ d_Crest_BackFaceInclusion
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
|
||||
|
||||
Texture2D<float> _CamDepthBuffer;
|
||||
RWTexture2D<float2> _Crest_Target;
|
||||
|
||||
#if d_Crest_BackFaceInclusion
|
||||
Texture2D<float> _Crest_CameraDepthBufferBackfaces;
|
||||
#endif
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float4 _HeightNearHeightFar;
|
||||
float4 _CustomZBufferParams;
|
||||
float _HeightOffset;
|
||||
float _Crest_PreviousPlane;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
float CustomLinear01Depth(const float z)
|
||||
{
|
||||
return (1.0 - z * _CustomZBufferParams.x) / _CustomZBufferParams.y;
|
||||
}
|
||||
|
||||
void Copy(const uint3 id)
|
||||
{
|
||||
const float deviceDepth = _CamDepthBuffer[id.xy].x;
|
||||
|
||||
// If geometry has been clipped by far plane, set the maximum depth.
|
||||
if (deviceDepth <= 0.0)
|
||||
{
|
||||
_Crest_Target[id.xy] = -CREST_WATER_DEPTH_BASELINE;
|
||||
return;
|
||||
}
|
||||
|
||||
const float linear01Z = CustomLinear01Depth(deviceDepth);
|
||||
|
||||
const float altitude =
|
||||
#if UNITY_REVERSED_Z
|
||||
lerp(_HeightNearHeightFar.y, _HeightNearHeightFar.x, linear01Z);
|
||||
#else
|
||||
lerp(_HeightNearHeightFar.x, _HeightNearHeightFar.y, linear01Z);
|
||||
#endif
|
||||
|
||||
_Crest_Target[id.xy] = altitude - _HeightOffset;
|
||||
}
|
||||
|
||||
void Fill(const uint3 id)
|
||||
{
|
||||
const float deviceDepth = _CamDepthBuffer[id.xy].x;
|
||||
|
||||
#if d_Crest_BackFaceInclusion
|
||||
const float deviceBackFaceDepth = _Crest_CameraDepthBufferBackfaces[id.xy].x;
|
||||
#endif
|
||||
|
||||
// If geometry has been clipped by far plane, set the maximum depth.
|
||||
if (deviceDepth <= 0.0)
|
||||
{
|
||||
#if d_Crest_BackFaceInclusion
|
||||
if (deviceBackFaceDepth <= 0.0)
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If not a hole, do not proceed.
|
||||
// We must be limiteed by precision on trying to represent depth baseline
|
||||
if (_Crest_Target[id.xy].x > -CREST_WATER_DEPTH_BASELINE)
|
||||
{
|
||||
#if d_Crest_BackFaceInclusion
|
||||
if (deviceBackFaceDepth <= 0.0)
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const float linear01Z = CustomLinear01Depth(deviceDepth);
|
||||
|
||||
const float altitude =
|
||||
#if UNITY_REVERSED_Z
|
||||
lerp(_HeightNearHeightFar.y, _HeightNearHeightFar.x, linear01Z);
|
||||
#else
|
||||
lerp(_HeightNearHeightFar.x, _HeightNearHeightFar.y, linear01Z);
|
||||
#endif
|
||||
|
||||
|
||||
#if d_Crest_BackFaceInclusion
|
||||
{
|
||||
const float linear01Z = CustomLinear01Depth(deviceBackFaceDepth);
|
||||
const float altitude =
|
||||
#if UNITY_REVERSED_Z
|
||||
lerp(_HeightNearHeightFar.y, _HeightNearHeightFar.x, linear01Z);
|
||||
#else
|
||||
lerp(_HeightNearHeightFar.x, _HeightNearHeightFar.y, linear01Z);
|
||||
#endif
|
||||
|
||||
// Check backfaces.
|
||||
if (altitude > (_Crest_PreviousPlane + 0.00001))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_Crest_Target[id.xy] = altitude - _HeightOffset;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestKernelDefault(Copy)
|
||||
m_CrestKernelDefault(Fill)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bb3e13f5a77e489584dd6fe9dd28a4f
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,69 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Draw cached world-space heights into current frame data. If heights are coming
|
||||
// from an ODC, then they are in object-space and are converted to world-space as
|
||||
// the LOD data stores world-space height.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#pragma multi_compile_local __ d_CrestSDF
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
#define m_CrestType float
|
||||
|
||||
#if d_CrestSDF
|
||||
#undef m_CrestType
|
||||
#define m_CrestType float2
|
||||
#endif
|
||||
|
||||
Texture2D<m_CrestType> _Crest_Texture;
|
||||
RWTexture2DArray<m_CrestType> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestInputTexture)
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float _Crest_HeightOffset;
|
||||
bool _Crest_SDF;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeDepth(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (!WithinUV(uv))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_CrestType current = _Crest_Target[id];
|
||||
m_CrestType result = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0);
|
||||
result.x += _Crest_HeightOffset;
|
||||
|
||||
// Take highest terrain height.
|
||||
result.x = max(current.x, result.x);
|
||||
|
||||
#if d_CrestSDF
|
||||
// Take shortest distance.
|
||||
result.y = _Crest_SDF ? min(current.y, result.y) : current.y;
|
||||
#endif
|
||||
|
||||
_Crest_Target[id] = result;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 025c29236eb8341f0a2078d93379be6a
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adds flow from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
RWTexture2DArray<float2> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
int _Crest_Blend;
|
||||
float _Crest_Weight;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float _Crest_FeatherWidth;
|
||||
bool _Crest_NegativeValues;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeFlow(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
half weight = _Crest_Weight;
|
||||
|
||||
// Feather boundaries.
|
||||
weight *= FeatherWeightFromUV(uv, _Crest_FeatherWidth);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float2 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).xy;
|
||||
|
||||
if (!_Crest_NegativeValues)
|
||||
{
|
||||
// From 0..1 to -1..1.
|
||||
source = source * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
if (_Crest_Blend == m_CrestBlendAlpha)
|
||||
{
|
||||
weight *= saturate(length(source));
|
||||
}
|
||||
|
||||
const float2 target = _Crest_Target[id];
|
||||
_Crest_Target[id] = Blend(_Crest_Blend, weight, 1.0, source, target);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67ee915fe51504dd894c5cbf6f1a7868
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,56 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adds foam from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
RWTexture2DArray<float> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
int _Crest_Blend;
|
||||
float _Crest_Weight;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float _Crest_FeatherWidth;
|
||||
float _Crest_SimDeltaTime;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeFoam(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
half weight = _Crest_Weight;
|
||||
|
||||
// Boundary check with feathering.
|
||||
weight *= FeatherWeightFromUV(uv, _Crest_FeatherWidth);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0).x;
|
||||
const float target = _Crest_Target[id];
|
||||
|
||||
_Crest_Target[id] = Blend(_Crest_Blend, weight, _Crest_SimDeltaTime, source, target);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69307e5986e134adc90ee257e7dba1ea
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,154 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// An implementation of the Jump Flood algorithm by Rong and Tan
|
||||
// Source: https://www.comp.nus.edu.sg/~tants/jfa.html
|
||||
|
||||
#pragma kernel CrestInitialize
|
||||
#pragma kernel CrestExecute
|
||||
#pragma kernel CrestApply
|
||||
|
||||
#pragma multi_compile_local __ d_Crest_Inverted
|
||||
#pragma multi_compile_local __ d_Crest_Standalone
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.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"
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
uint _Crest_JumpSize;
|
||||
uint _Crest_TextureSize;
|
||||
float4x4 _Crest_ProjectionToWorld;
|
||||
float _Crest_HeightOffset;
|
||||
float _Crest_WaterLevel;
|
||||
CBUFFER_END
|
||||
|
||||
// Holds scene depth for initialization.
|
||||
Texture2D<float2> _Crest_Source;
|
||||
RWTexture2D<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)
|
||||
|
||||
#if d_Crest_Inverted
|
||||
#define m_DepthCheck depth > 0.0
|
||||
#else
|
||||
#define m_DepthCheck depth <= 0.0
|
||||
#endif
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
bool IsUninitializedPosition(const float2 position)
|
||||
{
|
||||
return isinf(position.x);
|
||||
}
|
||||
|
||||
float2 IDtoWorld(const uint2 id, const float resolution, const float4x4 projectionToWorld)
|
||||
{
|
||||
float2 uv = (((id + 0.5) / resolution) - 0.5) * 2.0;
|
||||
return mul(projectionToWorld, float4(uv, 0.0, 1.0)).xz;
|
||||
}
|
||||
|
||||
void Initialize(const uint3 id)
|
||||
{
|
||||
float2 position = IDtoWorld(id.xy, _Crest_TextureSize, _Crest_ProjectionToWorld);
|
||||
float depth = _Crest_WaterLevel - (_Crest_Source[id.xy].x + _Crest_HeightOffset);
|
||||
|
||||
#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);
|
||||
depth += lerp(Cascade::MakeLevel(slice0).SampleLevel(position), Cascade::MakeLevel(slice1).SampleLevel(position), alpha);
|
||||
#endif
|
||||
|
||||
_Crest_Target[id.xy] = m_DepthCheck ? position : m_CrestUninitializedPosition;
|
||||
}
|
||||
|
||||
void Execute(const uint3 id)
|
||||
{
|
||||
float2 nearest = _Crest_Source[id.xy];
|
||||
|
||||
const uint3 jump = uint3(_Crest_JumpSize, -(int)_Crest_JumpSize, 0);
|
||||
const bool xBounds = _Crest_TextureSize - _Crest_JumpSize > id.x;
|
||||
const bool yBounds = _Crest_TextureSize - _Crest_JumpSize > id.y;
|
||||
const bool zBounds = id.x >= _Crest_JumpSize;
|
||||
const bool wBounds = id.y >= _Crest_JumpSize;
|
||||
|
||||
float2 candidates[8];
|
||||
candidates[0] = yBounds ? _Crest_Source[id.xy + jump.zx] : nearest;
|
||||
candidates[1] = yBounds && xBounds ? _Crest_Source[id.xy + jump.xx] : nearest;
|
||||
candidates[2] = xBounds ? _Crest_Source[id.xy + jump.xz] : nearest;
|
||||
candidates[3] = xBounds && wBounds ? _Crest_Source[id.xy + jump.xy] : nearest;
|
||||
candidates[4] = wBounds ? _Crest_Source[id.xy + jump.zy] : nearest;
|
||||
candidates[5] = wBounds && zBounds ? _Crest_Source[id.xy + jump.yy] : nearest;
|
||||
candidates[6] = zBounds ? _Crest_Source[id.xy + jump.yz] : nearest;
|
||||
candidates[7] = zBounds && yBounds ? _Crest_Source[id.xy + jump.yx] : nearest;
|
||||
|
||||
const float2 position = IDtoWorld(id.xy, _Crest_TextureSize, _Crest_ProjectionToWorld);
|
||||
const float2 displacement = nearest - position;
|
||||
float distance2 = dot(displacement, displacement);
|
||||
|
||||
for (uint i = 0; i < 8; i++)
|
||||
{
|
||||
if (IsUninitializedPosition(nearest))
|
||||
{
|
||||
nearest = candidates[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
const float2 candidateDisplacement = candidates[i] - position;
|
||||
const float candidateDistance2 = dot(candidateDisplacement, candidateDisplacement);
|
||||
|
||||
if (candidateDistance2 < distance2)
|
||||
{
|
||||
nearest = candidates[i];
|
||||
distance2 = candidateDistance2;
|
||||
}
|
||||
}
|
||||
|
||||
_Crest_Target[id.xy] = nearest;
|
||||
}
|
||||
|
||||
void Apply(const uint3 id)
|
||||
{
|
||||
float2 result = _Crest_Target[id.xy];
|
||||
float2 position = IDtoWorld(id.xy, _Crest_TextureSize, _Crest_ProjectionToWorld);
|
||||
|
||||
#if d_Crest_Inverted
|
||||
float depth = _Crest_WaterLevel - (result.x + _Crest_HeightOffset);
|
||||
|
||||
#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);
|
||||
depth += lerp(Cascade::MakeLevel(slice0).SampleLevel(position), Cascade::MakeLevel(slice1).SampleLevel(position), alpha);
|
||||
#endif
|
||||
|
||||
// Do not overwrite positive SDF.
|
||||
if (depth > 0) return;
|
||||
#endif
|
||||
|
||||
float2 nearest = _Crest_Source[id.xy];
|
||||
float2 displacement = nearest - position;
|
||||
|
||||
float distance = length(displacement);
|
||||
|
||||
#if d_Crest_Inverted
|
||||
distance = -distance;
|
||||
#endif
|
||||
|
||||
result.y = distance;
|
||||
|
||||
_Crest_Target[id.xy] = result;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestKernelDefault(Initialize)
|
||||
m_CrestKernelDefault(Execute)
|
||||
m_CrestKernelDefault(Apply)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 55a9b76c48b7343b2b66ed91a0619c29
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adds height from a provided texture. Used by Painted and Texture input modes.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#pragma multi_compile_local __ d_CatmullRom
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Utility/Filtering.hlsl"
|
||||
|
||||
m_DisplacementTexture(Texture2D, 4) _Crest_Texture;
|
||||
RWTexture2DArray<float> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
int _Crest_Blend;
|
||||
float _Crest_Weight;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float2 _Crest_Resolution;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeLevel(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
half weight = _Crest_Weight;
|
||||
|
||||
// Feather boundaries.
|
||||
weight *= FeatherWeightFromUV(uv, 0.0);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if d_CatmullRom
|
||||
const float source = Utility::SampleTextureCatmullRom(_Crest_Texture, LODData_linear_clamp_sampler, uv, _Crest_Resolution).x;
|
||||
#else
|
||||
const float source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0.0).x;
|
||||
#endif
|
||||
|
||||
const float target = _Crest_Target[id];
|
||||
|
||||
_Crest_Target[id] = Blend(_Crest_Blend, weight, 1.0, source, target);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6bccbd92220dc418cacd3f17096c6b97
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/InputsDriven.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Cascade.hlsl"
|
||||
|
||||
Texture2D _Crest_Texture;
|
||||
RWTexture2DArray<float3> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
int _Crest_Blend;
|
||||
float _Crest_Weight;
|
||||
float2 _Crest_TextureSize;
|
||||
float2 _Crest_TexturePosition;
|
||||
float2 _Crest_TextureRotation;
|
||||
float _Crest_FeatherWidth;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeScattering(id.z);
|
||||
const float2 uv = DataIDToInputUV(id.xy, cascade, _Crest_TexturePosition, _Crest_TextureRotation, _Crest_TextureSize);
|
||||
|
||||
half weight = _Crest_Weight;
|
||||
|
||||
// Feather boundaries.
|
||||
weight *= FeatherWeightFromUV(uv, _Crest_FeatherWidth);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const half4 source = _Crest_Texture.SampleLevel(LODData_linear_clamp_sampler, uv, 0);
|
||||
const half3 target = _Crest_Target[id];
|
||||
weight *= source.a;
|
||||
|
||||
_Crest_Target[id] = Blend(_Crest_Blend, weight, 1.0, source.xyz, target);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78d6b75ecfb664f0cbb70001b1446627
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,124 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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/Helpers.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;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float3 _Crest_Position;
|
||||
float3 _Crest_Velocity;
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_Weight;
|
||||
float _Crest_Radius;
|
||||
float _Crest_InnerSphereOffset;
|
||||
float _Crest_InnerSphereMultiplier;
|
||||
float _Crest_LargeWaveMultiplier;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
// Resolution-aware interaction falloff function, inspired by "bandfiltered step"
|
||||
// from Ottosson. Basically adding together this falloff function at different
|
||||
// scales generates a consistent result that doesn't grow into an ugly uintended
|
||||
// shape. Shadertoy with more details: https://www.shadertoy.com/view/WltBWM
|
||||
float InteractionFalloff(float a, float x)
|
||||
{
|
||||
float ax = a * x;
|
||||
float ax2 = ax * ax;
|
||||
float ax4 = ax2 * ax2;
|
||||
|
||||
return ax / (1.0 + ax2 * ax4);
|
||||
}
|
||||
|
||||
void SphereSDF(float2 offsetXZ, out float sdf, out float2 normal)
|
||||
{
|
||||
float distance = length(offsetXZ);
|
||||
sdf = distance - _Crest_Radius;
|
||||
normal = distance > 0.0001 ? offsetXZ / distance : float2(1.0, 0.0);
|
||||
}
|
||||
|
||||
void Execute(uint3 id)
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeDynamicWaves(id.z);
|
||||
|
||||
if (_Crest_LargeWaveMultiplier * _Crest_Radius < cascade._Texel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float2 positionXZ = cascade.IDToWorld(id.xy);
|
||||
float2 offsetXZ = positionXZ - _Crest_Position.xz;
|
||||
|
||||
// Spherical culling. Check diameter for buffered area.
|
||||
if (length(offsetXZ) > _Crest_Radius * 4.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Feather at edges of LOD to reduce streaking without reflections.
|
||||
half weight = _Crest_Weight * FeatherWeightFromUV(cascade.WorldToUV(positionXZ).xy, 0.1);
|
||||
|
||||
// Check we are within bounds.
|
||||
if (weight <= 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float minimumWavelength = Cascade::Make(id.z)._MaximumWavelength * 0.5;
|
||||
|
||||
float sdf;
|
||||
float2 sdfNormal;
|
||||
SphereSDF(offsetXZ, sdf, sdfNormal);
|
||||
|
||||
// Push in same direction as velocity inside sphere, and opposite direction outside.
|
||||
float verticalForce = 0.0;
|
||||
{
|
||||
verticalForce = -_Crest_Velocity.y;
|
||||
|
||||
// Range / radius of interaction force
|
||||
const float a = 1.67 / minimumWavelength;
|
||||
verticalForce *= InteractionFalloff( a, sdf );
|
||||
}
|
||||
|
||||
// Push water up in direction of motion, pull down behind.
|
||||
float horizontalForce = 0.0;
|
||||
if (sdf > 0.0 || sdf < -_Crest_Radius * _Crest_InnerSphereOffset)
|
||||
{
|
||||
// Range / radius of interaction force.
|
||||
const float a = 1.43 / minimumWavelength;
|
||||
|
||||
// Invert within sphere, to balance / negate forces applied outside of sphere.
|
||||
float forceSign = sign(sdf);
|
||||
|
||||
horizontalForce = forceSign * dot(sdfNormal, _Crest_Velocity.xz) * InteractionFalloff(a, abs(sdf));
|
||||
|
||||
// If inside sphere, add an additional weight.
|
||||
if (sdf < 0.0)
|
||||
{
|
||||
horizontalForce *= _Crest_InnerSphereMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to velocity (y-channel) to accelerate water. Magic number was the default
|
||||
// value for _Strength which has been removed.
|
||||
float acceleration = weight * (verticalForce + horizontalForce) * 0.2;
|
||||
|
||||
// Helps interaction to work at different scales
|
||||
acceleration /= minimumWavelength;
|
||||
|
||||
_Crest_Target[id] = float2(_Crest_Target[id].x, _Crest_Target[id].y + acceleration * _Crest_SimDeltaTime);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestInputKernelDefault(Execute)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98fb0af5d79724a2c945809b974524eb
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,52 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/All/Override"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[Enum(ColorWriteMask)]
|
||||
_Crest_ColorMask("Color Mask", Int) = 15
|
||||
_Crest_Value("Value", Vector) = (1, 1, 1, 1)
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend Off
|
||||
ColorMask [_Crest_ColorMask]
|
||||
ZWrite Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
half4 _Crest_Value;
|
||||
half _Crest_Weight;
|
||||
CBUFFER_END
|
||||
|
||||
float4 Vertex(float3 positionOS : POSITION) : SV_POSITION
|
||||
{
|
||||
float3 positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz;
|
||||
// Correct for displacement.
|
||||
positionWS.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
return mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
}
|
||||
|
||||
half4 Fragment() : SV_Target
|
||||
{
|
||||
return _Crest_Value * _Crest_Weight;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 288a089f90e714983b8a760dd49e5a5c
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,129 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// 0-1 scaling of existing water data using multiplicative blending.
|
||||
|
||||
Shader "Crest/Inputs/All/Scale"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
// Scale the water data. Zero is no data and one leaves data untouched.
|
||||
_Crest_Scale("Scale", Range(0, 1)) = 0.35
|
||||
|
||||
// Use the texture instead of the scale value.
|
||||
[Toggle(d_Texture)]
|
||||
_Crest_ApplyTexture("Apply Texture", Float) = 0
|
||||
[MainTexture] _Crest_Texture("Texture", 2D) = "black" {}
|
||||
|
||||
// Inverts the scale value.
|
||||
[Toggle(d_Invert)]
|
||||
_Crest_Invert("Invert", Float) = 0
|
||||
|
||||
[Header(Feather)]
|
||||
// Feather the edges of the mesh using the texture coordinates. Easiest to understand with a plane.
|
||||
[Toggle(d_Feather)]
|
||||
_Crest_Feather("Feather At UV Extents", Float) = 0
|
||||
// How far from edge to feather.
|
||||
_Crest_FeatherWidth("Feather Width", Range(0.001, 0.5)) = 0.1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
// Multiply
|
||||
Blend Zero SrcColor
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#pragma shader_feature_local d_Texture
|
||||
#pragma shader_feature_local d_Invert
|
||||
#pragma shader_feature_local d_Feather
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#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"
|
||||
|
||||
#if defined(d_Texture) || defined(d_Feather)
|
||||
#define _NEED_UVS
|
||||
#endif
|
||||
|
||||
#if d_Texture
|
||||
Texture2D _Crest_Texture;
|
||||
SamplerState sampler_Crest_Texture;
|
||||
#endif
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_Weight;
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
float _Crest_Scale;
|
||||
#if d_Feather
|
||||
half _Crest_FeatherWidth;
|
||||
#endif
|
||||
#if d_Texture
|
||||
float4 _Crest_Texture_ST;
|
||||
#endif
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
#ifdef _NEED_UVS
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
#ifdef _NEED_UVS
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
float3 positionWS = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement.
|
||||
positionWS.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
|
||||
#ifdef _NEED_UVS
|
||||
o.uv = input.uv;
|
||||
#endif
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
#if d_Texture
|
||||
float scale = _Crest_Texture.Sample(sampler_Crest_Texture, input.uv).r;
|
||||
#else
|
||||
float scale = _Crest_Scale;
|
||||
#endif
|
||||
|
||||
#if d_Invert
|
||||
scale = 1.0 - scale;
|
||||
#endif
|
||||
|
||||
#if d_Feather
|
||||
scale = lerp(1.0, scale, WaveHarmonic::Crest::FeatherWeightFromUV(input.uv, _Crest_FeatherWidth));
|
||||
#endif
|
||||
|
||||
return scale * _Crest_Weight;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbf67e7cbdc0a4cc09a539707e0007b9
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,82 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/Scattering/Color"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_Crest_Scattering("Scattering", Color) = (0.0, 0.09803921729326248, 0.20000000298023225, 0.0)
|
||||
|
||||
[Toggle(d_Feather)]
|
||||
_Crest_Feather("Feather At UV Extents", Float) = 0
|
||||
_Crest_FeatherWidth("Feather Width", Range(0.001, 0.5)) = 0.1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend SrcAlpha OneMinusSrcAlpha
|
||||
ZWrite Off
|
||||
ColorMask RGB
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#pragma shader_feature_local d_Feather
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 vertex : POSITION;
|
||||
#if d_Feather
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
#if d_Feather
|
||||
float2 uv : TEXCOORD0;
|
||||
#endif
|
||||
};
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
half4 _Crest_Scattering;
|
||||
half _Crest_FeatherWidth;
|
||||
CBUFFER_END
|
||||
|
||||
Varyings Vertex(Attributes input)
|
||||
{
|
||||
Varyings output;
|
||||
float3 positionWS = mul(unity_ObjectToWorld, float4(input.vertex, 1.0)).xyz;
|
||||
output.vertex = mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
#if d_Feather
|
||||
output.uv = input.uv;
|
||||
#endif
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 Fragment(Varyings input) : SV_Target
|
||||
{
|
||||
half4 color = _Crest_Scattering;
|
||||
color.a = 1.0;
|
||||
#if d_Feather
|
||||
color.a *= WaveHarmonic::Crest::FeatherWeightFromUV(input.uv, _Crest_FeatherWidth);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea69fc35da7574631aea97812ee8652b
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,192 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Generates waves from geometry that is rendered into the water simulation from a top down camera. Expects
|
||||
// following data on verts:
|
||||
// - POSITION: Vert positions as normal.
|
||||
// - TEXCOORD0: Axis - direction for waves to travel. "Forward vector" for waves.
|
||||
// - TEXCOORD1: X - 0 at start of waves, 1 at end of waves
|
||||
//
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uv1.x = 0 |
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | uv0 - wave direction vector
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | \|/
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ uv1.x = 1
|
||||
// ------------------- shoreline --------------------
|
||||
//
|
||||
|
||||
Shader "Crest/Inputs/Shape Waves/Add From Geometry"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[Enum(UnityEngine.Rendering.BlendMode)]
|
||||
_Crest_BlendModeSource("Source Blend Mode", Int) = 1
|
||||
[Enum(UnityEngine.Rendering.BlendMode)]
|
||||
_Crest_BlendModeTarget("Target Blend Mode", Int) = 1
|
||||
|
||||
// Controls ramp distance over which waves grow/fade as they move forwards
|
||||
_Crest_FeatherWaveStart( "Feather wave start (0-1)", Range( 0.0, 10 ) ) = 0.1
|
||||
|
||||
[Toggle(d_Feather)]
|
||||
_Crest_Feather("Feather At UV Extents", Float) = 0
|
||||
_Crest_FeatherWidth("Feather Width", Range(0.001, 1)) = 0.1
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
CGINCLUDE
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
// #pragma enable_d3d11_debug_symbols
|
||||
|
||||
#pragma shader_feature_local d_Feather
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.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"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Helpers.hlsl"
|
||||
|
||||
Texture2DArray _Crest_WaveBuffer;
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float _Crest_RespectShallowWaterAttenuation;
|
||||
int _Crest_WaveBufferSliceIndex;
|
||||
float _Crest_AverageWavelength;
|
||||
float _Crest_AttenuationInShallows;
|
||||
float _Crest_Weight;
|
||||
float2 _Crest_AxisX;
|
||||
half _Crest_MaximumAttenuationDepth;
|
||||
half _Crest_FeatherWidth;
|
||||
half _Crest_FeatherWaveStart;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 vertex : SV_POSITION;
|
||||
float2 uv : TEXCOORD0;
|
||||
float3 uv_slice : TEXCOORD1;
|
||||
float2 axis : TEXCOORD2;
|
||||
float3 worldPosScaled : TEXCOORD3;
|
||||
float2 worldPosXZ : TEXCOORD5;
|
||||
};
|
||||
|
||||
Varyings Vertex(Attributes v)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
const float3 positionOS = v.vertex.xyz;
|
||||
o.vertex = UnityObjectToClipPos(positionOS);
|
||||
const float3 worldPos = mul( unity_ObjectToWorld, float4(positionOS, 1.0) ).xyz;
|
||||
|
||||
// UV coordinate into the cascade we are rendering into
|
||||
o.uv_slice = Cascade::MakeAnimatedWaves(_Crest_LodIndex).WorldToUV(worldPos.xz);
|
||||
|
||||
o.worldPosXZ = worldPos.xz;
|
||||
|
||||
o.uv = v.uv;
|
||||
|
||||
// World pos prescaled by wave buffer size, suitable for using as UVs in fragment shader
|
||||
const float waveBufferSize = 0.5f * (1 << _Crest_WaveBufferSliceIndex);
|
||||
o.worldPosScaled = worldPos / waveBufferSize;
|
||||
|
||||
// Rotate forward axis around y-axis into world space
|
||||
o.axis = unity_ObjectToWorld._m00_m20.xy;
|
||||
o.axis = _Crest_AxisX.x * o.axis + _Crest_AxisX.y * float2(-o.axis.y, o.axis.x);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Fragment(Varyings input)
|
||||
{
|
||||
float wt = _Crest_Weight;
|
||||
|
||||
// Feature at away from shore.
|
||||
wt *= saturate(input.uv.x / _Crest_FeatherWaveStart);
|
||||
|
||||
#if d_Feather
|
||||
wt *= FeatherWeightFromUV(input.uv, _Crest_FeatherWidth);
|
||||
#endif
|
||||
|
||||
float alpha = wt;
|
||||
|
||||
// Attenuate if depth is less than half of the average wavelength
|
||||
const half depth = Cascade::MakeDepth(_Crest_LodIndex).SampleSignedDepthFromSeaLevel(input.worldPosXZ) +
|
||||
Cascade::MakeLevel(_Crest_LodIndex).SampleLevel(input.worldPosXZ);
|
||||
half depth_wt = saturate(2.0 * depth / _Crest_AverageWavelength);
|
||||
if (_Crest_MaximumAttenuationDepth < k_Crest_MaximumWaveAttenuationDepth)
|
||||
{
|
||||
depth_wt = lerp(depth_wt, 1.0, saturate(depth / _Crest_MaximumAttenuationDepth));
|
||||
}
|
||||
const float attenuationAmount = _Crest_AttenuationInShallows * _Crest_RespectShallowWaterAttenuation;
|
||||
wt *= attenuationAmount * depth_wt + (1.0 - attenuationAmount);
|
||||
|
||||
// Quantize wave direction and interpolate waves
|
||||
float axisHeading = atan2( input.axis.y, input.axis.x ) + 2.0 * 3.141592654;
|
||||
const float dTheta = 0.5*0.314159265;
|
||||
float angle0 = axisHeading;
|
||||
const float rem = fmod( angle0, dTheta );
|
||||
angle0 -= rem;
|
||||
const float angle1 = angle0 + dTheta;
|
||||
|
||||
float2 axisX0; sincos( angle0, axisX0.y, axisX0.x );
|
||||
float2 axisX1; sincos( angle1, axisX1.y, axisX1.x );
|
||||
float2 axisZ0; axisZ0.x = -axisX0.y; axisZ0.y = axisX0.x;
|
||||
float2 axisZ1; axisZ1.x = -axisX1.y; axisZ1.y = axisX1.x;
|
||||
|
||||
const float2 uv0 = float2(dot( input.worldPosScaled.xz, axisX0 ), dot( input.worldPosScaled.xz, axisZ0 ));
|
||||
const float2 uv1 = float2(dot( input.worldPosScaled.xz, axisX1 ), dot( input.worldPosScaled.xz, axisZ1 ));
|
||||
|
||||
// Sample displacement, rotate into frame
|
||||
float3 disp0 = _Crest_WaveBuffer.SampleLevel( sampler_Crest_linear_repeat, float3(uv0, _Crest_WaveBufferSliceIndex), 0 ).xyz;
|
||||
float3 disp1 = _Crest_WaveBuffer.SampleLevel( sampler_Crest_linear_repeat, float3(uv1, _Crest_WaveBufferSliceIndex), 0 ).xyz;
|
||||
disp0.xz = disp0.x * axisX0 + disp0.z * axisZ0;
|
||||
disp1.xz = disp1.x * axisX1 + disp1.z * axisZ1;
|
||||
float3 disp = lerp( disp0, disp1, rem / dTheta );
|
||||
|
||||
disp *= wt;
|
||||
|
||||
return float4(disp, alpha);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestVertex
|
||||
m_CrestFragment(float4)
|
||||
ENDCG
|
||||
|
||||
SubShader
|
||||
{
|
||||
ZWrite Off
|
||||
ZTest Always
|
||||
Cull Off
|
||||
|
||||
Pass
|
||||
{
|
||||
// Either additive or alpha blend for geometry waves.
|
||||
Blend [_Crest_BlendModeSource] [_Crest_BlendModeTarget]
|
||||
CGPROGRAM
|
||||
ENDCG
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
// Subsequent draws need to be additive. We cannot change render state with command
|
||||
// buffer and changing on material is not aligned with command buffer usage.
|
||||
Blend One One
|
||||
CGPROGRAM
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95ec6475fc33247d4b80d07df23f2748
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
Shader "Crest/Inputs/All/Utility"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _Crest_BlendModeSource("Source Blend Mode", Int) = 1
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _Crest_BlendModeTarget("Target Blend Mode", Int) = 1
|
||||
[Enum(UnityEngine.Rendering.BlendOp)] _Crest_BlendOperation("Blend Operation", Int) = 0
|
||||
[Enum(UnityEngine.Rendering.ColorWriteMask)] _Crest_ColorMask("Color Mask", Int) = 15
|
||||
_Crest_Value("Value", Vector) = (1, 1, 1, 1)
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend [_Crest_BlendModeSource] [_Crest_BlendModeTarget]
|
||||
BlendOp [_Crest_BlendOperation]
|
||||
ColorMask [_Crest_ColorMask]
|
||||
ZWrite Off
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
half4 _Crest_Value;
|
||||
half _Crest_Weight;
|
||||
CBUFFER_END
|
||||
|
||||
float4 Vertex(float3 positionOS : POSITION) : SV_POSITION
|
||||
{
|
||||
float3 positionWS = mul(unity_ObjectToWorld, float4(positionOS, 1.0)).xyz;
|
||||
// Correct for displacement.
|
||||
positionWS.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
return mul(UNITY_MATRIX_VP, float4(positionWS, 1.0));
|
||||
}
|
||||
|
||||
half4 Fragment() : SV_Target
|
||||
{
|
||||
return _Crest_Value * _Crest_Weight;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27b6f889dcd1b4d20919255e69078a08
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Renders water depth - signed distance from sea level to sea floor
|
||||
Shader "Crest/Inputs/Depth/Water Depth From Geometry"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
BlendOp Max
|
||||
ColorMask R
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Constants.hlsl"
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float terrainHeight : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
o.positionCS = UnityObjectToClipPos(input.positionOS);
|
||||
o.terrainHeight = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).y;
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
return float4(input.terrainHeight, 0.0, 0.0, 0.0);
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8aeab41790ee4cb1b72e19aa4a7a1ad
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,71 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// This sets base water height to Y value of geometry.
|
||||
|
||||
Shader "Crest/Inputs/Level/Water Level From Geometry"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _Crest_BlendSource("Source Blend Mode", Int) = 1
|
||||
[Enum(UnityEngine.Rendering.BlendMode)] _Crest_BlendTarget("Target Blend Mode", Int) = 0
|
||||
[Enum(UnityEngine.Rendering.BlendOp)] _Crest_BlendOperation("Blend Operation", Int) = 0
|
||||
|
||||
[HideInInspector]
|
||||
_Crest_Version("Version", Integer) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
Blend [_Crest_BlendSource] [_Crest_BlendTarget]
|
||||
BlendOp [_Crest_BlendOperation]
|
||||
|
||||
CGPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Globals.hlsl"
|
||||
|
||||
CBUFFER_START(CrestPerWaterInput)
|
||||
float3 _Crest_DisplacementAtInputPosition;
|
||||
half _Crest_Weight;
|
||||
CBUFFER_END
|
||||
|
||||
struct Attributes
|
||||
{
|
||||
float3 positionOS : POSITION;
|
||||
};
|
||||
|
||||
struct Varyings
|
||||
{
|
||||
float4 positionCS : SV_POSITION;
|
||||
float3 worldPos : TEXCOORD0;
|
||||
};
|
||||
|
||||
Varyings Vert(Attributes input)
|
||||
{
|
||||
Varyings o;
|
||||
|
||||
o.worldPos = mul(unity_ObjectToWorld, float4(input.positionOS, 1.0)).xyz;
|
||||
// Correct for displacement
|
||||
o.worldPos.xz -= _Crest_DisplacementAtInputPosition.xz;
|
||||
|
||||
o.positionCS = mul(UNITY_MATRIX_VP, float4(o.worldPos, 1.0));
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
// Write displacement to get from sea level of water to the y value of this geometry
|
||||
const float heightOffset = input.worldPos.y - g_Crest_WaterCenter.y;
|
||||
return heightOffset * _Crest_Weight;
|
||||
}
|
||||
ENDCG
|
||||
}
|
||||
}
|
||||
CustomEditor "WaveHarmonic.Crest.Editor.CustomShaderGUI"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06402bee7075b4b9fafef2b1ddf3b5cc
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestPackLevel
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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<float4> _Crest_Target;
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void PackLevel(uint3 id)
|
||||
{
|
||||
float4 displacement = _Crest_Target[id];
|
||||
|
||||
// Previously, in the water shader, we would sample the offset at the displaced
|
||||
// position so we need to do the same here to simulate that.
|
||||
const float2 position = Cascade::MakeAnimatedWaves(id.z).IDToWorld(id.xy);
|
||||
displacement.a = Cascade::MakeLevel(id.z).SampleLevel(position + displacement.xz);
|
||||
|
||||
_Crest_Target[id] = displacement;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestKernelDefault(PackLevel)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62854cc297743429aa087d7708d221c0
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3649a5e721fa420f9b546578f3987a1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,102 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestQueryDisplacement d_CrestDisplacement
|
||||
#pragma kernel CrestQueryFlow d_CrestFlow
|
||||
#pragma kernel CrestQueryDepth d_CrestDepth
|
||||
|
||||
// Must match value in script.
|
||||
#define GROUP_SIZE 64
|
||||
|
||||
StructuredBuffer<float3> _Crest_QueryPositions_MinimumGridSizes;
|
||||
RWStructuredBuffer<float3> _Crest_Target;
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Library/Macros.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"
|
||||
|
||||
#if d_CrestDisplacement
|
||||
#define d_CrestSample SampleDisplacement
|
||||
#define d_CrestMake MakeAnimatedWaves
|
||||
#define d_CrestComponents float3
|
||||
#define d_CrestReturn result
|
||||
#elif d_CrestDepth
|
||||
#define d_CrestSample SampleSignedDepthFromSeaLevelAndDistance
|
||||
#define d_CrestMake MakeDepth
|
||||
#define d_CrestComponents float2
|
||||
#define d_CrestReturn float3(result.x, result.y, 0.0)
|
||||
#else
|
||||
#define d_CrestSample SampleFlow
|
||||
#define d_CrestMake MakeFlow
|
||||
#define d_CrestComponents float2
|
||||
// Unfortunately we don't support float2 vs float3s yet, on the C# side
|
||||
#define d_CrestReturn float3(result.x, 0.0, result.y)
|
||||
#endif
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
|
||||
float3 Compute(const float2 i_Position, const float 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);
|
||||
|
||||
const Cascade cascade0 = Cascade::d_CrestMake(slice0);
|
||||
const Cascade cascade1 = Cascade::d_CrestMake(slice1);
|
||||
|
||||
const float weight0 = (1.0 - alpha) * Cascade::Make(slice0)._Weight;
|
||||
const float weight1 = (1.0 - weight0) * Cascade::Make(slice1)._Weight;
|
||||
|
||||
d_CrestComponents result =
|
||||
weight0 * cascade0.d_CrestSample(i_Position) +
|
||||
weight1 * cascade1.d_CrestSample(i_Position);
|
||||
|
||||
return d_CrestReturn;
|
||||
}
|
||||
|
||||
void Query(const uint3 id)
|
||||
{
|
||||
const float3 data = _Crest_QueryPositions_MinimumGridSizes[id.x];
|
||||
const float minimumGridSize = 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.
|
||||
float2 undisplaced = position;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
const float3 displacement = Compute(undisplaced, minimumSlice, g_Crest_WaterScale);
|
||||
const float2 error = (undisplaced + displacement.xz) - position;
|
||||
undisplaced -= error;
|
||||
}
|
||||
|
||||
position = undisplaced;
|
||||
#endif
|
||||
|
||||
_Crest_Target[id.x] = Compute(position, minimumSlice, g_Crest_WaterScale);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
[numthreads(GROUP_SIZE, 1, 1)]
|
||||
m_CrestKernelVariant(Query, Displacement)
|
||||
|
||||
[numthreads(GROUP_SIZE, 1, 1)]
|
||||
m_CrestKernelVariant(Query, Flow)
|
||||
|
||||
[numthreads(GROUP_SIZE, 1, 1)]
|
||||
m_CrestKernelVariant(Query, Depth)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7089d2ff99e0e4c9a94ef7c4711d5524
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Merged into Query.compute.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
[numthreads(1, 1, 1)]
|
||||
void CrestExecute(uint3 id : SV_DispatchThreadID) { }
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10bebb70ef1ea46d0b8babd5dda216bb
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Merged into Query.compute.
|
||||
|
||||
#pragma kernel CrestExecute
|
||||
[numthreads(1, 1, 1)]
|
||||
void CrestExecute(uint3 id : SV_DispatchThreadID) { }
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d20424c840cb64d6e93f9b46e9c2353d
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,171 @@
|
||||
// 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 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 ShapeCombineCopyDynamicWaves
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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"
|
||||
|
||||
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)
|
||||
{
|
||||
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 Cascade cascade = Cascade::MakeAnimatedWaves(slice0);
|
||||
|
||||
const float3 uv = cascade.IDToUV(id.xy);
|
||||
const float2 positionWSXZ = cascade.UVToWorld(uv);
|
||||
|
||||
float3 result = 0.0;
|
||||
|
||||
// Sample in waves for this cascade.
|
||||
{
|
||||
#if _FLOW_ON
|
||||
const half2 flow = Cascade::MakeFlow(slice0).SampleFlow(positionWSXZ);
|
||||
|
||||
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];
|
||||
#else
|
||||
result += cascade.Sample(_Crest_WaveBuffer, uv).xyz;
|
||||
#endif // _FLOW_ON
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if _DYNAMIC_WAVE_SIM_ON
|
||||
{
|
||||
// Convert dynamic wave sim to displacements.
|
||||
result += Cascade::MakeDynamicWaves(slice0)
|
||||
.SampleDynamicWavesDisplacement(positionWSXZ, _Crest_HorizontalDisplace, _Crest_DisplaceClamp);
|
||||
}
|
||||
#endif // _DYNAMIC_WAVE_SIM_ON
|
||||
|
||||
_Crest_Target[uint3(id.xy, slice0)] = float4(result, 0.0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
{
|
||||
const Cascade cascade = Cascade::MakeDynamicWaves(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);
|
||||
}
|
||||
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
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 ShapeCombineCopyDynamicWaves(uint3 id : SV_DispatchThreadID) { m_Crest::ShapeCombineCopyDynamicWaves(id); }
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02a2fc6716dfd4730a8c689ce364f132
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestShorelineColor
|
||||
|
||||
#pragma multi_compile_local __ d_Crest_ShorelineColorSource_ShorelineDistance
|
||||
#pragma multi_compile_local __ d_Crest_ShorelineScattering
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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<float3> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float _Crest_ShorelineColorMaximumDistance;
|
||||
float _Crest_ShorelineColorFalloff;
|
||||
half3 _Crest_ShorelineColor;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void ShorelineColor(uint3 id)
|
||||
{
|
||||
const uint slice0 = id.z;
|
||||
const Cascade cascade =
|
||||
#if d_Crest_ShorelineScattering
|
||||
Cascade::MakeScattering(slice0);
|
||||
#else
|
||||
Cascade::MakeAbsorption(slice0);
|
||||
#endif
|
||||
const float2 worldXZ = cascade.IDToWorld(id.xy);
|
||||
|
||||
const half depth = Cascade::MakeDepth(slice0)
|
||||
#if d_Crest_ShorelineColorSource_ShorelineDistance
|
||||
.SampleShorelineDistance(worldXZ);
|
||||
#else
|
||||
.SampleSignedDepthFromSeaLevel(worldXZ);
|
||||
#endif
|
||||
|
||||
const float shallowness = pow(1.0 - saturate(depth / _Crest_ShorelineColorMaximumDistance), _Crest_ShorelineColorFalloff);
|
||||
_Crest_Target[id] = lerp(_Crest_Target[id], _Crest_ShorelineColor, shallowness);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestKernelDefault(ShorelineColor)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 690b406e28d9a4abb842f6e39c9dc582
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,156 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Solves 2D wave equation
|
||||
|
||||
#pragma kernel CrestUpdateDynamicWaves
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float _Crest_Damping;
|
||||
float _Crest_Gravity;
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_LodChange;
|
||||
float _Crest_CourantNumber;
|
||||
float _Crest_AttenuationInShallows;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
float ComputeWaveSpeed(float wavelength, float g)
|
||||
{
|
||||
// wave speed of deep sea water waves: https://en.wikipedia.org/wiki/Wind_wave
|
||||
// https://en.wikipedia.org/wiki/Dispersion_(water_waves)#Wave_propagation_and_dispersion
|
||||
//float g = 9.81; float k = 2. * 3.141593 / wavelength; float cp = sqrt(g / k); return cp;
|
||||
const float one_over_2pi = 0.15915494;
|
||||
return sqrt(wavelength*g*one_over_2pi);
|
||||
}
|
||||
|
||||
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 Cascade cascadeSource = Cascade::MakeDynamicWavesSource(sliceIndexSource);
|
||||
|
||||
// Off either end of the cascade - not useful to sample anything from previous frame. Always initialise
|
||||
// with 0 values.
|
||||
if (sliceIndexSource < 0.0 || sliceIndexSource >= cascadeSource._Count - 1.0)
|
||||
{
|
||||
_Crest_Target[id] = (float2)0;
|
||||
return;
|
||||
}
|
||||
|
||||
const float sliceIndex = id.z;
|
||||
const Cascade cascade = Cascade::MakeDynamicWaves(sliceIndex);
|
||||
|
||||
const float2 worldPosXZ = cascade.IDToWorld(id.xy);
|
||||
const float gridSize = cascade._Texel;
|
||||
|
||||
// Min wavelength for this scale
|
||||
const float wavelength = 2.0 * gridSize;
|
||||
// could make velocity depend on waves
|
||||
//float h = max(waterSignedDepth + ft, 0.);
|
||||
float c = ComputeWaveSpeed(wavelength, _Crest_Gravity);
|
||||
|
||||
const float dt = _Crest_SimDeltaTime;
|
||||
|
||||
// Clamp based on my main man Courant
|
||||
c = min( c, _Crest_CourantNumber * gridSize / dt );
|
||||
|
||||
const half waterDepth = Cascade::MakeDepth(sliceIndex).SampleSignedDepthFromSeaLevel(worldPosXZ) +
|
||||
Cascade::MakeLevel(sliceIndex).SampleLevel(worldPosXZ);
|
||||
|
||||
// Wave reflections off geometry.
|
||||
if (waterDepth <= 0.0)
|
||||
{
|
||||
_Crest_Target[id] = float2(0.0, 0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
const half2 velocity = Cascade::MakeFlow(sliceIndex).SampleFlow(worldPosXZ);
|
||||
const float2 worldPosXZFlowed = worldPosXZ - dt * velocity;
|
||||
const float3 uv_source = cascadeSource.WorldToUV(worldPosXZFlowed);
|
||||
|
||||
// weighting for source position - weight 0 for off texture accesses to stop streaky artifacts
|
||||
float2 distToEdge = min(uv_source.xy, 1.0 - uv_source.xy);
|
||||
// soft, wide feather at boundary to balance reflections vs streaking under motion
|
||||
const float edgeFeather = 0.1;
|
||||
float weightEdge = saturate(min(distToEdge.x, distToEdge.y) / edgeFeather);
|
||||
weightEdge = lerp(0.95, 1.0, weightEdge);
|
||||
|
||||
// compute axes of laplacian kernel - rotated every frame
|
||||
const float e = cascadeSource._OneOverResolution;
|
||||
const float3 X = float3(1.0, 0.0, 0.0);
|
||||
const float3 Y = float3(-X.y, X.x, 0.0);
|
||||
|
||||
// no border wrap mode for RTs in unity it seems,
|
||||
// so make any off-array reads 0 manually
|
||||
const bool insideTarget = sliceIndexSource <= cascadeSource._Count && sliceIndexSource >= 0;
|
||||
|
||||
float fxm, fym, fxp, fyp; float2 ft_v;
|
||||
ft_v = fxm = fym = fxp = fyp = 0.0;
|
||||
|
||||
if (insideTarget)
|
||||
{
|
||||
fxm = cascadeSource.SampleDynamicWaves(uv_source - e * X).x; // x minus
|
||||
fym = cascadeSource.SampleDynamicWaves(uv_source - e * Y).x; // y minus
|
||||
fxp = cascadeSource.SampleDynamicWaves(uv_source + e * X).x; // x plus
|
||||
fyp = cascadeSource.SampleDynamicWaves(uv_source + e * Y).x; // y plus
|
||||
ft_v = cascadeSource.SampleDynamicWaves(uv_source);
|
||||
}
|
||||
|
||||
// wave propagation
|
||||
|
||||
// t - current value before update
|
||||
const float ft = ft_v.x;
|
||||
const float vt = ft_v.y;
|
||||
|
||||
// wave equation
|
||||
float coeff = dt * c * c / (gridSize * gridSize);
|
||||
float vtp = vt + coeff * (fxm + fxp + fym + fyp - 4.0 * ft);
|
||||
|
||||
// damping. works ok at low dts, doesnt damp well at high dts which counter intuitively leads to instabilities, i think.
|
||||
vtp *= 1.0 - min(1.0, _Crest_Damping * dt);
|
||||
|
||||
// dampen towards boundaries smoothly to eliminate reflections and streaking
|
||||
vtp *= weightEdge;
|
||||
|
||||
// integrate velocity onto position
|
||||
float ftp = ft + dt * vtp;
|
||||
ftp *= weightEdge;
|
||||
|
||||
if (_Crest_AttenuationInShallows > 0.0)
|
||||
{
|
||||
// attenuate waves based on water depth. if depth is greater than 0.5*wavelength, water is considered Deep and wave is
|
||||
// unaffected. if depth is less than this, wave velocity decreases. waves will then bunch up and grow in amplitude and
|
||||
// eventually break. i model "Deep" water, but then simply ramp down waves in non-deep water with a linear multiplier.
|
||||
// http://hyperphysics.phy-astr.gsu.edu/hbase/Waves/watwav2.html
|
||||
// http://hyperphysics.phy-astr.gsu.edu/hbase/watwav.html#c1
|
||||
const float depthMul = 1.0 - (1.0 - saturate(2.0 * waterDepth / wavelength)) * dt * 2.0;
|
||||
ftp *= _Crest_AttenuationInShallows * depthMul + (1.0 - _Crest_AttenuationInShallows);
|
||||
}
|
||||
|
||||
// Clear for safety as there is a potential for bad values which will propagate throughout the entire simulation.
|
||||
// Zero is not ideal but better than bad values. Cases:
|
||||
// - bad values randomly being sampled from the source texture, but ostensibly not injected by an input
|
||||
// - bad values sometimes appearing after an hour or so runtime
|
||||
if (!isfinite(ftp) || !isfinite(vtp))
|
||||
{
|
||||
ftp = 0.0;
|
||||
vtp = 0.0;
|
||||
}
|
||||
|
||||
_Crest_Target[id] = float2(ftp, vtp);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestKernelDefault(UpdateDynamicWaves)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ba116507793f45b5ba3f016f0837660
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#pragma kernel CrestUpdateFoam
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
|
||||
#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<float> _Crest_Target;
|
||||
|
||||
CBUFFER_START(CrestPerMaterial)
|
||||
float _Crest_FoamFadeRate;
|
||||
float _Crest_FoamMaximum;
|
||||
float _Crest_WaveFoamStrength;
|
||||
float _Crest_WaveFoamCoverage;
|
||||
float _Crest_ShorelineFoamMaxDepth;
|
||||
float _Crest_ShorelineFoamStrength;
|
||||
float _Crest_SimDeltaTime;
|
||||
float _Crest_SimDeltaTimePrev;
|
||||
float _Crest_LodChange;
|
||||
bool _Crest_NeedsPrewarming;
|
||||
uint _Crest_MinimumWavesSlice;
|
||||
float _Crest_FoamNegativeDepthPriming;
|
||||
CBUFFER_END
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
void UpdateFoam(uint3 id)
|
||||
{
|
||||
const uint slice0 = id.z;
|
||||
const Cascade cascade = Cascade::MakeFoam(slice0);
|
||||
const float2 worldPosXZ = cascade.IDToWorld(id.xy);
|
||||
half foam = 0.0;
|
||||
|
||||
// Sample from previous frame.
|
||||
{
|
||||
const half2 velocity = Cascade::MakeFlow(slice0).SampleFlow(worldPosXZ);
|
||||
const float2 positionXZ = worldPosXZ - _Crest_SimDeltaTime * velocity;
|
||||
// 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);
|
||||
foam = Cascade::MakeFoamSource(sliceIndexSource).SampleFoamOverflow(positionXZ, 1.0);
|
||||
}
|
||||
|
||||
// fade
|
||||
foam *= max(0.0, 1.0 - _Crest_FoamFadeRate * _Crest_SimDeltaTime);
|
||||
|
||||
// Prewarm wave foam. 1.0 / _Crest_FoamFadeRate perfectly matches a paused water in edit mode, but this is an unnatural
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
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
|
||||
// shoreline foam.
|
||||
simDeltaTime = _Crest_NeedsPrewarming ? (1.0 / _Crest_FoamFadeRate) : _Crest_SimDeltaTime;
|
||||
|
||||
// Add foam in shallow water. use the displaced position to ensure we add foam where world objects are.
|
||||
const half depth = Cascade::MakeDepth(slice0).SampleSignedDepthFromSeaLevel(worldPosXZ + displacement.xz) + displacement.y;
|
||||
foam += _Crest_ShorelineFoamStrength * simDeltaTime * saturate(1.0 - depth / _Crest_ShorelineFoamMaxDepth);
|
||||
|
||||
// Priming foam when under terrain helps with SWS leading-edge foam.
|
||||
if (depth <= _Crest_FoamNegativeDepthPriming)
|
||||
{
|
||||
foam += simDeltaTime;
|
||||
}
|
||||
|
||||
_Crest_Target[id] = min(foam, _Crest_FoamMaximum);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
|
||||
m_CrestKernelDefault(UpdateFoam)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1149a28b1712c464fbc3d96bea0bc34d
|
||||
ComputeShaderImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,175 @@
|
||||
// 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.
|
||||
half2 shadow = Cascade::MakeShadowSource(_Crest_LodIndex + g_Crest_LodChange).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)
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d67c7804ecde845f19a01df7b5097557
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,170 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Soft shadow term is red, hard shadow term is green.
|
||||
|
||||
Shader "Hidden/Crest/Simulation/Update Shadow"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
PackageRequirements
|
||||
{
|
||||
"com.unity.render-pipelines.high-definition"
|
||||
}
|
||||
|
||||
Tags { "RenderPipeline"="HDRenderPipeline" }
|
||||
|
||||
Pass
|
||||
{
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
// #pragma enable_d3d11_debug_symbols
|
||||
|
||||
// SHADOW_ULTRA_LOW uses Gather which is 4.5. HDRP minimum is 5.0 so this is fine.
|
||||
#pragma target 4.5
|
||||
|
||||
// TODO: We might be able to expose this to give developers the option.
|
||||
// #pragma multi_compile SHADOW_ULTRA_LOW SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH
|
||||
|
||||
// Ultra low uses Gather to filter which should be same cost as not filtering. See algorithms per keyword:
|
||||
// Runtime/Lighting/Shadow/HDShadowAlgorithms.hlsl
|
||||
#define SHADOW_ULTRA_LOW
|
||||
#define AREA_SHADOW_LOW
|
||||
#define PUNCTUAL_SHADOW_ULTRA_LOW
|
||||
#define DIRECTIONAL_SHADOW_ULTRA_LOW
|
||||
|
||||
#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"
|
||||
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl"
|
||||
|
||||
float4x4 _Crest_ViewProjectionMatrix;
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl"
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
half SampleShadows(const float4 i_positionWS)
|
||||
{
|
||||
// Get directional light data. By definition we only have one directional light casting shadow.
|
||||
DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
|
||||
HDShadowContext context = InitShadowContext();
|
||||
|
||||
// Zeros are for screen space position and world space normal which are for filtering and normal bias
|
||||
// respectively. They did not appear to have an impact.
|
||||
half shadows = GetDirectionalShadowAttenuation(context, 0, i_positionWS.xyz, 0, _DirectionalShadowIndex, -light.forward);
|
||||
// Apply shadow strength from main light.
|
||||
shadows = LerpWhiteTo(shadows, light.shadowDimmer);
|
||||
|
||||
return shadows;
|
||||
}
|
||||
|
||||
half ComputeShadowFade(const float4 i_positionWS)
|
||||
{
|
||||
// TODO: Work out shadow fade.
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
PackageRequirements
|
||||
{
|
||||
"com.unity.render-pipelines.universal"
|
||||
}
|
||||
|
||||
Tags { "RenderPipeline"="UniversalPipeline" }
|
||||
|
||||
Pass
|
||||
{
|
||||
HLSLPROGRAM
|
||||
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
// #pragma enable_d3d11_debug_symbols
|
||||
|
||||
// Maybe this is the equivalent of the SHADOW_COLLECTOR_PASS define? Inspired from com.unity.render-pipelines.universal/Shaders/Utils/ScreenSpaceShadows.shader
|
||||
#define _MAIN_LIGHT_SHADOWS_CASCADE
|
||||
#define MAIN_LIGHT_CALCULATE_SHADOWS
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
|
||||
|
||||
#define CREST_SAMPLE_SHADOW_HARD
|
||||
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl"
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
half SampleShadows(const float4 i_positionWS)
|
||||
{
|
||||
// Includes soft shadows if _SHADOWS_SOFT is defined (requires multi-compile pragma).
|
||||
return MainLightRealtimeShadow(TransformWorldToShadowCoord(i_positionWS.xyz));
|
||||
}
|
||||
|
||||
half ComputeShadowFade(const float4 i_positionWS)
|
||||
{
|
||||
return GetShadowFade(i_positionWS.xyz);
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Pass
|
||||
{
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vertex
|
||||
#pragma fragment Fragment
|
||||
|
||||
#pragma multi_compile_shadowcollector
|
||||
|
||||
// #pragma enable_d3d11_debug_symbols
|
||||
|
||||
#define CREST_SAMPLE_SHADOW_HARD
|
||||
#define d_Crest_ReceiveShadowsTransparent 1
|
||||
|
||||
#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/Shadows.hlsl"
|
||||
#include "Packages/com.waveharmonic.crest/Runtime/Shaders/Data/UpdateShadow.hlsl"
|
||||
|
||||
m_CrestNameSpace
|
||||
|
||||
half SampleShadows(const float4 i_positionWS)
|
||||
{
|
||||
// NOTE: "Shadow Projection > Close Fit" can still produce artefacts when away from caster, but this
|
||||
// appears to be an improvement over the compute shader.
|
||||
float4 shadowCoord = GET_SHADOW_COORDINATES(i_positionWS);
|
||||
half shadows = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, shadowCoord);
|
||||
if (_Crest_ClearShadows) shadows = 1.0;
|
||||
shadows = lerp(_LightShadowData.r, 1.0, shadows);
|
||||
|
||||
return shadows;
|
||||
}
|
||||
|
||||
half ComputeShadowFade(const float4 i_positionWS)
|
||||
{
|
||||
float z = dot(i_positionWS.xyz - _WorldSpaceCameraPos.xyz, unity_CameraToWorld._m02_m12_m22);
|
||||
float fadeDistance = UnityComputeShadowFadeDistance(i_positionWS.xyz, z);
|
||||
float fade = UnityComputeShadowFade(fadeDistance);
|
||||
return fade;
|
||||
}
|
||||
|
||||
m_CrestNameSpaceEnd
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6195b173b90b246ac9f5300b7e2aa482
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user