移除水
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1dfc7e28d58b14deaa99d95b6ccd0cc5
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59056ec4af44c42dd8f36c6a25eece46
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2985cdff827b8472bafc9e2da18fbf06
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c2709c536afb4bf6b90d29d03758f0d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce5a3f1aff978418c90b45d58f574528
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8c508e8f723e64d21a5219d1530e6ffd
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 120e704899e8944e9baf31404179e7ce
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05822262553744bae9714920130c0899
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a214bb0d815f498aaee2e050a73697f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1131dd19089574b28a35a17f1ea28f32
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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: []
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a561aef740e74d45a7db7b9dc255dd7
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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: []
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fbe311c1027b04a3d8401654d4a9d72f
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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: []
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f5eb7d739bac4dcf97596cc6b192494
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2b096e4d95e646c49d48ece0afa0547
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ab064b6606504a55b489af2787350c2
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77ee3d78b64074b2cba27c3b39c6084a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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}
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 17840562212c147d6bdb5144d35bc442
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfeba4e421ad54be597d83f0638a0c55
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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 { }
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc511f9846b8c404091aace6915510df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5b3ea5ad983894f72b6478985b8238d3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 055e56f78a8f84633baaceee3f56970f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a6548e15197394afb8759ec50e918937
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6e1410b6b6b14d1db0a242b6d4efef5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 71b85abdc5e234fe8a685d3be0b95443
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a52c8c04f6c749d7a2bc6e5a4fbe9ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ed87ea342278349c4885adef619f19cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1bc55489896941859aa8af34f8c1083
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 679dfc1207b124b3fa00496f7b93a5cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fb0d3abd1aa34af8942b9bab09a8575
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37086036dea5b4927a5cdb3af2d5d869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42f3809132d8b485a822f0bb271f51c5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ea9618107d2946a98206ac4c7772029
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e88db203d9474c568c462518871bb5a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51ed544a28b134d58a41f55650e368b7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 247a7260095bc49429a7f7cb2a4851d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c972e8f11f2447768dc0314b7bc34a4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d64d1f50f3b548bcbe279507f0e78da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26623fd0e291a478a9f8b68a3df7e8a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d13f0b872e9454b5daa77afa95b12943
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70deb49b538e247b9ab1bf7773d16809
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 300
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 82638e366ec3c4f5587d1ff63e01d8b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0cdc7659b2c244dbbb625ccd8ae65ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67bc7f0b9724d44ab9f0ddf0b1b5a773
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20184ba74fed44301b1efff21519c308
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 47424a406f7a145f8a8d6c207b7afc60
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 695da60ea6ccf44ea988e843144969cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +0,0 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Intentionally empty.
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc9697a0accb44ec7a0f693182937c94
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4edd034314af4679ba066d79580dc1d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 126e7f9b525874cdbb0653a0f1662e18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a95cc8f7e50c47d8bfdda73f6da338a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0ee0dbacf6784d1a8608ad94109098d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c85179d3b43c5467da99463c8a2199ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fcda6c7640ad44106aa39234017df797
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d7eafa182f969495d9e74b145310c516
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 88bb6e05d83b64105a4d8cbd478f5916
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
Reference in New Issue
Block a user