移除水

This commit is contained in:
2025-06-21 21:58:06 +08:00
parent d61516a576
commit e9f76d0f11
1566 changed files with 9218 additions and 300913 deletions

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1dfc7e28d58b14deaa99d95b6ccd0cc5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 59056ec4af44c42dd8f36c6a25eece46
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,67 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 382a5d8b1147b4e78a31353c022b8e15, type: 3}
m_Name: WavesCalm
m_EditorClassIdentifier:
_Version: 0
_WaveDirectionVariance: 56
_GravityScale: 1
_Multiplier: 1
_PowerLogarithmicScales:
- -7.39794
- -7.39794
- -7.39794
- -5.526391
- -4.8159227
- -4.413246
- -4.081862
- -3.7773297
- -3.8762438
- -3.824092
- -3.4170768
- -3.2395759
- -3.2135434
- -7.39794
_PowerDisabled: 0000000000000000000000000000
_ChopScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_GravityScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_Chop: 1
_ShowAdvancedControls: 0
_Model: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2985cdff827b8472bafc9e2da18fbf06
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,67 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 382a5d8b1147b4e78a31353c022b8e15, type: 3}
m_Name: WavesDead
m_EditorClassIdentifier:
_Version: 0
_WaveDirectionVariance: 56
_GravityScale: 1
_Multiplier: 1
_PowerLogarithmicScales:
- -7.39794
- -7.39794
- -7.39794
- -5.526391
- -4.8159227
- -4.413246
- -4.081862
- -3.7773297
- -3.8762438
- -3.824092
- -3.4170768
- -3.2395759
- -3.2135434
- -7.39794
_PowerDisabled: 0000010101010101010101010101
_ChopScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_GravityScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_Chop: 1
_ShowAdvancedControls: 0
_Model: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1c2709c536afb4bf6b90d29d03758f0d
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,67 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 382a5d8b1147b4e78a31353c022b8e15, type: 3}
m_Name: WavesModerate
m_EditorClassIdentifier:
_Version: 0
_WaveDirectionVariance: 90
_GravityScale: 1
_Multiplier: 1
_PowerLogarithmicScales:
- -7.1418724
- -6.539813
- -5.937754
- -5.3357
- -4.733663
- -4.1316957
- -3.5300062
- -2.929428
- -2.3332953
- -1.7549441
- -1.2477198
- -1.0250019
- -1.9403106
- -7.39794
_PowerDisabled: 0000000000000000000000000000
_ChopScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_GravityScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_Chop: 1.54
_ShowAdvancedControls: 0
_Model: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: ce5a3f1aff978418c90b45d58f574528
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,67 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 382a5d8b1147b4e78a31353c022b8e15, type: 3}
m_Name: WavesModerateSmooth
m_EditorClassIdentifier:
_Version: 0
_WaveDirectionVariance: 90
_GravityScale: 1
_Multiplier: 1
_PowerLogarithmicScales:
- -7.39794
- -7.39794
- -7.39794
- -6.302198
- -5.9911127
- -4.7409434
- -4.5640044
- -4.4886622
- -2.9012794
- -1.1004922
- -0.86166644
- -0.36967784
- 1.3923892
- 1.60206
_PowerDisabled: 0000000000000000000000000000
_ChopScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_GravityScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_Chop: 1.6
_ShowAdvancedControls: 0
_Model: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 8c508e8f723e64d21a5219d1530e6ffd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,67 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 382a5d8b1147b4e78a31353c022b8e15, type: 3}
m_Name: WavesShoreline
m_EditorClassIdentifier:
_Version: 0
_WaveDirectionVariance: 20
_GravityScale: 1
_Multiplier: 1
_PowerLogarithmicScales:
- -7.1418724
- -6.539813
- -5.937754
- -5.3357
- -4.733663
- -3.2727537
- -2.97585
- -2.4583952
- -1.6128922
- -1.7549441
- -1.2477198
- -1.0250019
- -1.9403106
- -7.39794
_PowerDisabled: 0101010101000100000001010101
_ChopScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_GravityScales:
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
- 1
_Chop: 1.54
_ShowAdvancedControls: 0
_Model: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 120e704899e8944e9baf31404179e7ce
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 05822262553744bae9714920130c0899
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2a214bb0d815f498aaee2e050a73697f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,91 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ClipExcludeArea
m_Shader: {fileID: 4800000, guid: 288a089f90e714983b8a760dd49e5a5c, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints:
- _Crest_Version: 0
m_Floats:
- _BumpScale: 1
- _ColorWriteMask: 4
- _Crest_BlendOperation: 0
- _Crest_BlendSource: 1
- _Crest_BlendTarget: 0
- _Crest_ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _Crest_Value: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1131dd19089574b28a35a17f1ea28f32
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,87 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ClipIncludeArea
m_Shader: {fileID: 4800000, guid: 288a089f90e714983b8a760dd49e5a5c, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints:
- _Crest_Version: 0
m_Floats:
- _BumpScale: 1
- _ColorWriteMask: 4
- _Crest_ColorMask: 15
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _Crest_Value: {r: 0, g: 0, b: 0, a: 0}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 2a561aef740e74d45a7db7b9dc255dd7
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,30 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: PushWaterUnderConvexHull
m_Shader: {fileID: 4800000, guid: 170672f06b4574545ba8305cb7d11091, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints:
- _Crest_Version: 0
m_Floats: []
m_Colors: []
m_BuildTextureStacks: []

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: fbe311c1027b04a3d8401654d4a9d72f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,30 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: WaterLevelFromGeometry
m_Shader: {fileID: 4800000, guid: 06402bee7075b4b9fafef2b1ddf3b5cc, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints:
- _Crest_Version: 0
m_Floats: []
m_Colors: []
m_BuildTextureStacks: []

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 0f5eb7d739bac4dcf97596cc6b192494
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,75 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Water Volume
m_Shader: {fileID: 4800000, guid: 034b985bd9c344992af148e26d2cdb24, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- d_Dithering
- d_Meniscus
m_InvalidKeywords:
- _ALPHATEST_ON
- _BUILTIN_ALPHATEST_ON
- _BUILTIN_AlphaClip
- _BUILTIN_SURFACE_TYPE_TRANSPARENT
- _DOUBLESIDED_ON
- _ENABLE_FOG_ON_TRANSPARENT
- _SPECULAR_SETUP
- _SURFACE_TYPE_TRANSPARENT
- _TRANSPARENT_WRITES_MOTION_VEC
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _Crest_CausticsDistortionTexture:
m_Texture: {fileID: 2800000, guid: 7aa3f69cfb40b429a865c45a7271c5f5, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _Crest_CausticsTexture:
m_Texture: {fileID: 2800000, guid: 1407209016967410da2ae6fdd4d97fc6, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints:
- _Crest_DataSliceOffset: 13
- _Crest_DitheringEnabled: 1
- _Crest_MeniscusEnabled: 1
- _Crest_Version: 0
m_Floats:
- CREST_FLOW: 0
- _Crest_AmbientTerm: 1
- _Crest_Anisotropy: 0.5
- _Crest_CausticsDepthOfField: 6
- _Crest_CausticsDistortionScale: 250
- _Crest_CausticsDistortionStrength: 0.16
- _Crest_CausticsEnabled: 1
- _Crest_CausticsFocalDepth: 2
- _Crest_CausticsMotionBlur: 1
- _Crest_CausticsScrollSpeed: 1
- _Crest_CausticsStrength: 3.2
- _Crest_CausticsTextureAverage: 0.07
- _Crest_CausticsTextureScale: 50
- _Crest_DirectTerm: 1
- _Crest_DitheringIntensity: 1
- _Crest_ExtinctionMultiplier: 1
- _Crest_OutScatteringExtinctionFactor: 0.2
- _Crest_OutScatteringFactor: 0.2
- _Crest_ShadowsAffectsAmbientFactor: 0.5
- _Crest_SunBoost: 2
m_Colors:
- _Crest_AbsorptionColor: {r: 0.34162676, g: 0.6954546, b: 0.85, a: 0.1019608}
- _Crest_Scattering: {r: 0, g: 0.09803919, b: 0.19999996, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: f2b096e4d95e646c49d48ece0afa0547
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,101 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-5994654682710206810
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: da692e001514ec24dbc4cca1949ff7e8, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 13
hdPluginSubTargetMaterialVersions:
m_Keys: []
m_Values:
--- !u!114 &-4042563326011365698
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 9
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Water
m_Shader: {fileID: -6465566751694194690, guid: 00ffe7d0b7161420897069dc6e12822c, type: 3}
m_Parent: {fileID: -876546973899608171, guid: 00ffe7d0b7161420897069dc6e12822c, type: 3}
m_ModifiedSerializedProperties: 0
m_ValidKeywords:
- _ALPHATEST_ON
- _BUILTIN_ALPHATEST_ON
- _BUILTIN_AlphaClip
- _BUILTIN_SURFACE_TYPE_TRANSPARENT
- _SPECULAR_SETUP
- _SURFACE_TYPE_TRANSPARENT
m_InvalidKeywords:
- _DOUBLESIDED_ON
- _ENABLE_FOG_ON_TRANSPARENT
- _TRANSPARENT_WRITES_MOTION_VEC
m_LightmapFlags: 2
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 1
m_CustomRenderQueue: 3000
stringTagMap:
MotionVector: User
RenderType: Transparent
disabledShaderPasses:
- TransparentDepthPostpass
- TransparentBackface
- RayTracingPrepass
- SHADOWCASTER
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats:
- _AlphaDstBlend: 10
- _BUILTIN_DstBlend: 10
- _BUILTIN_QueueControl: 0
- _BUILTIN_SrcBlend: 5
- _BUILTIN_ZWrite: 1
- _CullMode: 0
- _CullModeForward: 0
- _DstBlend: 10
- _QueueControl: 0
- _RefractionModel: 0
- _SrcBlend: 5
- _ZTestGBuffer: 3
- _ZWrite: 1
m_Colors:
- _DoubleSidedConstants: {r: 1, g: 1, b: 1, a: 0}
m_BuildTextureStacks: []
m_AllowLocking: 1
--- !u!114 &4748330692745026848
MonoBehaviour:
m_ObjectHideFlags: 11
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 639247ca83abc874e893eb93af2b5e44, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 0

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 8ab064b6606504a55b489af2787350c2
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 77ee3d78b64074b2cba27c3b39c6084a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,75 +0,0 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1516456258233481520
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5573293823876610619}
- component: {fileID: 6121422689720352427}
m_Layer: 4
m_Name: Chunk
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5573293823876610619
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1516456258233481520}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 1
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &6121422689720352427
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1516456258233481520}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 2
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials: []
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: 17840562212c147d6bdb5144d35bc442
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: cfeba4e421ad54be597d83f0638a0c55
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,33 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
// Define empty namespaces for when assemblies are not present.
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Samples.Ripples")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.CPUQueries")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.CPUQueries.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Paint")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Paint.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Scripting")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.ShallowWater")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.ShallowWater.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Splines")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Splines.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Watercraft")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Watercraft.Editor")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Whirlpool")]
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Whirlpool.Editor")]
namespace UnityEngine.InputSystem { }
namespace UnityEngine.Rendering.HighDefinition { }
namespace UnityEngine.Rendering.RenderGraphModule { }
namespace UnityEngine.Rendering.Universal { }
namespace WaveHarmonic.Crest.Editor { }
namespace WaveHarmonic.Crest.Paint { }
namespace WaveHarmonic.Crest.Splines { }
namespace WaveHarmonic.Crest.RelativeSpace { }

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: bc511f9846b8c404091aace6915510df
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,33 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
namespace WaveHarmonic.Crest
{
static class Constants
{
#if CREST_OCEAN
const string k_Prefix = "Crest 5 ";
#else
const string k_Prefix = "Crest ";
#endif
const string k_MenuScripts = "Crest/";
public const string k_MenuPrefixScripts = k_MenuScripts + k_Prefix;
public const string k_MenuPrefixInternal = k_MenuScripts + "Internal/";
public const string k_MenuPrefixDebug = k_MenuScripts + "Debug/" + k_Prefix;
public const string k_MenuPrefixInputs = k_MenuScripts + "Inputs/" + k_Prefix;
public const string k_MenuPrefixTime = k_MenuScripts + "Time/" + k_Prefix;
public const string k_MenuPrefixSpline = k_MenuScripts + "Spline/" + k_Prefix;
public const string k_MenuPrefixPhysics = k_MenuScripts + "Physics/" + k_Prefix;
public const string k_MenuPrefixSample = k_MenuScripts + "Sample/" + k_Prefix;
#if UNITY_EDITOR
public const int k_FieldGroupOrder = Editor.Inspector.k_FieldGroupOrder;
#else
public const int k_FieldGroupOrder = 0;
#endif
// Unity only supports textures up to a size of 16384, even if maxTextureSize returns a larger size.
// https://docs.unity3d.com/ScriptReference/SystemInfo-maxTextureSize.html
public const int k_MaximumTextureResolution = 16384;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5b3ea5ad983894f72b6478985b8238d3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 055e56f78a8f84633baaceee3f56970f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,68 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using WaveHarmonic.Crest.Internal;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Overrides the absorption color.
/// </summary>
public sealed partial class AbsorptionLod : ColorLod
{
// Orange
internal static readonly Color s_GizmoColor = new(1f, 165f / 255f, 0f, 0.5f);
internal static readonly Color s_DefaultColor = new(0.342f, 0.695f, 0.85f, 0.102f);
static new class ShaderIDs
{
public static readonly int s_SampleAbsorptionSimulation = Shader.PropertyToID("g_Crest_SampleAbsorptionSimulation");
}
internal override string ID => "Absorption";
internal override string Name => "Absorption";
internal override Color GizmoColor => s_GizmoColor;
private protected override bool NeedToReadWriteTextureData => true;
private protected override bool RequiresClearBorder => true;
private protected override bool AlwaysClear => true;
private protected override Color ClearColor
{
get
{
var color = Color.clear;
if (_Water.Material != null)
{
color = _Water.Material.GetVector(WaterRenderer.ShaderIDs.s_Absorption);
color.a = 0f;
}
return color;
}
}
private protected override int GlobalShaderID => ShaderIDs.s_SampleAbsorptionSimulation;
internal AbsorptionLod()
{
_ShorelineColor = (s_DefaultColor * 1.5f).Clamped01();
}
private protected override void SetShorelineColor(Color previous, Color current)
{
if (previous == current) return;
_ShorelineColorValue = WaterRenderer.CalculateAbsorptionValueFromColor(current);
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a6548e15197394afb8759ec50e918937
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,44 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// A color layer that can be composited onto the water surface.
/// </summary>
[FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Include, (int)LodTextureFormatMode.Performance, (int)LodTextureFormatMode.Manual)]
public sealed partial class AlbedoLod : Lod
{
internal static readonly Color s_GizmoColor = new(1f, 0f, 1f, 0.5f);
internal override string ID => "Albedo";
internal override Color GizmoColor => s_GizmoColor;
private protected override Color ClearColor => Color.clear;
private protected override bool NeedToReadWriteTextureData => false;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
LodTextureFormatMode.Manual => _TextureFormat,
_ => GraphicsFormat.R8G8B8A8_UNorm,
};
internal AlbedoLod()
{
_Resolution = 768;
_TextureFormat = GraphicsFormat.R8G8B8A8_UNorm;
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e6e1410b6b6b14d1db0a242b6d4efef5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,581 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
namespace WaveHarmonic.Crest
{
abstract class BakedWaveData : ScriptableObject
{
public abstract ICollisionProvider CreateCollisionProvider();
public abstract float WindSpeed { get; }
}
//
// Collision
//
/// <summary>
/// The source of collisions (ie water shape).
/// </summary>
public enum CollisionSource
{
/// <summary>
/// No collision source. Flat water.
/// </summary>
None = 0,
// GerstnerWavesCPU = 1,
/// <summary>
/// Uses AsyncGPUReadback to retrieve data from GPU to CPU.
/// </summary>
/// <remarks>
/// This is the most optimal approach.
/// </remarks>
GPU = 2,
/// <summary>
/// Computes data entirely on the CPU.
/// </summary>
CPU = 3,
}
/// <summary>
/// The pass to render displacement into.
/// </summary>
public enum DisplacementPass
{
/// <summary>
/// Displacement that is dependent on an LOD (eg waves).
/// </summary>
/// <remarks>
/// Uses filtering to determine which LOD to write to.
/// </remarks>
[Tooltip("Displacement that is dependent on an LOD (eg waves).\n\nUses filtering to determine which LOD to write to.")]
LodDependent,
/// <summary>
/// Renders to all LODs.
/// </summary>
[Tooltip("Renders to all LODs.")]
LodIndependent,
/// <summary>
/// Renders to all LODs, but as a separate pass.
/// </summary>
/// <remarks>
/// Typically used to render visual displacement which does not affect collisions.
/// </remarks>
[Tooltip("Renders to all LODs, but as a separate pass.\n\nTypically used to render visual displacement which does not affect collisions.")]
[InspectorName("Lod Independent (Last)")]
LodIndependentLast,
}
/// <summary>
/// Flags to enable extra collsion layers.
/// </summary>
[System.Flags]
public enum CollisionLayers
{
// NOTE: numbers must be in order for defaults to work (everything first).
/// <summary>
/// All layers.
/// </summary>
[Tooltip("All layers.")]
Everything = -1,
/// <summary>
/// No extra layers (ie single layer).
/// </summary>
[Tooltip("No extra layers (ie single layer).")]
Nothing,
/// <summary>
/// Separate layer for dynamic waves.
/// </summary>
/// <remarks>
/// Dynamic waves are normally combined together for efficiency. By enabling this
/// layer, dynamic waves are combined and added in a separate pass.
/// </remarks>
[Tooltip("Separate layer for dynamic waves.\n\nDynamic waves are normally combined together for efficiency. By enabling this layer, dynamic waves are combined and added in a separate pass.")]
DynamicWaves = 1 << 1,
/// <summary>
/// Extra displacement layer for visual displacement.
/// </summary>
[Tooltip("Extra displacement layer for visual displacement.")]
Displacement = 1 << 2,
}
/// <summary>
/// Captures waves/shape that is drawn kinematically - there is no frame-to-frame
/// state.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item>
/// A combine pass is done which combines downwards from low detail LODs into
/// the high detail LODs.
/// </item>
/// <item>
/// The LOD data is passed to the water material when the surface is drawn.
/// <item>
/// </item>
/// <see cref="DynamicWavesLod"/> adds its results into this data. They piggy back
/// off the combine pass and subsequent assignment to the water material.
/// </item>
/// </list>
/// The RGB channels are the XYZ displacement from a rest plane at water level to
/// the corresponding displaced position on the surface.
/// </remarks>
[@FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)]
public sealed partial class AnimatedWavesLod : Lod<ICollisionProvider>
{
[@Space(10)]
[Tooltip("Shifts wavelengths to maintain quality for higher resolutions.\n\nSet this to 2 to improve wave quality. In some cases like flowing rivers, this can make a substantial difference to visual stability. We recommend doubling the Resolution on the WaterRenderer component to preserve detail after making this change.")]
[@Range(1f, 4f)]
[@GenerateAPI]
[SerializeField]
float _WaveResolutionMultiplier = 1f;
[Tooltip("How much waves are dampened in shallow water.")]
[@Range(0f, 1f)]
[@GenerateAPI]
[SerializeField]
float _AttenuationInShallows = 0.95f;
[Tooltip("Any water deeper than this will receive full wave strength.\n\nThe lower the value, the less effective the depth cache will be at attenuating very large waves. Set to the maximum value (1,000) to disable.")]
[@Range(1f, 1000f)]
[@GenerateAPI]
[SerializeField]
float _ShallowsMaximumDepth = 1000f;
[@Heading("Collisions")]
[Tooltip("Where to obtain water shape on CPU for physics / gameplay.")]
[@GenerateAPI(Setter.Internal)]
[@DecoratedField, SerializeField]
internal CollisionSource _CollisionSource = CollisionSource.GPU;
[Tooltip("Collision layers to enable.\n\nSome layers will have overhead with CPU, GPU and memory.")]
[@Predicated(nameof(_CollisionSource), inverted: true, nameof(CollisionSource.GPU))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal CollisionLayers _CollisionLayers = CollisionLayers.Everything;
[Tooltip("Maximum number of wave queries that can be performed when using GPU queries.")]
[@Predicated(nameof(_CollisionSource), true, nameof(CollisionSource.GPU))]
[@GenerateAPI(Setter.None)]
[@DecoratedField, SerializeField]
int _MaximumQueryCount = QueryBase.k_DefaultMaximumQueryCount;
[@Predicated(nameof(_CollisionSource), true, nameof(CollisionSource.CPU))]
[@DecoratedField, SerializeField]
internal BakedWaveData _BakedWaveData;
internal static new partial class ShaderIDs
{
public static readonly int s_WaveBuffer = Shader.PropertyToID("_Crest_WaveBuffer");
public static readonly int s_DynamicWavesTarget = Shader.PropertyToID("_Crest_DynamicWavesTarget");
public static readonly int s_AnimatedWavesTarget = Shader.PropertyToID("_Crest_AnimatedWavesTarget");
public static readonly int s_AttenuationInShallows = Shader.PropertyToID("_Crest_AttenuationInShallows");
}
internal static readonly Color s_GizmoColor = new(0f, 1f, 0f, 0.5f);
/// <summary>
/// Turn shape combine pass on/off. Debug only - stripped in builds.
/// </summary>
internal static bool s_Combine = true;
internal override string ID => "AnimatedWaves";
internal override string Name => "Animated Waves";
internal override Color GizmoColor => s_GizmoColor;
private protected override bool NeedToReadWriteTextureData => true;
private protected override Color ClearColor => Color.black;
internal override int BufferCount => _Water.WriteMotionVectors ? 2 : 1;
internal override bool RunsInHeadless => true;
// NOTE: Tried RGB111110Float but errors becomes visible. One option would be to use a UNORM setup.
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
LodTextureFormatMode.Performance => GraphicsFormat.R16G16B16A16_SFloat,
LodTextureFormatMode.Precision => GraphicsFormat.R32G32B32A32_SFloat,
LodTextureFormatMode.Manual => _TextureFormat,
_ => throw new System.NotImplementedException(),
};
ComputeShader _CombineShader;
int _KernalShapeCombine = -1;
int _KernalShapeCombine_DISABLE_COMBINE = -1;
int _KernalShapeCombine_FLOW_ON = -1;
int _KernalShapeCombine_FLOW_ON_DISABLE_COMBINE = -1;
int _KernalShapeCombine_DYNAMIC_WAVE_SIM_ON = -1;
int _KernalShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE = -1;
int _KernalShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON = -1;
int _KernalShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE = -1;
internal AnimatedWavesLod()
{
_Enabled = true;
_OverrideResolution = false;
_TextureFormat = GraphicsFormat.R16G16B16A16_SFloat;
}
internal override void Initialize()
{
_CombineShader = WaterResources.Instance.Compute._ShapeCombine;
if (_CombineShader == null)
{
_Valid = false;
return;
}
base.Initialize();
}
private protected override void Allocate()
{
base.Allocate();
_KernalShapeCombine = _CombineShader.FindKernel("ShapeCombine");
_KernalShapeCombine_DISABLE_COMBINE = _CombineShader.FindKernel("ShapeCombine_DISABLE_COMBINE");
_KernalShapeCombine_FLOW_ON = _CombineShader.FindKernel("ShapeCombine_FLOW_ON");
_KernalShapeCombine_FLOW_ON_DISABLE_COMBINE = _CombineShader.FindKernel("ShapeCombine_FLOW_ON_DISABLE_COMBINE");
_KernalShapeCombine_DYNAMIC_WAVE_SIM_ON = _CombineShader.FindKernel("ShapeCombine_DYNAMIC_WAVE_SIM_ON");
_KernalShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE = _CombineShader.FindKernel("ShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE");
_KernalShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON = _CombineShader.FindKernel("ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON");
_KernalShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE = _CombineShader.FindKernel("ShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE");
}
internal override void BuildCommandBuffer(WaterRenderer water, CommandBuffer buffer)
{
buffer.BeginSample(Name);
FlipBuffers();
Shader.SetGlobalFloat(ShaderIDs.s_AttenuationInShallows, _AttenuationInShallows);
// Get temporary buffer to store waves. They will be copied in the combine pass.
buffer.GetTemporaryRT(ShaderIDs.s_WaveBuffer, DataTexture.descriptor);
buffer.SetRenderTarget(ShaderIDs.s_WaveBuffer, 0, CubemapFace.Unknown, -1);
buffer.ClearRenderTarget(false, true, ClearColor);
// LOD dependent data.
// Write to per-octave _WaveBuffers. Not the same as _AnimatedWaves.
// Draw any data with lod preference.
SubmitDraws(buffer, s_Inputs, ShaderIDs.s_WaveBuffer, (int)DisplacementPass.LodDependent, filter: true);
var lastSlice = Slices - 1;
var threadSize = Resolution / k_ThreadGroupSize;
// Combine the LODs - copy results from biggest LOD down to LOD 0
{
var combineShaderKernel = _KernalShapeCombine;
var combineShaderKernel_lastLOD = _KernalShapeCombine_DISABLE_COMBINE;
{
var isFlowOn = _Water._FlowLod.Enabled;
var isDynamicWavesOn = _Water._DynamicWavesLod.Enabled && !_CollisionLayers.HasFlag(CollisionLayers.DynamicWaves);
// Set the shader kernels that we will use.
if (isFlowOn && isDynamicWavesOn)
{
combineShaderKernel = _KernalShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON;
combineShaderKernel_lastLOD = _KernalShapeCombine_FLOW_ON_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE;
}
else if (isFlowOn)
{
combineShaderKernel = _KernalShapeCombine_FLOW_ON;
combineShaderKernel_lastLOD = _KernalShapeCombine_FLOW_ON_DISABLE_COMBINE;
}
else if (isDynamicWavesOn)
{
combineShaderKernel = _KernalShapeCombine_DYNAMIC_WAVE_SIM_ON;
combineShaderKernel_lastLOD = _KernalShapeCombine_DYNAMIC_WAVE_SIM_ON_DISABLE_COMBINE;
}
}
buffer.BeginSample("Combine");
// Combine waves.
for (var slice = lastSlice; slice >= 0; slice--)
{
var kernel = slice < lastSlice && s_Combine
? combineShaderKernel : combineShaderKernel_lastLOD;
var wrapper = new PropertyWrapperCompute(buffer, _CombineShader, kernel);
// The per-octave wave buffers we read from.
wrapper.SetTexture(ShaderIDs.s_WaveBuffer, ShaderIDs.s_WaveBuffer);
if (_Water._DynamicWavesLod.Enabled) _Water._DynamicWavesLod.Bind(wrapper);
// Set the animated waves texture where we read/write to combine the results. Use
// compute suffix to avoid collision as a file already uses the normal name.
wrapper.SetTexture(Crest.ShaderIDs.s_Target, DataTexture);
wrapper.SetInteger(Lod.ShaderIDs.s_LodIndex, slice);
wrapper.Dispatch(threadSize, threadSize, 1);
}
buffer.EndSample("Combine");
}
buffer.ReleaseTemporaryRT(ShaderIDs.s_WaveBuffer);
// LOD independent data.
// Draw any data that did not express a preference for one lod or another.
var drawn = SubmitDraws(buffer, s_Inputs, DataTexture, (int)DisplacementPass.LodIndependent);
// Alpha channel is cleared in combine step, but if any inputs draw in post-combine
// step then alpha may have data.
var clear = WaterResources.Instance.Compute._Clear;
if (drawn && clear != null)
{
buffer.SetComputeTextureParam(clear, 0, Crest.ShaderIDs.s_Target, DataTexture);
buffer.SetComputeVectorParam(clear, Crest.ShaderIDs.s_ClearMask, Color.black);
buffer.SetComputeVectorParam(clear, Crest.ShaderIDs.s_ClearColor, Color.clear);
buffer.DispatchCompute
(
clear,
0,
Resolution / k_ThreadGroupSizeX,
Resolution / k_ThreadGroupSizeY,
Slices
);
}
// Pack height data into alpha channel.
// We do not add height to displacement directly for better precision and layering.
var heightShader = WaterResources.Instance.Compute._PackLevel;
if (_Water._LevelLod.Enabled && heightShader != null)
{
buffer.SetComputeTextureParam(heightShader, 0, Crest.ShaderIDs.s_Target, DataTexture);
buffer.DispatchCompute
(
heightShader,
0,
Resolution / k_ThreadGroupSizeX,
Resolution / k_ThreadGroupSizeY,
Slices
);
}
// Query collisions including only Animated Waves.
// Requires copying the water level.
Provider.UpdateQueries(_Water, CollisionLayer.AfterAnimatedWaves);
// Transfer Dynamic Waves to Animated Waves.
if (_CollisionLayers.HasFlag(CollisionLayers.DynamicWaves) && _Water._DynamicWavesLod.Enabled)
{
buffer.BeginSample("Combine");
// Clearing not required as we overwrite enter texture.
buffer.GetTemporaryRT(ShaderIDs.s_DynamicWavesTarget, DataTexture.descriptor);
var wrapper = new PropertyWrapperCompute(buffer, _CombineShader, 8);
wrapper.SetTexture(ShaderIDs.s_DynamicWavesTarget, ShaderIDs.s_DynamicWavesTarget);
_Water._DynamicWavesLod.Bind(wrapper);
// Compute displacement from Dynamic Waves.
for (var slice = lastSlice; slice >= 0; slice--)
{
wrapper.SetInteger(Lod.ShaderIDs.s_LodIndex, slice);
wrapper.Dispatch(threadSize, threadSize, 1);
}
// Copy Dynamic Waves displacement into Animated Waves.
{
wrapper = new PropertyWrapperCompute(buffer, _CombineShader, 9);
wrapper.SetTexture(ShaderIDs.s_AnimatedWavesTarget, DataTexture);
wrapper.SetTexture(ShaderIDs.s_DynamicWavesTarget, ShaderIDs.s_DynamicWavesTarget);
wrapper.Dispatch(threadSize, threadSize, Slices);
}
buffer.ReleaseTemporaryRT(ShaderIDs.s_DynamicWavesTarget);
buffer.EndSample("Combine");
// Query collisions including Dynamic Waves.
// Does not require copying the water level as they are added with zero alpha.
_Water.CollisionProvider.UpdateQueries(_Water, CollisionLayer.AfterDynamicWaves);
}
if (_CollisionLayers.HasFlag(CollisionLayers.Displacement))
{
// LOD independent data.
// Draw any data that did not express a preference for one lod or another.
drawn = SubmitDraws(buffer, s_Inputs, DataTexture, (int)DisplacementPass.LodIndependentLast);
}
if (_CollisionLayers == CollisionLayers.Nothing || _CollisionLayers.HasFlag(CollisionLayers.Displacement))
{
Queryable?.UpdateQueries(_Water);
}
if (BufferCount > 1)
{
// Update current and previous. Latter for MVs and/or VFX.
Shader.SetGlobalTexture(_TextureSourceShaderID, _Targets.Previous(1));
Shader.SetGlobalTexture(_TextureShaderID, DataTexture);
}
buffer.EndSample(Name);
}
/// <summary>
/// Provides water shape to CPU.
/// </summary>
private protected override ICollisionProvider CreateProvider(bool enable)
{
ICollisionProvider result = null;
Queryable?.CleanUp();
if (!enable)
{
return ICollisionProvider.None;
}
switch (_CollisionSource)
{
case CollisionSource.None:
result = ICollisionProvider.None;
break;
case CollisionSource.GPU:
if (_Valid && !_Water.IsRunningWithoutGraphics)
{
result = new CollisionQueryWithPasses(_Water);
}
if (_Water.IsRunningWithoutGraphics)
{
Debug.LogError($"Crest: GPU queries not supported in headless/batch mode. To resolve, assign an Animated Wave Settings asset to the {nameof(WaterRenderer)} component and set the Collision Source to be a CPU option.");
}
break;
case CollisionSource.CPU:
if (_BakedWaveData != null)
{
result = _BakedWaveData.CreateCollisionProvider();
}
break;
}
if (result == null)
{
// This should not be hit, but can be if compute shaders aren't loaded correctly.
// They will print out appropriate errors. Don't just return null and have null reference
// exceptions spamming the logs.
return ICollisionProvider.None;
}
return result;
}
//
// DrawFilter
//
internal readonly struct WavelengthFilter
{
public readonly float _Minimum;
public readonly float _Maximum;
public readonly float _TransitionThreshold;
public readonly float _ViewerAltitudeLevelAlpha;
public readonly int _Slice;
public readonly int _Slices;
public WavelengthFilter(WaterRenderer water, int slice)
{
_Slice = slice;
_Slices = water.LodLevels;
_Maximum = water.MaximumWavelength(slice);
_Minimum = _Maximum * 0.5f;
_TransitionThreshold = water.MaximumWavelength(_Slices - 1) * 0.5f;
_ViewerAltitudeLevelAlpha = water.ViewerAltitudeLevelAlpha;
}
}
internal static float FilterByWavelength(WavelengthFilter filter, float wavelength)
{
// No wavelength preference - don't draw per-lod
if (wavelength == 0f)
{
return 0f;
}
// Too small for this lod
if (wavelength < filter._Minimum)
{
return 0f;
}
// If approaching end of lod chain, start smoothly transitioning any large wavelengths across last two lods
if (wavelength >= filter._TransitionThreshold)
{
if (filter._Slice == filter._Slices - 2)
{
return 1f - filter._ViewerAltitudeLevelAlpha;
}
if (filter._Slice == filter._Slices - 1)
{
return filter._ViewerAltitudeLevelAlpha;
}
}
else if (wavelength < filter._Maximum)
{
// Fits in this lod
return 1f;
}
return 0f;
}
internal static float FilterByWavelength(WaterRenderer water, int slice, float wavelength)
{
return FilterByWavelength(new(water, slice), wavelength);
}
//
// Inputs
//
internal static readonly Utility.SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override Utility.SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
#if UNITY_EDITOR
[@OnChange]
private protected override void OnChange(string propertyPath, object previousValue)
{
base.OnChange(propertyPath, previousValue);
switch (propertyPath)
{
case nameof(_CollisionLayers):
case nameof(_CollisionSource):
if (_Water == null || !_Water.isActiveAndEnabled || !Enabled) return;
Queryable?.CleanUp();
InitializeProvider(true);
break;
}
}
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 71b85abdc5e234fe8a685d3be0b95443
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,31 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
readonly struct Cascade
{
public readonly Vector2 _SnappedPosition;
public readonly float _Texel;
public readonly int _Resolution;
public readonly Vector4 Packed => new(_SnappedPosition.x, _SnappedPosition.y, _Texel, 0f);
public Cascade(Vector2 snapped, float texel, int resolution)
{
_SnappedPosition = snapped;
_Texel = texel;
_Resolution = resolution;
}
public readonly Rect TexelRect
{
get
{
var w = _Texel * _Resolution;
return new(_SnappedPosition.x - w / 2f, _SnappedPosition.y - w / 2f, w, w);
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3a52c8c04f6c749d7a2bc6e5a4fbe9ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,120 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// The default state for clipping.
/// </summary>
public enum DefaultClippingState
{
/// <summary>
/// By default, nothing is clipped. Use clip inputs to remove water.
/// </summary>
NothingClipped,
/// <summary>
/// By default, everything is clipped. Use clip inputs to add water.
/// </summary>
EverythingClipped,
}
/// <summary>
/// Drives water surface clipping (carving holes).
/// </summary>
/// <remarks>
/// 0-1 values, surface clipped when > 0.5.
/// </remarks>
[FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)]
public sealed partial class ClipLod : Lod
{
[Tooltip("The default clipping behaviour.\n\nWhether to clip nothing by default (and clip inputs remove patches of surface), or to clip everything by default (and clip inputs add patches of surface).")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
internal DefaultClippingState _DefaultClippingState = DefaultClippingState.NothingClipped;
static new class ShaderIDs
{
public static readonly int s_ClipByDefault = Shader.PropertyToID("g_Crest_ClipByDefault");
}
internal static readonly Color s_GizmoColor = new(0f, 1f, 1f, 0.5f);
internal override string ID => "Clip";
internal override string Name => "Clip Surface";
internal override Color GizmoColor => s_GizmoColor;
private protected override Color ClearColor => _DefaultClippingState == DefaultClippingState.EverythingClipped ? Color.white : Color.black;
private protected override bool NeedToReadWriteTextureData => true;
private protected override bool RequiresClearBorder => true;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
// The clip values only really need 8bits (unless using signed distance).
LodTextureFormatMode.Performance => GraphicsFormat.R8_UNorm,
LodTextureFormatMode.Precision => GraphicsFormat.R16_UNorm,
LodTextureFormatMode.Manual => _TextureFormat,
_ => throw new System.NotImplementedException(),
};
internal ClipLod()
{
_TextureFormat = GraphicsFormat.R8_UNorm;
}
internal override void SetGlobals(bool enable)
{
base.SetGlobals(enable);
Shader.SetGlobalFloat(ShaderIDs.s_ClipByDefault, enable && Enabled ? (float)_DefaultClippingState : (float)DefaultClippingState.NothingClipped);
}
internal override void Disable()
{
base.Disable();
Shader.SetGlobalFloat(ShaderIDs.s_ClipByDefault, (float)DefaultClippingState.NothingClipped);
}
internal override void BuildCommandBuffer(WaterRenderer water, CommandBuffer buffer)
{
base.BuildCommandBuffer(water, buffer);
Shader.SetGlobalFloat(ShaderIDs.s_ClipByDefault, (float)_DefaultClippingState);
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
void SetDefaultClippingState(DefaultClippingState previous, DefaultClippingState current)
{
if (previous == current) return;
if (_Water == null || !_Water.isActiveAndEnabled || !Enabled) return;
// Change default clipping state.
_TargetsToClear = Mathf.Max(1, _TargetsToClear);
}
#if UNITY_EDITOR
[@OnChange]
private protected override void OnChange(string path, object previous)
{
base.OnChange(path, previous);
switch (path)
{
case nameof(_DefaultClippingState):
SetDefaultClippingState((DefaultClippingState)previous, _DefaultClippingState);
break;
}
}
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: ed87ea342278349c4885adef619f19cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,169 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
namespace WaveHarmonic.Crest
{
/// <summary>
/// The source of depth color.
/// </summary>
public enum ShorelineVolumeColorSource
{
/// <summary>
/// No depth color.
/// </summary>
None,
/// <summary>
/// Depth color based on water depth.
/// </summary>
Depth,
/// <summary>
/// Depth color based on shoreline distance.
/// </summary>
Distance,
}
/// <summary>
/// Contains shared functionality for <see cref="AbsorptionLod"/> and <see cref="ScatteringLod"/>.
/// </summary>
[FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)]
public abstract partial class ColorLod : Lod
{
[@Space(10f)]
[Tooltip("Source of the shoreline color.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal ShorelineVolumeColorSource _ShorelineColorSource;
[Tooltip("Color of the shoreline color.")]
[@Predicated(nameof(_ShorelineColorSource), inverted: false, nameof(ShorelineVolumeColorSource.None), hide: true)]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
private protected Color _ShorelineColor;
[Tooltip("The maximum distance of the shoreline color.\n\nIf using Depth, then it is maximum depth.")]
[@Predicated(nameof(_ShorelineColorSource), inverted: false, nameof(ShorelineVolumeColorSource.None), hide: true)]
[@GenerateAPI]
[@DecoratedField, SerializeField]
float _ShorelineColorMaximumDistance = 10f;
[Tooltip("Shoreline color falloff value.")]
[@Predicated(nameof(_ShorelineColorSource), inverted: false, nameof(ShorelineVolumeColorSource.None), hide: true)]
[@GenerateAPI]
[@DecoratedField, SerializeField]
float _ShorelineColorFalloff = 2f;
static new class ShaderIDs
{
public static readonly int s_ShorelineColor = Shader.PropertyToID("_Crest_ShorelineColor");
public static readonly int s_ShorelineColorMaximumDistance = Shader.PropertyToID("_Crest_ShorelineColorMaximumDistance");
public static readonly int s_ShorelineColorFalloff = Shader.PropertyToID("_Crest_ShorelineColorFalloff");
}
private protected abstract int GlobalShaderID { get; }
private protected abstract void SetShorelineColor(Color previous, Color current);
private protected Vector4 _ShorelineColorValue;
ShorelineColorInput _ShorelineColorInput;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
LodTextureFormatMode.Manual => _TextureFormat,
LodTextureFormatMode.Performance => GraphicsFormat.R8G8B8_UNorm,
LodTextureFormatMode.Precision => GraphicsFormat.R16G16B16_UNorm,
_ => throw new System.NotImplementedException($"Crest: {_TextureFormatMode} not implemented for {Name}."),
};
internal ColorLod()
{
// Interpolation banding with lower precision.
_TextureFormat = GraphicsFormat.R16G16B16_UNorm;
_TextureFormatMode = LodTextureFormatMode.Precision;
}
internal override void Enable()
{
base.Enable();
if (Enabled)
{
_ShorelineColorInput ??= new(this);
// Convert color to value.
SetShorelineColor(Color.clear, _ShorelineColor);
Inputs.Add(_ShorelineColorInput.Queue, _ShorelineColorInput);
}
}
internal override void SetGlobals(bool enable)
{
base.SetGlobals(enable);
Helpers.SetGlobalBoolean(GlobalShaderID, enable && Enabled);
}
internal override void Disable()
{
base.Disable();
Inputs.Remove(_ShorelineColorInput);
}
sealed class ShorelineColorInput : ILodInput
{
public bool Enabled => _VolumeColorLod._ShorelineColorSource != ShorelineVolumeColorSource.None &&
_VolumeColorLod._Water._DepthLod.Enabled;
public bool IsCompute => true;
public int Queue => int.MinValue;
public int Pass => -1;
public Rect Rect => Rect.zero;
public MonoBehaviour Component => null;
public float Filter(WaterRenderer water, int slice) => 1f;
readonly ColorLod _VolumeColorLod;
public ShorelineColorInput(ColorLod lod)
{
_VolumeColorLod = lod;
}
public void Draw(Lod lod, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1, int slices = -1)
{
var resources = WaterResources.Instance;
var wrapper = new PropertyWrapperCompute(buffer, resources.Compute._ShorelineColor, 0);
wrapper.SetVector(ShaderIDs.s_ShorelineColor, _VolumeColorLod._ShorelineColorValue);
wrapper.SetFloat(ShaderIDs.s_ShorelineColorMaximumDistance, _VolumeColorLod._ShorelineColorMaximumDistance);
wrapper.SetFloat(ShaderIDs.s_ShorelineColorFalloff, _VolumeColorLod._ShorelineColorFalloff);
wrapper.SetKeyword(WaterResources.Instance.Keywords.ShorelineColorScattering, lod.GetType() == typeof(ScatteringLod));
wrapper.SetKeyword(WaterResources.Instance.Keywords.ShorelineColorSourceDistance, _VolumeColorLod._ShorelineColorSource == ShorelineVolumeColorSource.Distance);
wrapper.SetTexture(Crest.ShaderIDs.s_Target, target);
var threads = lod.Resolution / k_ThreadGroupSize;
wrapper.Dispatch(threads, threads, slices);
}
}
}
#if UNITY_EDITOR
abstract partial class ColorLod
{
private protected override void OnChange(string propertyPath, object previousValue)
{
base.OnChange(propertyPath, previousValue);
switch (propertyPath)
{
case nameof(_ShorelineColor):
SetShorelineColor((Color)previousValue, _ShorelineColor);
break;
}
}
}
#endif
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e1bc55489896941859aa8af34f8c1083
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,107 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Data that gives depth of the water (height of sea level above water floor).
/// </summary>
[FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)]
public sealed partial class DepthLod : Lod<IDepthProvider>
{
[Tooltip("Support signed distance field data generated from the depth probes.\n\nRequires a two component texture format.")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
internal bool _EnableSignedDistanceFields = true;
// NOTE: Must match CREST_WATER_DEPTH_BASELINE in Constants.hlsl.
internal const float k_DepthBaseline = Mathf.Infinity;
internal static readonly Color s_GizmoColor = new(1f, 0f, 0f, 0.5f);
// We want the clear color to be the mininimum terrain height (-1000m).
// Mathf.Infinity can cause problems for distance.
static readonly Color s_NullColor = new(-k_DepthBaseline, k_DepthBaseline, 0, 0);
internal override string ID => "Depth";
internal override string Name => "Water Depth";
internal override Color GizmoColor => s_GizmoColor;
private protected override Color ClearColor => s_NullColor;
private protected override bool NeedToReadWriteTextureData => true;
internal override bool RunsInHeadless => true;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
LodTextureFormatMode.Automatic or
LodTextureFormatMode.Performance => _EnableSignedDistanceFields ? GraphicsFormat.R16G16_SFloat : GraphicsFormat.R16_SFloat,
LodTextureFormatMode.Precision => _EnableSignedDistanceFields ? GraphicsFormat.R32G32_SFloat : GraphicsFormat.R32_SFloat,
LodTextureFormatMode.Manual => _TextureFormat,
_ => throw new System.NotImplementedException(),
};
Texture2DArray _NullTexture;
private protected override Texture2DArray NullTexture
{
get
{
if (_NullTexture == null)
{
var texture = TextureArrayHelpers.CreateTexture2D(s_NullColor, UnityEngine.TextureFormat.RFloat);
texture.name = $"_Crest_{ID}LodTemporaryDefaultTexture";
_NullTexture = TextureArrayHelpers.CreateTexture2DArray(texture, k_MaximumSlices);
_NullTexture.name = $"_Crest_{ID}LodDefaultTexture";
Helpers.Destroy(texture);
}
return _NullTexture;
}
}
internal DepthLod()
{
_Enabled = true;
_TextureFormat = GraphicsFormat.R16G16_SFloat;
}
private protected override IDepthProvider CreateProvider(bool enable)
{
Queryable?.CleanUp();
// Depth is GPU only, and can only be queried using the compute path.
return enable && Enabled ? new DepthQuery(_Water) : IDepthProvider.None;
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
void SetEnableSignedDistanceFields(bool previous, bool current)
{
if (previous == current) return;
if (_Water == null || !_Water.isActiveAndEnabled || !Enabled) return;
ReAllocate();
}
#if UNITY_EDITOR
[@OnChange]
private protected override void OnChange(string propertyPath, object previousValue)
{
base.OnChange(propertyPath, previousValue);
switch (propertyPath)
{
case nameof(_EnableSignedDistanceFields):
SetEnableSignedDistanceFields((bool)previousValue, _EnableSignedDistanceFields);
break;
}
}
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 679dfc1207b124b3fa00496f7b93a5cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,116 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// A dynamic shape simulation that moves around with a displacement LOD.
/// </summary>
public sealed partial class DynamicWavesLod : PersistentLod
{
[Tooltip("How much waves are dampened in shallow water.")]
[@Range(0f, 1f)]
[@GenerateAPI]
[SerializeField]
float _AttenuationInShallows = 1f;
[Tooltip("Settings for fine tuning this simulation.")]
[@Embedded]
[@GenerateAPI(Getter.Custom)]
[SerializeField]
DynamicWavesLodSettings _Settings;
const string k_DynamicWavesKeyword = "CREST_DYNAMIC_WAVE_SIM_ON_INTERNAL";
static new class ShaderIDs
{
public static readonly int s_HorizontalDisplace = Shader.PropertyToID("_Crest_HorizontalDisplace");
public static readonly int s_DisplaceClamp = Shader.PropertyToID("_Crest_DisplaceClamp");
public static readonly int s_Damping = Shader.PropertyToID("_Crest_Damping");
public static readonly int s_Gravity = Shader.PropertyToID("_Crest_Gravity");
public static readonly int s_CourantNumber = Shader.PropertyToID("_Crest_CourantNumber");
}
internal static readonly Color s_GizmoColor = new(0f, 1f, 0f, 0.5f);
internal override string ID => "DynamicWaves";
internal override string Name => "Dynamic Waves";
internal override Color GizmoColor => s_GizmoColor;
private protected override Color ClearColor => Color.black;
internal override bool RunsInHeadless => true;
private protected override ComputeShader SimulationShader => WaterResources.Instance.Compute._UpdateDynamicWaves;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
// Try and match Animated Waves format as we copy this simulation into it.
LodTextureFormatMode.Automatic => Water == null ? GraphicsFormat.None : Water.AnimatedWavesLod.TextureFormatMode switch
{
LodTextureFormatMode.Precision => GraphicsFormat.R32G32_SFloat,
_ => GraphicsFormat.R16G16_SFloat,
},
LodTextureFormatMode.Performance => GraphicsFormat.R16G16_SFloat,
LodTextureFormatMode.Precision => GraphicsFormat.R32G32_SFloat,
LodTextureFormatMode.Manual => _TextureFormat,
_ => throw new System.NotImplementedException(),
};
internal float TimeLeftToSimulate => _TimeToSimulate;
internal DynamicWavesLod()
{
_OverrideResolution = false;
_Resolution = 512;
_TextureFormatMode = LodTextureFormatMode.Automatic;
_TextureFormat = GraphicsFormat.R16G16_SFloat;
}
internal override void Enable()
{
base.Enable();
Shader.EnableKeyword(k_DynamicWavesKeyword);
}
internal override void Disable()
{
base.Disable();
Shader.DisableKeyword(k_DynamicWavesKeyword);
}
internal override void Bind<T>(T target)
{
base.Bind(target);
target.SetFloat(ShaderIDs.s_HorizontalDisplace, Settings._HorizontalDisplace);
target.SetFloat(ShaderIDs.s_DisplaceClamp, Settings._DisplaceClamp);
}
private protected override void SetAdditionalSimulationParameters<T>(T simMaterial)
{
base.SetAdditionalSimulationParameters(simMaterial);
simMaterial.SetFloat(ShaderIDs.s_Damping, Settings._Damping);
simMaterial.SetFloat(ShaderIDs.s_Gravity, _Water.Gravity * Settings._GravityMultiplier);
simMaterial.SetFloat(ShaderIDs.s_CourantNumber, Settings._CourantNumber);
simMaterial.SetFloat(AnimatedWavesLod.ShaderIDs.s_AttenuationInShallows, _AttenuationInShallows);
}
private protected override void GetSubstepData(float timeToSimulate, out int substeps, out float delta)
{
substeps = Mathf.FloorToInt(timeToSimulate * _SimulationFrequency);
delta = substeps > 0 ? (1f / _SimulationFrequency) : 0f;
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 9fb0d3abd1aa34af8942b9bab09a8575
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,70 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Simulates horizontal motion of water.
/// </summary>
[FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)]
public sealed partial class FlowLod : Lod<IFlowProvider>
{
const string k_FlowKeyword = "CREST_FLOW_ON_INTERNAL";
internal static readonly Color s_GizmoColor = new(0f, 0f, 1f, 0.5f);
internal override string ID => "Flow";
internal override Color GizmoColor => s_GizmoColor;
private protected override Color ClearColor => Color.black;
private protected override bool NeedToReadWriteTextureData => true;
internal override bool RunsInHeadless => true;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
LodTextureFormatMode.Performance => GraphicsFormat.R16G16_SFloat,
LodTextureFormatMode.Precision => GraphicsFormat.R32G32_SFloat,
LodTextureFormatMode.Manual => _TextureFormat,
_ => throw new System.NotImplementedException(),
};
internal FlowLod()
{
_Resolution = 128;
_TextureFormat = GraphicsFormat.R16G16_SFloat;
}
internal override void Enable()
{
base.Enable();
Shader.EnableKeyword(k_FlowKeyword);
}
internal override void Disable()
{
base.Disable();
Shader.DisableKeyword(k_FlowKeyword);
}
private protected override IFlowProvider CreateProvider(bool enable)
{
Queryable?.CleanUp();
// Flow is GPU only, and can only be queried using the compute path.
return enable && Enabled ? new FlowQuery(_Water) : IFlowProvider.None;
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 37086036dea5b4927a5cdb3af2d5d869
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,95 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// A persistent foam simulation that moves around with a displacement LOD. The input is fully combined water surface shape.
/// </summary>
[FilterEnum(nameof(_TextureFormatMode), Filtered.Mode.Exclude, (int)LodTextureFormatMode.Automatic)]
public sealed partial class FoamLod : PersistentLod
{
[Tooltip("Prewarms the simulation on load and teleports.\n\nResults are only an approximation.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _Prewarm = true;
[Tooltip("Settings for fine tuning this simulation.")]
[@Embedded]
[@GenerateAPI(Getter.Custom)]
[SerializeField]
FoamLodSettings _Settings;
static new class ShaderIDs
{
public static readonly int s_MinimumWavesSlice = Shader.PropertyToID("_Crest_MinimumWavesSlice");
public static readonly int s_FoamMaximum = Shader.PropertyToID("_Crest_FoamMaximum");
public static readonly int s_FoamFadeRate = Shader.PropertyToID("_Crest_FoamFadeRate");
public static readonly int s_WaveFoamStrength = Shader.PropertyToID("_Crest_WaveFoamStrength");
public static readonly int s_WaveFoamCoverage = Shader.PropertyToID("_Crest_WaveFoamCoverage");
public static readonly int s_ShorelineFoamMaxDepth = Shader.PropertyToID("_Crest_ShorelineFoamMaxDepth");
public static readonly int s_ShorelineFoamStrength = Shader.PropertyToID("_Crest_ShorelineFoamStrength");
public static readonly int s_NeedsPrewarming = Shader.PropertyToID("_Crest_NeedsPrewarming");
public static readonly int s_FoamNegativeDepthPriming = Shader.PropertyToID("_Crest_FoamNegativeDepthPriming");
}
internal static readonly Color s_GizmoColor = new(1f, 1f, 1f, 0.5f);
internal override string ID => "Foam";
internal override Color GizmoColor => s_GizmoColor;
private protected override Color ClearColor => Color.black;
private protected override ComputeShader SimulationShader => WaterResources.Instance.Compute._UpdateFoam;
private protected override GraphicsFormat RequestedTextureFormat => _TextureFormatMode switch
{
LodTextureFormatMode.Performance => GraphicsFormat.R16_SFloat,
LodTextureFormatMode.Precision => GraphicsFormat.R32_SFloat,
LodTextureFormatMode.Manual => _TextureFormat,
_ => throw new System.NotImplementedException(),
};
private protected override void SetAdditionalSimulationParameters<T>(T properties)
{
base.SetAdditionalSimulationParameters(properties);
// Prewarm simulation for first frame or teleporting. It will not be the same results as running the
// simulation for multiple frames - but good enough.
properties.SetBoolean(ShaderIDs.s_NeedsPrewarming, _Prewarm && _NeedsPrewarmingThisStep);
properties.SetFloat(ShaderIDs.s_FoamFadeRate, Settings._FoamFadeRate);
properties.SetFloat(ShaderIDs.s_WaveFoamStrength, Settings._WaveFoamStrength);
properties.SetFloat(ShaderIDs.s_WaveFoamCoverage, Settings._WaveFoamCoverage);
properties.SetFloat(ShaderIDs.s_ShorelineFoamMaxDepth, Settings._ShorelineFoamMaximumDepth);
properties.SetFloat(ShaderIDs.s_ShorelineFoamStrength, Settings._ShorelineFoamStrength);
properties.SetFloat(ShaderIDs.s_FoamMaximum, Settings.Maximum);
properties.SetFloat(ShaderIDs.s_FoamNegativeDepthPriming, -Settings._ShorelineFoamPriming);
properties.SetInteger(ShaderIDs.s_MinimumWavesSlice, Settings.FilterWaves);
}
private protected override void GetSubstepData(float timeToSimulate, out int substeps, out float delta)
{
substeps = Mathf.FloorToInt(timeToSimulate * _SimulationFrequency);
delta = substeps > 0 ? (1f / _SimulationFrequency) : 0f;
}
internal FoamLod()
{
_Enabled = true;
_TextureFormat = GraphicsFormat.R16_SFloat;
_SimulationFrequency = 30;
}
internal static readonly SortedList<int, ILodInput> s_Inputs = new(Helpers.DuplicateComparison);
private protected override SortedList<int, ILodInput> Inputs => s_Inputs;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void OnLoad()
{
s_Inputs.Clear();
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 42f3809132d8b485a822f0bb271f51c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 1ea9618107d2946a98206ac4c7772029
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,66 +0,0 @@
// <auto-generated/>
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
partial class DynamicWavesLod
{
DynamicWavesLodSettings _DefaultSettings;
DynamicWavesLodSettings GetSettings()
{
if (_Settings != null)
{
return _Settings;
}
if (_DefaultSettings == null)
{
_DefaultSettings = ScriptableObject.CreateInstance<DynamicWavesLodSettings>();
_DefaultSettings.name = $"Default {Name} (instance)";
_DefaultSettings.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
}
return _DefaultSettings;
}
internal override void Destroy()
{
base.Destroy();
Helpers.Destroy(_DefaultSettings);
}
}
partial class FoamLod
{
FoamLodSettings _DefaultSettings;
FoamLodSettings GetSettings()
{
if (_Settings != null)
{
return _Settings;
}
if (_DefaultSettings == null)
{
_DefaultSettings = ScriptableObject.CreateInstance<FoamLodSettings>();
_DefaultSettings.name = $"Default {Name} (instance)";
_DefaultSettings.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
}
return _DefaultSettings;
}
internal override void Destroy()
{
base.Destroy();
Helpers.Destroy(_DefaultSettings);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 4e88db203d9474c568c462518871bb5a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 51ed544a28b134d58a41f55650e368b7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,37 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="AbsorptionLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the scattering color.
/// </remarks>
[@HelpURL("Manual/WaterAppearance.html#volume-color-inputs")]
public sealed partial class AbsorptionLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
#if d_CrestPaint
internal override LodInputMode DefaultMode => LodInputMode.Paint;
#else
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
#endif
internal override void InferBlend()
{
base.InferBlend();
_Blend = LodInputBlend.Alpha;
}
// Looks fine moving around.
private protected override bool FollowHorizontalMotion => true;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 247a7260095bc49429a7f7cb2a4851d5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,24 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="AlbedoLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the surface color.
/// </remarks>
[@HelpURL("Manual/WaterAppearance.html#albedo-inputs")]
public sealed partial class AlbedoLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 5c972e8f11f2447768dc0314b7bc34a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,139 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="AnimatedWavesLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to render into the displacment textures to
/// affect the water shape.
/// </remarks>
[@HelpURL("Manual/Waves.html#animated-waves-inputs")]
public sealed partial class AnimatedWavesLodInput : LodInput
{
[@Space(10)]
[Tooltip("When to render the input into the displacement data.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
DisplacementPass _DisplacementPass = DisplacementPass.LodIndependent;
[Tooltip("Whether to filter this input by wavelength.\n\nIf disabled, it will render to all LODs.")]
[@Predicated(nameof(_DisplacementPass), inverted: true, nameof(DisplacementPass.LodDependent))]
[@GenerateAPI]
[DecoratedField, SerializeField]
bool _FilterByWavelength;
[Tooltip("Which octave to render into.\n\nFor example, set this to 2 to render into the 2m-4m octave. These refer to the same octaves as the wave spectrum editor.")]
[@Predicated(nameof(_DisplacementPass), inverted: true, nameof(DisplacementPass.LodDependent))]
[@Predicated(nameof(_FilterByWavelength))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
float _OctaveWavelength = 512f;
[Header("Culling")]
[Tooltip("Inform the system how much this input will displace the water surface vertically.\n\nThis is used to set bounding box heights for the water chunks.")]
[@GenerateAPI]
[SerializeField]
float _MaximumDisplacementVertical = 0f;
[Tooltip("Inform the system how much this input will displace the water surface horizontally.\n\nThis is used to set bounding box widths for the water chunks.")]
[@GenerateAPI]
[SerializeField]
float _MaximumDisplacementHorizontal = 0f;
[Tooltip("Use the bounding box of an attached renderer component to determine the maximum vertical displacement.")]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Renderer))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _ReportRendererBounds = false;
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
internal override int Pass => (int)_DisplacementPass;
internal AnimatedWavesLodInput() : base()
{
_FollowHorizontalWaveMotion = true;
}
internal override float Filter(WaterRenderer water, int slice)
{
return AnimatedWavesLod.FilterByWavelength(water, slice, _FilterByWavelength ? _OctaveWavelength : 0f);
}
private protected override void OnUpdate(WaterRenderer water)
{
base.OnUpdate(water);
if (!Enabled)
{
return;
}
var maxDispVert = _MaximumDisplacementVertical;
// let water system know how far from the sea level this shape may displace the surface
if (_ReportRendererBounds)
{
var range = Data.HeightRange;
var minY = range.x;
var maxY = range.y;
var seaLevel = water.SeaLevel;
maxDispVert = Mathf.Max(maxDispVert, Mathf.Abs(seaLevel - minY), Mathf.Abs(seaLevel - maxY));
}
if (_MaximumDisplacementHorizontal > 0f || maxDispVert > 0f)
{
water.ReportMaximumDisplacement(_MaximumDisplacementHorizontal, maxDispVert, 0f);
}
}
}
partial class AnimatedWavesLodInput : ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 1;
#pragma warning restore 414
[System.Obsolete("Please use DisplacementPass instead.")]
[Tooltip("When to render the input into the displacement data.\n\nIf enabled, it renders into all LODs of the simulation after the combine step rather than before with filtering. Furthermore, it will also affect dynamic waves.")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
[HideInInspector]
bool _RenderPostCombine = true;
void SetRenderPostCombine(bool previous, bool current, bool force = false)
{
if (previous == current && !force) return;
_DisplacementPass = current ? DisplacementPass.LodIndependent : DisplacementPass.LodDependent;
}
#pragma warning disable CS0618 // Type or member is obsolete
/// <inheritdoc/>
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (_Version < 1)
{
SetRenderPostCombine(_RenderPostCombine, _RenderPostCombine, force: true);
_Version = 1;
}
}
#pragma warning restore CS0618 // Type or member is obsolete
/// <inheritdoc/>
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 3d64d1f50f3b548bcbe279507f0e78da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,156 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
using WaveHarmonic.Crest.Internal;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="ClipLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to use to clip the surface of the water.
/// </remarks>
[@HelpURL("Manual/Clipping.html#clip-inputs")]
public sealed partial class ClipLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
[@Heading("Primitive")]
[Tooltip("The primitive to render (signed distance) into the simulation.")]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Primitive), hide: true)]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal LodInputPrimitive _Primitive = LodInputPrimitive.Cube;
// Only Mode.Primitive SDF supports inverted.
[Tooltip("Removes clip surface data instead of adding it.")]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Primitive), hide: true)]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _Inverted;
[@Heading("Culling")]
[Tooltip("Prevents inputs from cancelling each other out when aligned vertically.\n\nIt is imperfect so custom logic might be needed for your use case.")]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Paint), hide: true)]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Renderer))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _WaterHeightDistanceCulling = false;
internal override LodInputMode DefaultMode => LodInputMode.Primitive;
// The clip surface samples at the displaced position in the water shader, so the displacement correction is not needed.
private protected override bool FollowHorizontalMotion => true;
readonly SampleCollisionHelper _SampleHeightHelper = new();
ComputeShader PrimitiveShader => WaterResources.Instance.Compute._ClipPrimitive;
static LocalKeyword KeywordInverted => WaterResources.Instance.Keywords.ClipPrimitiveInverted;
static LocalKeyword KeywordSphere => WaterResources.Instance.Keywords.ClipPrimitiveSphere;
static LocalKeyword KeywordCube => WaterResources.Instance.Keywords.ClipPrimitiveCube;
static LocalKeyword KeywordRectangle => WaterResources.Instance.Keywords.ClipPrimitiveRectangle;
bool _Enabled = true;
Rect _Rect;
internal override void InferBlend()
{
base.InferBlend();
_Blend = LodInputBlend.Maximum;
}
internal override bool Enabled => _Enabled && Mode switch
{
LodInputMode.Primitive => enabled && PrimitiveShader != null,
_ => base.Enabled,
};
internal override Rect Rect
{
get
{
if (Mode == LodInputMode.Primitive)
{
if (_RecalculateBounds)
{
// This mode has full transform support so need to get rect from bounds.
_Rect = transform.Bounds().RectXZ();
_RecalculateBounds = false;
}
return _Rect;
}
return base.Rect;
}
}
internal override void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slices = -1)
{
if (Mode == LodInputMode.Primitive)
{
var wrapper = new PropertyWrapperCompute(buffer, PrimitiveShader, 0);
wrapper.SetMatrix(Crest.ShaderIDs.s_Matrix, transform.worldToLocalMatrix);
// For culling.
wrapper.SetVector(Crest.ShaderIDs.s_Position, transform.position);
wrapper.SetFloat(Crest.ShaderIDs.s_Diameter, transform.lossyScale.Maximum());
wrapper.SetKeyword(KeywordInverted, _Inverted);
wrapper.SetKeyword(KeywordSphere, _Primitive == LodInputPrimitive.Sphere);
wrapper.SetKeyword(KeywordCube, _Primitive == LodInputPrimitive.Cube);
wrapper.SetKeyword(KeywordRectangle, _Primitive == LodInputPrimitive.Quad);
wrapper.SetTexture(Crest.ShaderIDs.s_Target, target);
var threads = simulation.Resolution / Lod.k_ThreadGroupSize;
wrapper.Dispatch(threads, threads, slices);
}
else
{
base.Draw(simulation, buffer, target, pass, weight, slices);
}
}
private protected override void OnUpdate(WaterRenderer water)
{
base.OnUpdate(water);
if (Mode != LodInputMode.Renderer)
{
_Enabled = true;
return;
}
if (!base.Enabled)
{
return;
}
if (Data is not RendererLodInputData data || data._Renderer == null)
{
return;
}
// Prevents possible conflicts since overlapping doesn't work for every case for convex hull.
if (_WaterHeightDistanceCulling)
{
var position = transform.position;
if (_SampleHeightHelper.SampleHeight(position, out var waterHeight))
{
position.y = waterHeight;
_Enabled = Mathf.Abs(data._Renderer.bounds.ClosestPoint(position).y - waterHeight) < 1;
}
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 26623fd0e291a478a9f8b68a3df7e8a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,72 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="DepthLod"/>.
/// </summary>
/// <remarks>
/// <para>
/// Attach this to objects that you want to use to add water depth.
/// </para>
/// <para>
/// Renders depth every frame and should only be used for dynamic objects. For
/// static objects, use a <see cref="DepthProbe"/>
/// </para>
/// </remarks>
[@HelpURL("Manual/ShallowsAndShorelines.html#sea-floor-depth")]
public sealed partial class DepthLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
[@Space(10)]
[@Label("Relative Height")]
[Tooltip("Whether the data is relative to the input height.\n\nUseful for procedural placement.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal bool _Relative;
[@Label("Copy Signed Distance Field")]
[Tooltip("Whether to copy the signed distance field.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal bool _CopySignedDistanceField;
internal static new class ShaderIDs
{
public static readonly int s_HeightOffset = Shader.PropertyToID("_Crest_HeightOffset");
public static readonly int s_SDF = Shader.PropertyToID("_Crest_SDF");
}
internal override LodInputMode DefaultMode => LodInputMode.Geometry;
internal override void InferBlend()
{
base.InferBlend();
_Blend = LodInputBlend.Maximum;
}
internal override void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1)
{
var wrapper = new PropertyWrapperBuffer(buffer);
wrapper.SetFloat(ShaderIDs.s_HeightOffset, _Relative ? transform.position.y : 0f);
if (IsCompute)
{
wrapper.SetInteger(ShaderIDs.s_SDF, _CopySignedDistanceField ? 1 : 0);
buffer.SetKeyword(WaterResources.Instance.Compute._DepthTexture, WaterResources.Instance.Keywords.DepthTextureSDF, simulation._Water._DepthLod._EnableSignedDistanceFields);
}
base.Draw(simulation, buffer, target, pass, weight, slice);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: d13f0b872e9454b5daa77afa95b12943
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 70deb49b538e247b9ab1bf7773d16809
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 300
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,25 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="DynamicWavesLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the simulation, such as
/// ripples etc.
/// </remarks>
[@HelpURL("Manual/Waves.html#dynamic-waves-inputs")]
public sealed partial class DynamicWavesLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 82638e366ec3c4f5587d1ff63e01d8b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,34 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="FlowLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the horizontal flow of the
/// water volume.
/// </remarks>
[@HelpURL("Manual/TidesAndCurrents.html#flow-inputs")]
[FilterEnum(nameof(_Blend), Filtered.Mode.Include, (int)LodInputBlend.Additive, (int)LodInputBlend.Alpha)]
public sealed partial class FlowLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
// Countering will incur thrashing. Previously we allowed the option so the
// serialized value could be "false".
private protected override bool FollowHorizontalMotion => true;
#if d_CrestPaint
internal override LodInputMode DefaultMode => LodInputMode.Paint;
#else
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a0cdc7659b2c244dbbb625ccd8ae65ae
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,40 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="FoamLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the foam simulation, such as
/// depositing foam on the surface.
/// </remarks>
[@HelpURL("Manual/WaterAppearance.html#foam-inputs")]
[@FilterEnum(nameof(_Blend), Filtered.Mode.Include, (int)LodInputBlend.Additive, (int)LodInputBlend.Maximum)]
public sealed partial class FoamLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
#if d_CrestPaint
internal override LodInputMode DefaultMode => LodInputMode.Paint;
#else
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
#endif
internal override void InferBlend()
{
base.InferBlend();
if (_Mode is LodInputMode.Paint)
{
_Blend = LodInputBlend.Maximum;
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 67bc7f0b9724d44ab9f0ddf0b1b5a773
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: 20184ba74fed44301b1efff21519c308
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,266 +0,0 @@
// <auto-generated/>
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Absorption Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Spline, (int)LodInputMode.Paint)]
partial class AbsorptionLodInput
{
internal override Color GizmoColor => AbsorptionLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => AbsorptionLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(AbsorptionLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class AbsorptionTextureLodInputData : TextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._AbsorptionTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(AbsorptionLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class AbsorptionRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Absorption";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Albedo Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer)]
partial class AlbedoLodInput
{
internal override Color GizmoColor => AlbedoLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => AlbedoLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(AlbedoLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class AlbedoRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Albedo";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Animated Waves Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer)]
partial class AnimatedWavesLodInput
{
internal override Color GizmoColor => AnimatedWavesLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => AnimatedWavesLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(AnimatedWavesLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class AnimatedWavesRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Animated Waves";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Clip Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Paint, (int)LodInputMode.Primitive)]
partial class ClipLodInput
{
internal override Color GizmoColor => ClipLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => ClipLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(ClipLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class ClipTextureLodInputData : TextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._ClipTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(ClipLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class ClipRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Clip";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Water Depth Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Geometry)]
partial class DepthLodInput
{
internal override Color GizmoColor => DepthLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => DepthLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(DepthLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class DepthTextureLodInputData : TextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._DepthTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(DepthLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class DepthRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Depth";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Dynamic Waves Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer)]
partial class DynamicWavesLodInput
{
internal override Color GizmoColor => DynamicWavesLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => DynamicWavesLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(DynamicWavesLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class DynamicWavesRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Dynamic Waves";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Flow Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Paint, (int)LodInputMode.Spline)]
partial class FlowLodInput
{
internal override Color GizmoColor => FlowLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => FlowLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(FlowLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class FlowTextureLodInputData : DirectionalTextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._FlowTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(FlowLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class FlowRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Flow";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Foam Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Paint, (int)LodInputMode.Spline)]
partial class FoamLodInput
{
internal override Color GizmoColor => FoamLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => FoamLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(FoamLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class FoamTextureLodInputData : TextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._FoamTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(FoamLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class FoamRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Foam";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Water Level Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Paint, (int)LodInputMode.Spline, (int)LodInputMode.Geometry)]
partial class LevelLodInput
{
internal override Color GizmoColor => LevelLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => LevelLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(LevelLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class LevelTextureLodInputData : TextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._LevelTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(LevelLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class LevelRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Level";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Scattering Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Spline, (int)LodInputMode.Paint)]
partial class ScatteringLodInput
{
internal override Color GizmoColor => ScatteringLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => ScatteringLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(ScatteringLodInput), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class ScatteringTextureLodInputData : TextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._ScatteringTexture;
}
/// <inheritdoc/>
[ForLodInput(typeof(ScatteringLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class ScatteringRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Scattering";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Shadow Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer)]
partial class ShadowLodInput
{
internal override Color GizmoColor => ShadowLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => ShadowLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(ShadowLodInput), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class ShadowRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Shadow";
}
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Shape Waves Input")]
[@FilterEnum(nameof(_Mode), Filtered.Mode.Include, (int)LodInputMode.Renderer, (int)LodInputMode.Texture, (int)LodInputMode.Paint, (int)LodInputMode.Spline, (int)LodInputMode.Global)]
partial class ShapeWaves
{
internal override Color GizmoColor => AnimatedWavesLod.s_GizmoColor;
private protected override SortedList<int, ILodInput> Inputs => AnimatedWavesLod.s_Inputs;
}
/// <inheritdoc/>
[ForLodInput(typeof(ShapeWaves), LodInputMode.Texture)]
[System.Serializable]
public sealed partial class ShapeWavesTextureLodInputData : DirectionalTextureLodInputData
{
private protected override ComputeShader TextureShader => WaterResources.Instance.Compute._ShapeWavesTransfer;
}
/// <inheritdoc/>
[ForLodInput(typeof(ShapeWaves), LodInputMode.Renderer)]
[System.Serializable]
public sealed partial class ShapeWavesRendererLodInputData : RendererLodInputData
{
internal override string ShaderPrefix => "Crest/Inputs/Shape Waves";
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 47424a406f7a145f8a8d6c207b7afc60
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,111 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
using WaveHarmonic.Crest.Internal;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Data storage for for the Geometry input mode.
/// </summary>
[System.Serializable]
public abstract partial class GeometryLodInputData : LodInputData
{
[Tooltip("Geometry to render into the simulation.")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
internal Mesh _Geometry;
private protected abstract Shader GeometryShader { get; }
internal override bool IsEnabled => _Geometry != null;
Material _Material;
internal override void Draw(Lod lod, Component component, CommandBuffer buffer, RenderTargetIdentifier target, int slices)
{
#if UNITY_EDITOR
// Weird things happen when hitting save if this is not set here. Hitting save will
// still flicker the input, but without this it nothing renders.
if (!Application.isPlaying) LodInput.SetBlendFromPreset(_Material, _Input.Blend);
#endif
buffer.DrawMesh(_Geometry, component.transform.localToWorldMatrix, _Material);
}
internal override void OnEnable()
{
if (_Material == null)
{
_Material = new Material(GeometryShader);
}
LodInput.SetBlendFromPreset(_Material, _Input.Blend);
}
internal override void OnDisable()
{
// Empty.
}
internal override void RecalculateBounds()
{
_Bounds = _Input.transform.TransformBounds(_Geometry.bounds);
}
internal override void RecalculateRect()
{
_Rect = Bounds.RectXZ();
}
void SetGeometry(Mesh previous, Mesh current)
{
if (previous == current) return;
RecalculateCulling();
}
#if UNITY_EDITOR
internal override void OnChange(string propertyPath, object previousValue)
{
if (_Input == null || !_Input.isActiveAndEnabled) return;
switch (propertyPath)
{
case nameof(_Geometry):
SetGeometry((Mesh)previousValue, _Geometry);
break;
case "../" + nameof(LodInput._Blend):
LodInput.SetBlendFromPreset(_Material, _Input.Blend);
break;
}
}
internal override bool InferMode(Component component, ref LodInputMode mode)
{
return false;
}
internal override void Reset()
{
base.Reset();
_Geometry = Helpers.PlaneMesh;
}
#endif
}
/// <inheritdoc/>
[ForLodInput(typeof(LevelLodInput), LodInputMode.Geometry)]
public sealed class LevelGeometryLodInputData : GeometryLodInputData
{
private protected override Shader GeometryShader => WaterResources.Instance.Shaders._LevelGeometry;
}
/// <inheritdoc/>
[ForLodInput(typeof(DepthLodInput), LodInputMode.Geometry)]
public sealed class DepthGeometryLodInputData : GeometryLodInputData
{
private protected override Shader GeometryShader => WaterResources.Instance.Shaders._DepthGeometry;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 695da60ea6ccf44ea988e843144969cb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,4 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
// Intentionally empty.

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: cc9697a0accb44ec7a0f693182937c94
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,132 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="LevelLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the water height.
/// </remarks>
[@HelpURL("Manual/WaterBodies.html#water-bodies")]
[@FilterEnum(nameof(_Blend), Filtered.Mode.Include, (int)LodInputBlend.Off, (int)LodInputBlend.Additive, (int)LodInputBlend.Minimum, (int)LodInputBlend.Maximum)]
public sealed partial class LevelLodInput : LodInput
{
[@Heading("Water Chunk Culling")]
[Tooltip("Whether to use the manual \"Height Range\" for water chunk culling.\n\nMandatory for non mesh inputs like \"Texture\".")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
bool _OverrideHeight;
[Tooltip("The minimum and maximum height value to report for water chunk culling.")]
[@Predicated(nameof(_OverrideHeight))]
[@Range(-100, 100, Range.Clamp.None)]
[@GenerateAPI]
[SerializeField]
Vector2 _HeightRange = new(-100, 100);
LevelLodInput()
{
_FollowHorizontalWaveMotion = true;
}
// Water level is packed into alpha using the displaced position.
private protected override bool FollowHorizontalMotion => true;
internal override LodInputMode DefaultMode => LodInputMode.Geometry;
internal Rect _Rect;
internal override void InferBlend()
{
base.InferBlend();
_Blend = LodInputBlend.Off;
if (_Mode is LodInputMode.Paint or LodInputMode.Texture)
{
_Blend = LodInputBlend.Additive;
}
}
private protected override void Initialize()
{
base.Initialize();
_Reporter ??= new(this);
WaterChunkRenderer.HeightReporters.Add(_Reporter);
}
private protected override void OnDisable()
{
base.OnDisable();
WaterChunkRenderer.HeightReporters.Remove(_Reporter);
}
bool ReportHeight(ref Rect bounds, ref float minimum, ref float maximum)
{
if (!Enabled)
{
return false;
}
_Rect = Data.Rect;
// These modes do not provide a height yet.
if (!Data.HasHeightRange && !_OverrideHeight)
{
return false;
}
if (bounds.Overlaps(_Rect, false))
{
var range = _OverrideHeight ? _HeightRange : Data.HeightRange;
minimum = range.x;
maximum = range.y;
return true;
}
return false;
}
}
partial class LevelLodInput
{
Reporter _Reporter;
sealed class Reporter : IReportsHeight
{
readonly LevelLodInput _Input;
public Reporter(LevelLodInput input) => _Input = input;
public bool ReportHeight(ref Rect bounds, ref float minimum, ref float maximum) => _Input.ReportHeight(ref bounds, ref minimum, ref maximum);
}
}
partial class LevelLodInput : ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 1;
#pragma warning restore 414
/// <inheritdoc/>
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
// Version 1
// - Implemented blend mode but default value was serialized as Additive.
if (_Version < 1)
{
if (_Mode is LodInputMode.Spline or LodInputMode.Renderer) _Blend = LodInputBlend.Off;
_Version = 1;
}
}
/// <inheritdoc/>
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
// Empty.
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: a4edd034314af4679ba066d79580dc1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,485 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using WaveHarmonic.Crest.Internal;
namespace WaveHarmonic.Crest
{
interface ILodInput
{
const int k_QueueMaximumSubIndex = 1000;
/// <summary>
/// Draw the input (the render target will be bound)
/// </summary>
public void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1);
float Filter(WaterRenderer water, int slice);
/// <summary>
/// Whether to apply this input.
/// </summary>
bool Enabled { get; }
bool IsCompute { get; }
int Queue { get; }
int Pass { get; }
Rect Rect { get; }
MonoBehaviour Component { get; }
// Allow sorting within a queue. Callers can pass in things like sibling index to
// get deterministic sorting.
int Order => Queue * k_QueueMaximumSubIndex + Mathf.Min(Component.transform.GetSiblingIndex(), k_QueueMaximumSubIndex - 1);
internal static void Attach(ILodInput input, Utility.SortedList<int, ILodInput> inputs)
{
inputs.Remove(input);
inputs.Add(input.Order, input);
}
internal static void Detach(ILodInput input, Utility.SortedList<int, ILodInput> inputs)
{
inputs.Remove(input);
}
}
/// <summary>
/// Base class for scripts that register inputs to the various LOD data types.
/// </summary>
[@ExecuteDuringEditMode]
[@HelpURL("Manual/WaterInputs.html")]
public abstract partial class LodInput : ManagedBehaviour<WaterRenderer>
{
[Tooltip("The mode for this input.\n\nSee the manual for more details about input modes. Use AddComponent(LodInputMode) to set the mode via scripting. The mode cannot be changed after creation.")]
[@Filtered((int)LodInputMode.Unset)]
[@GenerateAPI(Setter.None)]
[SerializeField]
internal LodInputMode _Mode = LodInputMode.Unset;
// NOTE:
// Weight and Feather do not support Depth and Clip as they do not make much sense.
// For others it is a case of only supporting unsupported mode(s).
[Tooltip("Scales the input.")]
[@Predicated(typeof(AlbedoLodInput), inverted: true, hide: true)]
[@Predicated(typeof(ClipLodInput), inverted: true, hide: true)]
[@Predicated(typeof(DepthLodInput), inverted: true, hide: true)]
[@Range(0f, 1f)]
[@GenerateAPI]
[SerializeField]
float _Weight = 1f;
[Tooltip("The order this input will render.\n\nOrder is Queue plus SiblingIndex")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
int _Queue;
[Tooltip("How this input blends into existing data.\n\nSimilar to blend operations in shaders. For inputs which have materials, use the blend functionality on the shader/material.")]
[@Predicated(typeof(AbsorptionLodInput), inverted: true, hide: true)]
[@Predicated(typeof(AlbedoLodInput), inverted: true, hide: true)]
[@Predicated(typeof(AnimatedWavesLodInput), inverted: true, hide: true)]
[@Predicated(typeof(ClipLodInput), inverted: true, hide: true)]
[@Predicated(typeof(DepthLodInput), inverted: true, hide: true)]
[@Predicated(typeof(DynamicWavesLodInput), inverted: true, hide: true)]
[@Predicated(typeof(ScatteringLodInput), inverted: true, hide: true)]
[@Predicated(typeof(ShadowLodInput), inverted: true, hide: true)]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Global))]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Primitive))]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Renderer))]
[@Filtered]
[@GenerateAPI]
[SerializeField]
internal LodInputBlend _Blend = LodInputBlend.Additive;
[@Label("Feather")]
[Tooltip("The width of the feathering to soften the edges to blend inputs.\n\nInputs that do not support feathering will have this field disabled or hidden in UI.")]
[@Predicated(typeof(AlbedoLodInput), inverted: true, hide: true)]
[@Predicated(typeof(AnimatedWavesLodInput), inverted: true, hide: true)]
[@Predicated(typeof(ClipLodInput), inverted: true, hide: true)]
[@Predicated(typeof(DepthLodInput), inverted: true, hide: true)]
[@Predicated(typeof(DynamicWavesLodInput), inverted: true, hide: true)]
[@Predicated(typeof(LevelLodInput), inverted: true, hide: true)]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Renderer))]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Global))]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Primitive))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
float _FeatherWidth = 0.1f;
[Tooltip("How this input responds to horizontal displacement.\n\nIf false, data will not move horizontally with the waves. Has a small performance overhead when disabled. Only suitable for inputs of small size.")]
[@Predicated(typeof(ClipLodInput), inverted: true, hide: true)]
[@Predicated(typeof(FlowLodInput), inverted: true, hide: true)]
[@Predicated(typeof(LevelLodInput), inverted: true, hide: true)]
[@Predicated(typeof(ShapeWaves), inverted: true, hide: true)]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Global))]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Spline))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
private protected bool _FollowHorizontalWaveMotion = false;
[@Heading("Mode")]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Unset), hide: true)]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Primitive), hide: true)]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Global), hide: true)]
[@Stripped]
[SerializeReference]
internal LodInputData _Data;
// Need always visble for space to appear before foldout instead of inside.
[@Space(10, isAlwaysVisible: true)]
[@Group("Debug", order = k_DebugGroupOrder)]
[@Predicated(nameof(_Mode), inverted: false, nameof(LodInputMode.Global))]
[@DecoratedField, SerializeField]
internal bool _DrawBounds;
internal const int k_DebugGroupOrder = 10;
internal static class ShaderIDs
{
public static int s_Weight = Shader.PropertyToID("_Crest_Weight");
public static int s_DisplacementAtInputPosition = Shader.PropertyToID("_Crest_DisplacementAtInputPosition");
public static readonly int s_BlendSource = Shader.PropertyToID("_Crest_BlendSource");
public static readonly int s_BlendTarget = Shader.PropertyToID("_Crest_BlendTarget");
public static readonly int s_BlendOperation = Shader.PropertyToID("_Crest_BlendOperation");
}
internal abstract Color GizmoColor { get; }
internal abstract LodInputMode DefaultMode { get; }
private protected abstract Utility.SortedList<int, ILodInput> Inputs { get; }
/// <summary>
/// Disables rendering of input into data, but continues most scripting activities.
/// </summary>
public bool ForceRenderingOff { get; set; }
/// <summary>
/// Properties specific to <see cref="Mode"/>.
/// </summary>
/// <remarks>
/// <para>
/// You will need to cast to a more specific type to change
/// certain properties. Types derive from and end with <see cref="LodInputData"/>.
/// Consider using <see cref="GetData{DataType}"/> which will validate and cast.
/// </para>
/// <para>
/// <see cref="LodInputMode.Global"/> and <see cref="LodInputMode.Primitive"/> will
/// have no associated data and will be null. The rest will have an
/// <see cref="LodInputData"/> type which will be prefixed with the input type and
/// then mode (eg <see cref="LodInputMode.Texture"/> mode for
/// <see cref="FoamLodInput"/> will be <see cref="FoamTextureLodInputData"/>).
/// </para>
/// <para>
/// An exception is <see cref="ShapeGerstner"/> and <see cref="ShapeFFT"/>. They
/// are derived from <see cref="ShapeWaves"/> and use it as a prefix. (eg <see
/// cref="ShapeWavesTextureLodInputData"/>).
/// </para>
/// </remarks>
public LodInputData Data { get => _Data; internal set => _Data = value; }
/// <summary>
/// Retrieves the typed data and validates the passed type.
/// </summary>
/// <remarks>
/// Validation is stripped from builds.
/// </remarks>
/// <typeparam name="T">The data type to cast to.</typeparam>
/// <returns>The casted data.</returns>
public T GetData<T>() where T : LodInputData
{
if (_Mode is LodInputMode.Global or LodInputMode.Primitive or LodInputMode.Unset)
{
Debug.AssertFormat(false, "Crest: {0} has no associated data type.", _Mode);
return null;
}
Debug.AssertFormat(Data is T, "Crest: Incorrect data type ({1}). The data type is {0}.", Data.GetType().BaseType.Name, typeof(T).Name);
return Data as T;
}
internal bool IsCompute => Mode is LodInputMode.Texture or LodInputMode.Paint or LodInputMode.Global or LodInputMode.Primitive;
internal virtual int Pass => -1;
internal virtual Rect Rect
{
get
{
var rect = Rect.zero;
if (_Data != null)
{
rect = _Data.Rect;
rect.center -= _Displacement.XZ();
}
return rect;
}
}
readonly SampleCollisionHelper _SampleHeightHelper = new();
Vector3 _Displacement;
private protected bool _RecalculateBounds = true;
internal virtual bool Enabled => enabled && !ForceRenderingOff && Mode switch
{
LodInputMode.Unset => false,
_ => Data?.IsEnabled ?? false,
};
// By default do not follow horizontal motion of waves. This means that the water input will appear on the surface at its XZ location, instead
// of moving horizontally with the waves.
private protected virtual bool FollowHorizontalMotion => Mode is LodInputMode.Global or LodInputMode.Spline || _FollowHorizontalWaveMotion;
//
// Event Methods
//
private protected override void Initialize()
{
base.Initialize();
Data?.OnEnable();
Attach();
}
private protected override void OnDisable()
{
base.OnDisable();
Detach();
Data?.OnDisable();
}
private protected override Action<WaterRenderer> OnUpdateMethod => OnUpdate;
private protected virtual void OnUpdate(WaterRenderer water)
{
if (transform.hasChanged)
{
_RecalculateBounds = true;
}
// Input culling depends on displacement.
if (!FollowHorizontalMotion)
{
_SampleHeightHelper.SampleDisplacement(transform.position, out _Displacement);
}
else
{
_Displacement = Vector3.zero;
}
Data?.OnUpdate();
}
private protected override Action<WaterRenderer> OnLateUpdateMethod => OnLateUpdate;
private protected virtual void OnLateUpdate(WaterRenderer water)
{
Data?.OnLateUpdate();
transform.hasChanged = false;
}
//
// ILodInput
//
private protected virtual void Attach()
{
_Input ??= new(this);
ILodInput.Attach(_Input, Inputs);
}
private protected virtual void Detach()
{
ILodInput.Detach(_Input, Inputs);
}
internal virtual void Draw(Lod simulation, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1f, int slice = -1)
{
if (weight == 0f)
{
return;
}
// Must use global as weight can change per slice for ShapeWaves.
var wrapper = new PropertyWrapperBuffer(buffer);
wrapper.SetFloat(ShaderIDs.s_Weight, weight * _Weight);
wrapper.SetVector(ShaderIDs.s_DisplacementAtInputPosition, _Displacement);
Data?.Draw(simulation, this, buffer, target, slice);
}
internal virtual float Filter(WaterRenderer water, int slice)
{
return 1f;
}
/// <summary>
/// Sets the Blend render state using Blend present.
/// </summary>
internal static void SetBlendFromPreset(Material material, LodInputBlend preset)
{
// Blend.Additive
var source = BlendMode.One;
var target = BlendMode.One;
var operation = BlendOp.Add;
switch (preset)
{
case LodInputBlend.Off:
source = BlendMode.One;
target = BlendMode.Zero;
break;
case LodInputBlend.Alpha or LodInputBlend.AlphaClip:
source = BlendMode.One; // We apply alpha before blending.
target = BlendMode.OneMinusSrcAlpha;
break;
case LodInputBlend.Maximum:
operation = BlendOp.Max;
break;
case LodInputBlend.Minimum:
operation = BlendOp.Min;
break;
}
// SetInteger did not appear to work last time. Will need to revisit.
material.SetInt(ShaderIDs.s_BlendSource, (int)source);
material.SetInt(ShaderIDs.s_BlendTarget, (int)target);
material.SetInt(ShaderIDs.s_BlendOperation, (int)operation);
}
void SetQueue(int previous, int current)
{
if (previous == current) return;
if (!isActiveAndEnabled) return;
Attach();
}
internal virtual void InferBlend()
{
// Correct for most cases.
_Blend = LodInputBlend.Additive;
}
//
// Editor Only Methods
//
#if UNITY_EDITOR
[@OnChange(skipIfInactive: false)]
void OnChange(string propertyPath, object previousValue)
{
switch (propertyPath)
{
case nameof(_Queue):
SetQueue((int)previousValue, _Queue);
break;
case nameof(_Mode):
if (!isActiveAndEnabled) { ChangeMode(Mode); break; }
OnDisable();
ChangeMode(Mode);
UnityEditor.EditorTools.ToolManager.RefreshAvailableTools();
OnEnable();
break;
case nameof(_Blend):
// TODO: Make compatible with disabled.
if (isActiveAndEnabled) Data.OnChange($"../{propertyPath}", previousValue);
break;
}
}
internal void ChangeMode(LodInputMode mode)
{
_Data = null;
// Try to infer the mode.
var types = TypeCache.GetTypesWithAttribute<ForLodInput>();
var self = GetType();
foreach (var type in types)
{
var attributes = type.GetCustomAttributes<ForLodInput>();
foreach (var attribute in attributes)
{
if (attribute._Mode != mode) continue;
if (!attribute._Type.IsAssignableFrom(self)) continue;
_Mode = mode;
InferBlend();
_Data = (LodInputData)Activator.CreateInstance(type);
_Data._Input = this;
_Data.InferMode(this, ref _Mode);
return;
}
}
_Mode = DefaultMode;
InferBlend();
}
/// <summary>
/// Called when component attached in edit mode, or when Reset clicked by user.
/// Besides recovering from Unset default value, also does a nice bit of auto-config.
/// </summary>
private protected override void Reset()
{
var types = TypeCache.GetTypesWithAttribute<ForLodInput>();
var self = GetType();
// Use inferred mode.
foreach (var type in types)
{
var attributes = type.GetCustomAttributes<ForLodInput>();
foreach (var attribute in attributes)
{
if (!attribute._Type.IsAssignableFrom(self)) continue;
var instance = (LodInputData)Activator.CreateInstance(type);
instance._Input = this;
if (instance.InferMode(this, ref _Mode))
{
_Data = instance;
InferBlend();
return;
}
}
}
// Use default mode.
ChangeMode(DefaultMode);
_Data?.Reset();
base.Reset();
}
#endif
}
partial class LodInput
{
Input _Input;
sealed class Input : ILodInput
{
readonly LodInput _Input;
public Input(LodInput input) => _Input = input;
public bool Enabled => _Input.Enabled;
public bool IsCompute => _Input.IsCompute;
public int Queue => _Input.Queue;
public int Pass => _Input.Pass;
public Rect Rect => _Input.Rect;
public MonoBehaviour Component => _Input;
public float Filter(WaterRenderer water, int slice) => _Input.Filter(water, slice);
public void Draw(Lod lod, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1, int slice = -1) => _Input.Draw(lod, buffer, target, pass, weight, slice);
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 126e7f9b525874cdbb0653a0f1662e18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,212 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace WaveHarmonic.Crest
{
[AttributeUsage(AttributeTargets.Class)]
sealed class ForLodInput : Attribute
{
public readonly Type _Type;
public readonly LodInputMode _Mode;
public ForLodInput(Type type, LodInputMode mode)
{
_Type = type;
_Mode = mode;
}
}
/// <summary>
/// Data storage for an input, pertinent to the associated input mode.
/// </summary>
public abstract class LodInputData
{
[SerializeField, HideInInspector]
internal LodInput _Input;
private protected Rect _Rect;
private protected Bounds _Bounds;
private protected bool _RecalculateRect = true;
private protected bool _RecalculateBounds = true;
internal abstract bool IsEnabled { get; }
internal abstract void OnEnable();
internal abstract void OnDisable();
internal abstract void Draw(Lod lod, Component component, CommandBuffer buffer, RenderTargetIdentifier target, int slice);
internal abstract void RecalculateRect();
internal abstract void RecalculateBounds();
internal virtual bool HasHeightRange => true;
internal Rect Rect
{
get
{
if (_RecalculateRect)
{
RecalculateRect();
_RecalculateRect = false;
}
return _Rect;
}
}
internal Bounds Bounds
{
get
{
if (_RecalculateBounds)
{
RecalculateBounds();
_RecalculateBounds = false;
}
return _Bounds;
}
}
// Warning: NotImplementedException is thrown for paint and texture types.
internal Vector2 HeightRange
{
get
{
if (!HasHeightRange) return Vector2.zero;
var bounds = Bounds;
return new(bounds.min.y, bounds.max.y);
}
}
private protected void RecalculateCulling()
{
_RecalculateRect = _RecalculateBounds = true;
}
internal virtual void OnUpdate()
{
if (_Input.transform.hasChanged)
{
RecalculateCulling();
}
}
internal virtual void OnLateUpdate()
{
}
#if UNITY_EDITOR
internal abstract void OnChange(string propertyPath, object previousValue);
internal abstract bool InferMode(Component component, ref LodInputMode mode);
internal virtual void Reset() { }
#endif
}
/// <summary>
/// Modes that inputs can use. Not all inputs support all modes. Refer to the UI.
/// </summary>
public enum LodInputMode
{
/// <summary>
/// Unset is the serialization default.
/// </summary>
/// <remarks>
/// This will be replaced with the default mode automatically. Unset can also be
/// used if something is invalid.
/// </remarks>
Unset = 0,
/// <summary>
/// Hand-painted data by the user. Currently unused.
/// </summary>
Paint,
/// <summary>
/// Driven by a user created spline.
/// </summary>
Spline,
/// <summary>
/// Attached 'Renderer' (mesh, particle or other) used to drive data.
/// </summary>
Renderer,
/// <summary>
/// Driven by a mathematical primitive such as a cube or sphere.
/// </summary>
Primitive,
/// <summary>
/// Covers the entire water area.
/// </summary>
Global,
/// <summary>
/// Data driven by a user provided texture.
/// </summary>
Texture,
/// <summary>
/// Renders geometry using a default material.
/// </summary>
Geometry,
}
/// <summary>
/// Blend presets for inputs.
/// </summary>
public enum LodInputBlend
{
/// <summary>
/// No blending. Overwrites.
/// </summary>
Off,
/// <summary>
/// Additive blending.
/// </summary>
Additive,
/// <summary>
/// Takes the minimum value.
/// </summary>
Minimum,
/// <summary>
/// Takes the maximum value.
/// </summary>
Maximum,
/// <summary>
/// Applies the inverse weight to the target.
/// </summary>
/// <remarks>
/// Basically overwrites what is already in the simulation.
/// </remarks>
Alpha,
/// <summary>
/// Same as alpha except anything above zero will overwrite rather than blend.
/// </summary>
AlphaClip,
}
/// <summary>
/// Primitive shapes.
/// </summary>
// Have this match UnityEngine.PrimitiveType.
public enum LodInputPrimitive
{
/// <summary>
/// Spheroid.
/// </summary>
Sphere = 0,
/// <summary>
/// Cuboid.
/// </summary>
Cube = 3,
/// <summary>
/// Quad.
/// </summary>
Quad = 5,
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 6a95cc8f7e50c47d8bfdda73f6da338a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,272 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Data storage for for the Renderer input mode.
/// </summary>
public abstract partial class RendererLodInputData : LodInputData
{
[Tooltip("The renderer to use for this input.\n\nCan be anything that inherits from <i>Renderer</i> like <i>MeshRenderer</i>, <i>TrailRenderer</i> etc.")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
internal Renderer _Renderer;
[Tooltip("Forces the renderer to only render into the LOD data, and not to render in the scene as it normally would.")]
[@GenerateAPI(Setter.Custom)]
[@DecoratedField, SerializeField]
internal bool _DisableRenderer = true;
[Tooltip("Whether to set the shader pass manually.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal bool _OverrideShaderPass;
[Tooltip("The shader pass to execute.\n\nSet to -1 to execute all passes.")]
[@Predicated(nameof(_OverrideShaderPass))]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal int _ShaderPassIndex;
#pragma warning disable 414
[Tooltip("Check that the shader applied to this object matches the input type.\n\nFor example, an Animated Waves input object has an Animated Waves input shader.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal bool _CheckShaderName = true;
[Tooltip("Check that the shader applied to this object has only a single pass, as only the first pass is executed for most inputs.")]
[@GenerateAPI]
[@DecoratedField, SerializeField]
internal bool _CheckShaderPasses = true;
#pragma warning restore 414
static class ShaderIDs
{
public static readonly int s_Time = Shader.PropertyToID("_Time");
}
// Some renderers require multiple materials like particles with trails.
// We pass this to GetSharedMaterials to avoid allocations.
internal List<Material> _Materials = new();
MaterialPropertyBlock _MaterialPropertyBlock;
internal abstract string ShaderPrefix { get; }
internal override bool IsEnabled => _Renderer != null && _MaterialPropertyBlock != null;
internal override void RecalculateRect()
{
_Rect = Rect.MinMaxRect(_Renderer.bounds.min.x, _Renderer.bounds.min.z, _Renderer.bounds.max.x, _Renderer.bounds.max.z);
}
internal override void RecalculateBounds()
{
_Bounds = _Renderer.bounds;
}
bool AnyOtherInputsControllingRenderer(Renderer renderer)
{
for (var index = 0; index < SceneManager.sceneCount; index++)
{
var scene = SceneManager.GetSceneAt(index);
if (!scene.isLoaded)
{
continue;
}
foreach (var rootGameObject in scene.GetRootGameObjects())
{
foreach (var component in rootGameObject.GetComponentsInChildren<LodInput>())
{
if (component == _Input)
{
continue;
}
if (component.Data is not RendererLodInputData data)
{
continue;
}
if (component.isActiveAndEnabled && data._DisableRenderer && data._Renderer == renderer)
{
return true;
}
}
}
}
return false;
}
internal override void OnEnable()
{
_MaterialPropertyBlock ??= new();
if (_Renderer == null)
{
return;
}
_Renderer.GetSharedMaterials(_Materials);
if (_DisableRenderer)
{
// If we disable using "enabled" then the renderer might not behave correctly (eg line/trail positions
// will not be updated). This keeps the scripting side of the component running and just disables the
// rendering. Similar to disabling the Renderer module on the Particle System. It also is not serialized.
_Renderer.forceRenderingOff = true;
}
}
internal override void OnDisable()
{
if (_Renderer != null && _DisableRenderer && !AnyOtherInputsControllingRenderer(_Renderer))
{
_Renderer.forceRenderingOff = false;
}
}
internal override void OnUpdate()
{
if (_Renderer == null)
{
return;
}
// We have to check this every time as the user could change the materials and it is too difficult to track.
// Doing this in LateUpdate could add one frame latency to receiving the change.
_Renderer.GetSharedMaterials(_Materials);
// Always recalculate, as there are too much to track.
_RecalculateBounds = true;
_RecalculateRect = _Bounds != _Renderer.bounds;
}
internal override void Draw(Lod lod, Component component, CommandBuffer buffer, RenderTargetIdentifier target, int slice)
{
// NOTE: Inputs will only change the first material (only ShapeWaves at the moment).
for (var i = 0; i < _Materials.Count; i++)
{
var material = _Materials[i];
Debug.AssertFormat(material != null, _Renderer, "Crest: Attached renderer has an empty material slot which is not allowed.");
#if UNITY_EDITOR
// Empty material slots is a user error, but skip so we do not spam errors.
if (material == null)
{
continue;
}
#endif
var pass = _ShaderPassIndex;
if (ShapeWaves.s_RenderPassOverride > -1)
{
// Needs to use a second pass to disable blending.
pass = ShapeWaves.s_RenderPassOverride;
}
else if (!_OverrideShaderPass)
{
// BIRP/URP SG first pass is the right one.
pass = 0;
// Support HDRP SG. It will always have more than one pass.
if (RenderPipelineHelper.IsHighDefinition && material.shader.passCount > 1)
{
var sgPass = material.FindPass("ForwardOnly");
if (sgPass > -1) pass = sgPass;
}
}
else if (_ShaderPassIndex > material.shader.passCount - 1)
{
return;
}
// Time is not set for us for some reason… Use Time.timeSinceLevelLoad as per:
// https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
if (RenderPipelineHelper.IsLegacy)
{
_Renderer.GetPropertyBlock(_MaterialPropertyBlock);
_MaterialPropertyBlock.SetVector(ShaderIDs.s_Time, new
(
Time.timeSinceLevelLoad / 20,
Time.timeSinceLevelLoad,
Time.timeSinceLevelLoad * 2f,
Time.timeSinceLevelLoad * 3f
));
_Renderer.SetPropertyBlock(_MaterialPropertyBlock);
}
// By default, shaderPass is -1 which is all passes. Shader Graph will produce multi-pass shaders
// for depth etc so we should only render one pass. Unlit SG will have the unlit pass first.
// Submesh count generally must equal number of materials.
buffer.DrawRenderer(_Renderer, material, submeshIndex: i, pass);
}
}
void SetRenderer(Renderer previous, Renderer current)
{
if (previous == current) return;
if (_Input == null || !_Input.isActiveAndEnabled) return;
if (previous != null && _DisableRenderer && !AnyOtherInputsControllingRenderer(previous))
{
// Turn off if there are no other inputs have set this value.
previous.forceRenderingOff = false;
}
if (current != null)
{
current.forceRenderingOff = true;
}
}
void SetDisableRenderer(bool previous, bool current)
{
if (previous == current) return;
if (_Input == null || !_Input.isActiveAndEnabled) return;
if (_Renderer != null && !AnyOtherInputsControllingRenderer(_Renderer))
{
_Renderer.forceRenderingOff = _DisableRenderer;
}
}
#if UNITY_EDITOR
[@OnChange]
internal override void OnChange(string propertyPath, object previousValue)
{
switch (propertyPath)
{
case nameof(_Renderer):
SetRenderer((Renderer)previousValue, _Renderer);
break;
case nameof(_DisableRenderer):
SetDisableRenderer((bool)previousValue, _DisableRenderer);
break;
}
}
internal override bool InferMode(Component component, ref LodInputMode mode)
{
if (component.TryGetComponent(out _Renderer))
{
mode = LodInputMode.Renderer;
return true;
}
return false;
}
#endif
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c0ee0dbacf6784d1a8608ad94109098d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,37 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="ScatteringLod"/>.
/// </summary>
/// <remarks>
/// Attach this to objects that you want to influence the scattering color.
/// </remarks>
[@HelpURL("Manual/WaterAppearance.html#volume-color-inputs")]
public sealed partial class ScatteringLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
#if d_CrestPaint
internal override LodInputMode DefaultMode => LodInputMode.Paint;
#else
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
#endif
internal override void InferBlend()
{
base.InferBlend();
_Blend = LodInputBlend.Alpha;
}
// Looks fine moving around.
private protected override bool FollowHorizontalMotion => true;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: c85179d3b43c5467da99463c8a2199ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,24 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Registers a custom input to the <see cref="ShadowLod"/>.
/// </summary>
/// <remarks>
/// Attach this objects that you want use to override shadows.
/// </remarks>
[@HelpURL("Manual/WaterAppearance.html#shadows-lod")]
public sealed partial class ShadowLodInput : LodInput
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 0;
#pragma warning restore 414
internal override LodInputMode DefaultMode => LodInputMode.Renderer;
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: fcda6c7640ad44106aa39234017df797
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,8 +0,0 @@
fileFormatVersion: 2
guid: d7eafa182f969495d9e74b145310c516
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,212 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
namespace WaveHarmonic.Crest
{
/// <summary>
/// FFT wave shape.
/// </summary>
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Shape FFT")]
public sealed partial class ShapeFFT : ShapeWaves
{
// Waves
[Tooltip("How turbulent/chaotic the waves are.")]
[@Range(0, 1, order = -3)]
[@GenerateAPI]
[SerializeField]
float _WindTurbulence = 0.145f;
[Tooltip("How aligned the waves are with wind.")]
[@Range(0, 1, order = -4)]
[@GenerateAPI]
[SerializeField]
float _WindAlignment;
// Generation
[Tooltip("FFT waves will loop with a period of this many seconds.")]
[@Range(4f, 128f, Range.Clamp.Minimum)]
[@GenerateAPI]
[SerializeField]
float _TimeLoopLength = Mathf.Infinity;
[Header("Culling")]
[Tooltip("Maximum amount the surface will be displaced vertically from sea level.\n\nIncrease this if gaps appear at bottom of screen.")]
[@GenerateAPI]
[SerializeField]
float _MaximumVerticalDisplacement = 10f;
[Tooltip("Maximum amount a point on the surface will be displaced horizontally by waves from its rest position.\n\nIncrease this if gaps appear at sides of screen.")]
[@GenerateAPI]
[SerializeField]
float _MaximumHorizontalDisplacement = 15f;
[@Heading("Collision Data Baking")]
[Tooltip("Enable running this FFT with baked data.\n\nThis makes the FFT periodic (repeating in time).")]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
[@DecoratedField, SerializeField]
internal bool _EnableBakedCollision = false;
[Tooltip("Frames per second of baked data.\n\nLarger values may help the collision track the surface closely at the cost of more frames and increase baked data size.")]
[@Predicated(nameof(_EnableBakedCollision))]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
[@DecoratedField, SerializeField]
internal int _TimeResolution = 4;
[Tooltip("Smallest wavelength required in collision.\n\nTo preview the effect of this, disable power sliders in spectrum for smaller values than this number. Smaller values require more resolution and increase baked data size.")]
[@Predicated(nameof(_EnableBakedCollision))]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
[@DecoratedField, SerializeField]
internal float _SmallestWavelengthRequired = 2f;
[Tooltip("FFT waves will loop with a period of this many seconds.\n\nSmaller values decrease data size but can make waves visibly repetitive.")]
[@Predicated(nameof(_EnableBakedCollision))]
[@Predicated(nameof(_Mode), inverted: true, nameof(LodInputMode.Global), hide: true)]
[@Range(4f, 128f)]
[SerializeField]
internal float _BakedTimeLoopLength = 32f;
internal float LoopPeriod => _EnableBakedCollision ? _BakedTimeLoopLength : _TimeLoopLength;
private protected override int MinimumResolution => 16;
private protected override int MaximumResolution => int.MaxValue;
FFTCompute.Parameters _OldFFTParameters;
internal FFTCompute.Parameters FFTParameters => new
(
_ActiveSpectrum,
Resolution,
_TimeLoopLength,
WindSpeedMPS,
WindDirRadForFFT,
_WindTurbulence,
_WindAlignment
);
private protected override void OnUpdate(WaterRenderer water)
{
base.OnUpdate(water);
// We do not filter FFTs.
_FirstCascade = 0;
_LastCascade = k_CascadeCount - 1;
ReportMaxDisplacement(water);
// If geometry is being used, the water input shader will rotate the waves to align to geo
var parameters = FFTParameters;
// Don't create tons of generators when values are varying. Notify so that existing generators may be adapted.
if (parameters.GetHashCode() != _OldFFTParameters.GetHashCode())
{
FFTCompute.OnGenerationDataUpdated(_OldFFTParameters, parameters);
}
_OldFFTParameters = parameters;
}
internal override void Draw(Lod lod, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1, int slice = -1)
{
if (_LastGenerateFrameCount != Time.frameCount)
{
_WaveBuffers = FFTCompute.GenerateDisplacements
(
buffer,
lod.Water.CurrentTime,
FFTParameters,
UpdateDataEachFrame
);
_LastGenerateFrameCount = Time.frameCount;
}
base.Draw(lod, buffer, target, pass, weight, slice);
}
private protected override void SetRenderParameters<T>(WaterRenderer water, T wrapper)
{
base.SetRenderParameters(water, wrapper);
// If using geometry, the primary wave direction is used by the input shader to
// rotate the waves relative to the geo rotation. If not, the wind direction is
// already used in the FFT generation.
var waveDir = (Mode is LodInputMode.Spline or LodInputMode.Paint) ? PrimaryWaveDirection : Vector2.right;
wrapper.SetVector(ShaderIDs.s_AxisX, waveDir);
}
private protected override void ReportMaxDisplacement(WaterRenderer water)
{
if (!Enabled) return;
// Apply weight or will cause popping due to scale change.
MaximumReportedHorizontalDisplacement = _MaximumHorizontalDisplacement * Weight;
MaximumReportedVerticalDisplacement = MaximumReportedWavesDisplacement = _MaximumVerticalDisplacement * Weight;
if (Mode == LodInputMode.Global)
{
water.ReportMaximumDisplacement(MaximumReportedHorizontalDisplacement, MaximumReportedVerticalDisplacement, MaximumReportedVerticalDisplacement);
}
}
private protected override void DestroySharedResources()
{
FFTCompute.CleanUpAll();
}
float WindDirRadForFFT
{
get
{
// These input types use a wave direction provided by geometry or the painted user direction
if (Mode is LodInputMode.Spline or LodInputMode.Paint)
{
return 0f;
}
return _WaveDirectionHeadingAngle * Mathf.Deg2Rad;
}
}
#if UNITY_EDITOR
void OnGUI()
{
if (_DrawSlicesInEditor)
{
FFTCompute.GetInstance(FFTParameters)?.OnGUI();
}
}
internal FFTCompute GetFFTComputeInstance()
{
return FFTCompute.GetInstance(FFTParameters);
}
#endif
}
partial class ShapeFFT : ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 1;
#pragma warning restore 414
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
_Version = MigrateV1(_Version);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
// Empty.
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 88bb6e05d83b64105a4d8cbd478f5916
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,523 +0,0 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using WaveHarmonic.Crest.Utility;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Gerstner wave shape.
/// </summary>
[AddComponentMenu(Constants.k_MenuPrefixInputs + "Shape Gerstner")]
public sealed partial class ShapeGerstner : ShapeWaves
{
// Waves
[Tooltip("The weight of the opposing, second pair of Gerstner waves.\n\nEach Gerstner wave is actually a pair of waves travelling in opposite directions (similar to FFT). This weight is applied to the wave travelling in against-wind direction. Set to zero to obtain simple single waves which are useful for shorelines waves.")]
[@Range(0f, 1f, order = -3)]
[@GenerateAPI]
[SerializeField]
float _ReverseWaveWeight = 0.5f;
// Generation Settings
[Tooltip("How many wave components to generate in each octave.")]
[@Delayed]
[@GenerateAPI]
[SerializeField]
int _ComponentsPerOctave = 8;
[Tooltip("Change to get a different set of waves.")]
[@GenerateAPI]
[SerializeField]
int _RandomSeed = 0;
private protected override int MinimumResolution => 8;
private protected override int MaximumResolution => 64;
float _WindSpeedWhenGenerated = -1f;
const int k_MaximumWaveComponents = 1024;
// Data for all components
float[] _Wavelengths;
float[] _Amplitudes;
float[] _Amplitudes2;
float[] _Powers;
float[] _AngleDegrees;
float[] _Phases;
float[] _Phases2;
struct GerstnerCascadeParams
{
public int _StartIndex;
}
ComputeBuffer _BufferCascadeParameters;
readonly GerstnerCascadeParams[] _CascadeParameters = new GerstnerCascadeParams[k_CascadeCount + 1];
// Caution - order here impact performance. Rearranging these to match order
// they're read in the compute shader made it 50% slower..
struct GerstnerWaveComponent4
{
public Vector4 _TwoPiOverWavelength;
public Vector4 _Amplitude;
public Vector4 _WaveDirectionX;
public Vector4 _WaveDirectionZ;
public Vector4 _Omega;
public Vector4 _Phase;
public Vector4 _ChopAmplitude;
// Waves are generated in pairs, these values are for the second in the pair
public Vector4 _Amplitude2;
public Vector4 _ChopAmplitude2;
public Vector4 _Phase2;
}
ComputeBuffer _BufferWaveData;
readonly GerstnerWaveComponent4[] _WaveData = new GerstnerWaveComponent4[k_MaximumWaveComponents / 4];
ComputeShader _ShaderGerstner;
int _KernelGerstner = -1;
static new class ShaderIDs
{
public static readonly int s_FirstCascadeIndex = Shader.PropertyToID("_Crest_FirstCascadeIndex");
public static readonly int s_TextureRes = Shader.PropertyToID("_Crest_TextureRes");
public static readonly int s_CascadeParams = Shader.PropertyToID("_Crest_GerstnerCascadeParams");
public static readonly int s_GerstnerWaveData = Shader.PropertyToID("_Crest_GerstnerWaveData");
}
readonly float _TwoPi = 2f * Mathf.PI;
readonly float _ReciprocalTwoPi = 1f / (2f * Mathf.PI);
internal static readonly SortedList<int, ShapeGerstner> s_Instances = new(Helpers.SiblingIndexComparison);
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void InitStatics()
{
s_Instances.Clear();
}
void InitData()
{
if (_WaveBuffers == null)
{
_WaveBuffers = new(_Resolution, _Resolution, 0, GraphicsFormat.R16G16B16A16_SFloat);
}
else
{
_WaveBuffers.Release();
}
{
_WaveBuffers.width = _WaveBuffers.height = _Resolution;
_WaveBuffers.wrapMode = TextureWrapMode.Clamp;
_WaveBuffers.antiAliasing = 1;
_WaveBuffers.filterMode = FilterMode.Bilinear;
_WaveBuffers.anisoLevel = 0;
_WaveBuffers.useMipMap = false;
_WaveBuffers.name = "_Crest_GerstnerCascades";
_WaveBuffers.dimension = TextureDimension.Tex2DArray;
_WaveBuffers.volumeDepth = k_CascadeCount;
_WaveBuffers.enableRandomWrite = true;
_WaveBuffers.Create();
}
_BufferCascadeParameters?.Release();
_BufferWaveData?.Release();
_BufferCascadeParameters = new(k_CascadeCount + 1, UnsafeUtility.SizeOf<GerstnerCascadeParams>());
_BufferWaveData = new(k_MaximumWaveComponents / 4, UnsafeUtility.SizeOf<GerstnerWaveComponent4>());
_ShaderGerstner = WaterResources.Instance.Compute._Gerstner;
_KernelGerstner = _ShaderGerstner.FindKernel("Gerstner");
}
private protected override void OnUpdate(WaterRenderer water)
{
var isFirstUpdate = _FirstUpdate;
base.OnUpdate(water);
if (_WaveBuffers == null || _Resolution != _WaveBuffers.width || _BufferCascadeParameters == null || _BufferWaveData == null)
{
InitData();
}
var windSpeed = WindSpeedMPS;
if (isFirstUpdate || UpdateDataEachFrame || windSpeed != _WindSpeedWhenGenerated)
{
UpdateWaveData(water, windSpeed);
_WindSpeedWhenGenerated = windSpeed;
}
ReportMaxDisplacement(water);
}
internal override void Draw(Lod lod, CommandBuffer buffer, RenderTargetIdentifier target, int pass = -1, float weight = 1, int slice = -1)
{
if (_LastGenerateFrameCount != Time.frameCount)
{
if (_FirstCascade >= 0 && _LastCascade >= 0)
{
UpdateGenerateWaves(buffer);
// Above changes the render target. Change it back if necessary.
if (!IsCompute) buffer.SetRenderTarget(target, 0, CubemapFace.Unknown, slice);
}
_LastGenerateFrameCount = Time.frameCount;
}
base.Draw(lod, buffer, target, pass, weight, slice);
}
private protected override void SetRenderParameters<T>(WaterRenderer water, T wrapper)
{
base.SetRenderParameters(water, wrapper);
wrapper.SetVector(ShapeWaves.ShaderIDs.s_AxisX, PrimaryWaveDirection);
}
void SliceUpWaves(WaterRenderer water, float windSpeed)
{
// Do not filter cascades if blending as the blend operation might be skipped.
// Same for renderer as we do not know the blend operation.
var isFilterable = Blend != LodInputBlend.Alpha && _Mode != LodInputMode.Renderer;
_FirstCascade = isFilterable ? -1 : 0;
_LastCascade = -2;
var cascadeIdx = 0;
var componentIdx = 0;
var outputIdx = 0;
_CascadeParameters[0]._StartIndex = 0;
// Seek forward to first wavelength that is big enough to render into current cascades
var minWl = MinWavelength(cascadeIdx);
while (componentIdx < _Wavelengths.Length && _Wavelengths[componentIdx] < minWl)
{
componentIdx++;
}
//Debug.Log($"Crest: {cascadeIdx}: start {_cascadeParams[cascadeIdx]._startIndex} minWL {minWl}");
for (; componentIdx < _Wavelengths.Length; componentIdx++)
{
// Skip small amplitude waves
while (componentIdx < _Wavelengths.Length && _Amplitudes[componentIdx] < 0.001f)
{
componentIdx++;
}
if (componentIdx >= _Wavelengths.Length) break;
// Check if we need to move to the next cascade
while (cascadeIdx < k_CascadeCount && _Wavelengths[componentIdx] >= 2f * minWl)
{
// Wrap up this cascade and begin next
// Fill remaining elements of current vector4 with 0s
var vi = outputIdx / 4;
var ei = outputIdx - vi * 4;
while (ei != 0)
{
_WaveData[vi]._TwoPiOverWavelength[ei] = 1f;
_WaveData[vi]._Amplitude[ei] = 0f;
_WaveData[vi]._WaveDirectionX[ei] = 0f;
_WaveData[vi]._WaveDirectionZ[ei] = 0f;
_WaveData[vi]._Omega[ei] = 0f;
_WaveData[vi]._Phase[ei] = 0f;
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._ChopAmplitude[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
ei = (ei + 1) % 4;
outputIdx++;
}
if (outputIdx > 0 && _FirstCascade < 0) _FirstCascade = cascadeIdx;
cascadeIdx++;
_CascadeParameters[cascadeIdx]._StartIndex = outputIdx / 4;
minWl *= 2f;
//Debug.Log($"Crest: {cascadeIdx}: start {_cascadeParams[cascadeIdx]._startIndex} minWL {minWl}");
}
if (cascadeIdx == k_CascadeCount) break;
{
// Pack into vector elements
var vi = outputIdx / 4;
var ei = outputIdx - vi * 4;
_WaveData[vi]._Amplitude[ei] = _Amplitudes[componentIdx];
_WaveData[vi]._Amplitude2[ei] = _Amplitudes2[componentIdx];
var chopScale = _ActiveSpectrum._ChopScales[componentIdx / _ComponentsPerOctave];
_WaveData[vi]._ChopAmplitude[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes[componentIdx];
_WaveData[vi]._ChopAmplitude2[ei] = -chopScale * _ActiveSpectrum._Chop * _Amplitudes2[componentIdx];
var angle = Mathf.Deg2Rad * _AngleDegrees[componentIdx];
var dx = Mathf.Cos(angle);
var dz = Mathf.Sin(angle);
var gravityScale = _ActiveSpectrum._GravityScales[componentIdx / _ComponentsPerOctave];
var gravity = water.Gravity * _ActiveSpectrum._GravityScale;
var c = Mathf.Sqrt(_Wavelengths[componentIdx] * gravity * gravityScale * _ReciprocalTwoPi);
var k = _TwoPi / _Wavelengths[componentIdx];
// Constrain wave vector (wavelength and wave direction) to ensure wave tiles across domain
{
var kx = k * dx;
var kz = k * dz;
var diameter = 0.5f * (1 << cascadeIdx);
// Number of times wave repeats across domain in x and z
var n = kx / (_TwoPi / diameter);
var m = kz / (_TwoPi / diameter);
// Ensure the wave repeats an integral number of times across domain
kx = _TwoPi * Mathf.Round(n) / diameter;
kz = _TwoPi * Mathf.Round(m) / diameter;
// Compute new wave vector and direction
k = Mathf.Sqrt(kx * kx + kz * kz);
dx = kx / k;
dz = kz / k;
}
_WaveData[vi]._TwoPiOverWavelength[ei] = k;
_WaveData[vi]._WaveDirectionX[ei] = dx;
_WaveData[vi]._WaveDirectionZ[ei] = dz;
// Repeat every 2pi to keep angle bounded - helps precision on 16bit platforms
_WaveData[vi]._Omega[ei] = k * c;
_WaveData[vi]._Phase[ei] = Mathf.Repeat(_Phases[componentIdx], Mathf.PI * 2f);
_WaveData[vi]._Phase2[ei] = Mathf.Repeat(_Phases2[componentIdx], Mathf.PI * 2f);
outputIdx++;
}
}
_LastCascade = isFilterable ? cascadeIdx : k_CascadeCount - 1;
{
// Fill remaining elements of current vector4 with 0s
var vi = outputIdx / 4;
var ei = outputIdx - vi * 4;
while (ei != 0)
{
_WaveData[vi]._TwoPiOverWavelength[ei] = 1f;
_WaveData[vi]._Amplitude[ei] = 0f;
_WaveData[vi]._WaveDirectionX[ei] = 0f;
_WaveData[vi]._WaveDirectionZ[ei] = 0f;
_WaveData[vi]._Omega[ei] = 0f;
_WaveData[vi]._Phase[ei] = 0f;
_WaveData[vi]._Phase2[ei] = 0f;
_WaveData[vi]._ChopAmplitude[ei] = 0f;
_WaveData[vi]._Amplitude2[ei] = 0f;
_WaveData[vi]._ChopAmplitude2[ei] = 0f;
ei = (ei + 1) % 4;
outputIdx++;
}
}
while (cascadeIdx < k_CascadeCount)
{
cascadeIdx++;
minWl *= 2f;
_CascadeParameters[cascadeIdx]._StartIndex = outputIdx / 4;
//Debug.Log($"Crest: {cascadeIdx}: start {_cascadeParams[cascadeIdx]._startIndex} minWL {minWl}");
}
_BufferCascadeParameters.SetData(_CascadeParameters);
_BufferWaveData.SetData(_WaveData);
}
void UpdateGenerateWaves(CommandBuffer buf)
{
// Clear existing waves or they could get copied.
buf.SetRenderTarget(_WaveBuffers, 0, CubemapFace.Unknown, -1);
buf.ClearRenderTarget(RTClearFlags.Color, Color.black, 0, 0);
buf.SetComputeFloatParam(_ShaderGerstner, ShaderIDs.s_TextureRes, _WaveBuffers.width);
buf.SetComputeIntParam(_ShaderGerstner, ShaderIDs.s_FirstCascadeIndex, _FirstCascade);
buf.SetComputeBufferParam(_ShaderGerstner, _KernelGerstner, ShaderIDs.s_CascadeParams, _BufferCascadeParameters);
buf.SetComputeBufferParam(_ShaderGerstner, _KernelGerstner, ShaderIDs.s_GerstnerWaveData, _BufferWaveData);
buf.SetComputeTextureParam(_ShaderGerstner, _KernelGerstner, ShapeWaves.ShaderIDs.s_WaveBuffer, _WaveBuffers);
buf.DispatchCompute(_ShaderGerstner, _KernelGerstner, _WaveBuffers.width / Lod.k_ThreadGroupSizeX, _WaveBuffers.height / Lod.k_ThreadGroupSizeY, _LastCascade - _FirstCascade + 1);
}
/// <summary>
/// Resamples wave spectrum
/// </summary>
/// <param name="water">The water renderer.</param>
/// <param name="windSpeed">Wind speed in m/s</param>
void UpdateWaveData(WaterRenderer water, float windSpeed)
{
// Set random seed to get repeatable results
var randomStateBkp = Random.state;
Random.InitState(_RandomSeed);
_ActiveSpectrum.GenerateWaveData(_ComponentsPerOctave, ref _Wavelengths, ref _AngleDegrees);
UpdateAmplitudes();
// Won't run every time so put last in the random sequence
if (_Phases == null || _Phases.Length != _Wavelengths.Length || _Phases2 == null || _Phases2.Length != _Wavelengths.Length)
{
InitPhases();
}
Random.state = randomStateBkp;
SliceUpWaves(water, windSpeed);
}
void UpdateAmplitudes()
{
if (_Amplitudes == null || _Amplitudes.Length != _Wavelengths.Length)
{
_Amplitudes = new float[_Wavelengths.Length];
}
if (_Amplitudes2 == null || _Amplitudes2.Length != _Wavelengths.Length)
{
_Amplitudes2 = new float[_Wavelengths.Length];
}
if (_Powers == null || _Powers.Length != _Wavelengths.Length)
{
_Powers = new float[_Wavelengths.Length];
}
var windSpeed = WindSpeedMPS;
for (var i = 0; i < _Wavelengths.Length; i++)
{
var amp = _ActiveSpectrum.GetAmplitude(_Wavelengths[i], _ComponentsPerOctave, windSpeed, out _Powers[i]);
_Amplitudes[i] = Random.value * amp;
_Amplitudes2[i] = Random.value * amp * _ReverseWaveWeight;
}
}
void InitPhases()
{
// Set random seed to get repeatable results
var randomStateBkp = Random.state;
Random.InitState(_RandomSeed);
var totalComps = _ComponentsPerOctave * WaveSpectrum.k_NumberOfOctaves;
_Phases = new float[totalComps];
_Phases2 = new float[totalComps];
for (var octave = 0; octave < WaveSpectrum.k_NumberOfOctaves; octave++)
{
for (var i = 0; i < _ComponentsPerOctave; i++)
{
var index = octave * _ComponentsPerOctave + i;
var rnd = (i + Random.value) / _ComponentsPerOctave;
_Phases[index] = 2f * Mathf.PI * rnd;
var rnd2 = (i + Random.value) / _ComponentsPerOctave;
_Phases2[index] = 2f * Mathf.PI * rnd2;
}
}
Random.state = randomStateBkp;
}
private protected override void ReportMaxDisplacement(WaterRenderer water)
{
if (!Enabled) return;
if (_ActiveSpectrum._ChopScales.Length != WaveSpectrum.k_NumberOfOctaves)
{
Debug.LogError($"Crest: {nameof(WaveSpectrum)} {_ActiveSpectrum.name} is out of date, please open this asset and resave in editor.", _ActiveSpectrum);
}
if (_Wavelengths == null)
{
return;
}
var ampSum = 0f;
for (var i = 0; i < _Wavelengths.Length; i++)
{
ampSum += _Amplitudes[i] * _ActiveSpectrum._ChopScales[i / _ComponentsPerOctave];
}
// Apply weight or will cause popping due to scale change.
ampSum *= Weight;
MaximumReportedHorizontalDisplacement = ampSum * _ActiveSpectrum._Chop;
MaximumReportedVerticalDisplacement = ampSum;
MaximumReportedWavesDisplacement = ampSum;
if (Mode == LodInputMode.Global)
{
water.ReportMaximumDisplacement(ampSum * _ActiveSpectrum._Chop, ampSum, ampSum);
}
}
private protected override void Initialize()
{
base.Initialize();
s_Instances.Add(transform.GetSiblingIndex(), this);
}
private protected override void OnDisable()
{
base.OnDisable();
s_Instances.Remove(this);
if (_BufferCascadeParameters != null && _BufferCascadeParameters.IsValid())
{
_BufferCascadeParameters.Dispose();
_BufferCascadeParameters = null;
}
if (_BufferWaveData != null && _BufferWaveData.IsValid())
{
_BufferWaveData.Dispose();
_BufferWaveData = null;
}
if (_WaveBuffers != null)
{
Helpers.Destroy(_WaveBuffers);
_WaveBuffers = null;
}
}
private protected override void DestroySharedResources() { }
#if UNITY_EDITOR
void OnGUI()
{
if (_DrawSlicesInEditor && _WaveBuffers != null && _WaveBuffers.IsCreated())
{
DebugGUI.DrawTextureArray(_WaveBuffers, 8, 0.5f);
}
}
#endif
}
partial class ShapeGerstner : ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
#pragma warning disable 414
int _Version = 1;
#pragma warning restore 414
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
_Version = MigrateV1(_Version);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
// Empty.
}
}
}

Some files were not shown because too many files have changed in this diff Show More