This commit is contained in:
zhangjiajia
2026-05-06 16:56:59 +08:00
parent 575626d3e1
commit 81ffaaeca6
1373 changed files with 145920 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace WaveHarmonic.Crest
{
partial class Meniscus
{
internal const string k_MaterialPath = "Packages/com.waveharmonic.crest/Runtime/Materials/Meniscus.mat";
internal void Reset()
{
_Material = AssetDatabase.LoadAssetAtPath<Material>(k_MaterialPath);
}
[@OnChange]
void OnChange(string path, object previous)
{
switch (path)
{
case nameof(_Enabled): SetEnabled((bool)previous, _Enabled); break;
case nameof(_Material): SetMaterial((Material)previous, _Material); break;
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,88 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#if d_UnityHDRP
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
namespace WaveHarmonic.Crest
{
partial class Meniscus
{
internal sealed class MeniscusRendererHDRP : MeniscusRenderer
{
const string k_Name = "Meniscus";
MeniscusCustomPass _CustomPass;
GameObject _GameObject;
public MeniscusRendererHDRP(WaterRenderer water, Meniscus meniscus) : base(water, meniscus)
{
}
public override void Enable()
{
base.Enable();
_GameObject = CustomPassHelpers.CreateOrUpdate
(
parent: _Water.Container.transform,
k_Name,
hide: !_Water._Debug._ShowHiddenObjects
);
CustomPassHelpers.CreateOrUpdate
(
_GameObject,
ref _CustomPass,
k_Draw,
CustomPassInjectionPoint.BeforePostProcess,
priority: -1
);
_CustomPass._Renderer = this;
}
public override void Disable()
{
base.Disable();
if (_GameObject != null)
{
// Will also trigger Cleanup below.
_GameObject.SetActive(false);
}
}
public override void OnBeginCameraRendering(Camera camera)
{
}
public override void OnEndCameraRendering(Camera camera)
{
}
sealed class MeniscusCustomPass : CustomPass
{
internal MeniscusRenderer _Renderer;
protected override void Execute(CustomPassContext context)
{
var camera = context.hdCamera.camera;
if (!_Renderer.ShouldExecute(camera))
{
return;
}
_Renderer.Execute(camera, new CommandWrapper(context.cmd));
}
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,57 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
using UnityEngine.Rendering;
namespace WaveHarmonic.Crest
{
partial class Meniscus
{
internal sealed class MeniscusRendererBIRP : MeniscusRenderer
{
CommandBuffer _Commands;
// NOTE: This will not work for recursive rendering.
bool _CommandsRegistered;
public MeniscusRendererBIRP(WaterRenderer water, Meniscus meniscus) : base(water, meniscus)
{
}
public override void OnBeginCameraRendering(Camera camera)
{
if (!ShouldExecute(camera))
{
return;
}
_Commands ??= new()
{
name = k_Draw,
};
_Commands.Clear();
Execute(camera, new CommandWrapper(_Commands));
camera.AddCommandBuffer(CameraEvent.AfterForwardAlpha, _Commands);
_CommandsRegistered = true;
}
public override void OnEndCameraRendering(Camera camera)
{
if (!_CommandsRegistered)
{
return;
}
camera.RemoveCommandBuffer(CameraEvent.AfterForwardAlpha, _Commands);
_CommandsRegistered = false;
}
}
}
}

View File

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

View File

@@ -0,0 +1,118 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
#if d_UnityURP
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace WaveHarmonic.Crest
{
partial class Meniscus
{
internal sealed class MeniscusRendererURP : MeniscusRenderer
{
readonly MeniscusRenderPass _MaskRenderPass = new();
public MeniscusRendererURP(WaterRenderer water, Meniscus meniscus) : base(water, meniscus)
{
}
public override void OnBeginCameraRendering(Camera camera)
{
if (!ShouldExecute(camera))
{
return;
}
_MaskRenderPass._Renderer = this;
_MaskRenderPass.EnqueuePass(camera);
}
public override void OnEndCameraRendering(Camera camera)
{
}
sealed partial class MeniscusRenderPass : ScriptableRenderPass
{
const string k_Name = k_Draw;
internal MeniscusRenderer _Renderer;
bool _RequiresOpaqueTexture;
public MeniscusRenderPass()
{
renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
}
internal void EnqueuePass(Camera camera)
{
// TODO: check if we need to even enqueue a pass
var renderer = camera.GetUniversalAdditionalCameraData().scriptableRenderer;
#if UNITY_EDITOR
if (renderer == null)
{
return;
}
#endif
_RequiresOpaqueTexture = _Renderer._Meniscus.RequiresOpaqueTexture;
ConfigureInput(_RequiresOpaqueTexture ? ScriptableRenderPassInput.Color : ScriptableRenderPassInput.None);
// Enqueue the pass. This happens every frame.
renderer.EnqueuePass(this);
}
#if UNITY_6000_0_OR_NEWER
class PassData
{
public UniversalCameraData _CameraData;
public MeniscusRenderer _Renderer;
}
public override void RecordRenderGraph(UnityEngine.Rendering.RenderGraphModule.RenderGraph graph, ContextContainer frame)
{
using (var builder = graph.AddRasterRenderPass<PassData>(k_Name, out var data))
{
builder.AllowPassCulling(false);
var resources = frame.Get<UniversalResourceData>();
if (_RequiresOpaqueTexture)
{
builder.UseTexture(resources.cameraOpaqueTexture);
}
data._CameraData = frame.Get<UniversalCameraData>();
data._Renderer = _Renderer;
builder.SetRenderAttachment(resources.activeColorTexture, index: 0);
builder.SetRenderFunc<PassData>((data, context) =>
{
data._Renderer.Execute(data._CameraData.camera, new RasterCommandWrapper(context.cmd));
});
}
}
[System.Obsolete]
#endif
public override void Execute(ScriptableRenderContext context, ref RenderingData data)
{
var buffer = CommandBufferPool.Get(k_Name);
_Renderer.Execute(data.cameraData.camera, new CommandWrapper(buffer));
context.ExecuteCommandBuffer(buffer);
CommandBufferPool.Release(buffer);
}
}
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,234 @@
// Crest Water System
// Copyright © 2024 Wave Harmonic. All rights reserved.
using UnityEngine;
namespace WaveHarmonic.Crest
{
/// <summary>
/// Renders the meniscus (waterline).
/// </summary>
[System.Serializable]
public sealed partial class Meniscus
{
[@Space(10)]
[Tooltip("Whether the meniscus is enabled.")]
[@GenerateAPI(Getter.Custom, Setter.Custom)]
[@DecoratedField]
[SerializeField]
internal bool _Enabled = true;
[Tooltip("Any camera with this layer in its culling mask will render the meniscus.")]
[@Layer]
[@GenerateAPI]
[SerializeField]
int _Layer = 4; // Water
[Tooltip("The meniscus material.")]
[@AttachMaterialEditor(order: 2)]
[@MaterialField("Crest/Meniscus", name: "Meniscus", title: "Create Meniscus Material")]
[@GenerateAPI(Setter.Custom)]
[SerializeField]
internal Material _Material;
WaterRenderer _Water;
internal MeniscusRenderer Renderer { get; private set; }
internal bool RequiresOpaqueTexture => Enabled && Material != null && Material.IsKeywordEnabled("d_Crest_Refraction");
/// <summary>
/// Disables rendering without de-allocating.
/// </summary>
public bool ForceRenderingOff { get; set; }
internal void Enable()
{
Initialize(_Water);
Renderer?.Enable();
}
internal void Disable()
{
Renderer?.Disable();
}
internal void Destroy()
{
Renderer?.Destroy();
Renderer = null;
}
internal void OnActiveRenderPipelineTypeChanged()
{
Destroy();
Initialize(_Water);
}
internal void Initialize(WaterRenderer water)
{
_Water = water;
if (!Enabled)
{
return;
}
#if d_UnityHDRP
if (RenderPipelineHelper.IsHighDefinition)
{
Renderer ??= new MeniscusRendererHDRP(water, this);
}
else
#endif
#if d_UnityURP
if (RenderPipelineHelper.IsUniversal)
{
Renderer ??= new MeniscusRendererURP(water, this);
}
else
#endif
// Legacy
{
Renderer ??= new MeniscusRendererBIRP(water, this);
}
}
}
// Getters/Setters
partial class Meniscus
{
bool GetEnabled()
{
return _Enabled && _Material != null;
}
void SetEnabled(bool previous, bool current)
{
if (previous == current) return;
if (_Water == null || !_Water.isActiveAndEnabled) return;
if (_Enabled) Enable(); else Disable();
}
void SetMaterial(Material previous, Material current)
{
if (previous == current) return;
if (_Water == null || !_Water.isActiveAndEnabled) return;
if (previous == null) Enable(); else if (current == null) Disable();
}
}
partial class Meniscus
{
internal abstract partial class MeniscusRenderer
{
private protected const string k_Draw = "Crest.DrawWater/Meniscus";
private protected readonly WaterRenderer _Water;
internal readonly Meniscus _Meniscus;
static partial class ShaderIDs
{
public static readonly int s_HorizonNormal = Shader.PropertyToID("_Crest_HorizonNormal");
}
public abstract void OnBeginCameraRendering(Camera camera);
public abstract void OnEndCameraRendering(Camera camera);
public MeniscusRenderer(WaterRenderer water, Meniscus meniscus)
{
_Water = water;
_Meniscus = meniscus;
}
public virtual void Enable()
{
}
public virtual void Disable()
{
}
public virtual void Destroy()
{
}
internal bool ShouldExecute(Camera camera)
{
#if UNITY_EDITOR
if (GL.wireframe)
{
return false;
}
#endif
if (_Meniscus.ForceRenderingOff)
{
return false;
}
// Meniscus is a product of the water surface.
if (!_Water.Surface.Enabled)
{
return false;
}
if (camera.cameraType is not CameraType.Game and not CameraType.SceneView)
{
return false;
}
if (!WaterRenderer.ShouldRender(camera, _Meniscus.Layer))
{
return false;
}
#if d_CrestPortals
if (_Water.Portals.Active)
{
// Near surface check not compatible with portals.
return true;
}
#endif
_Water.UpdatePerCameraHeight(camera);
// Only execute if near the surface.
if (_Water._ViewerHeightAboveWaterPerCamera is > 2f or < -8f)
{
return false;
}
return true;
}
internal void Execute<T>(Camera camera, T commands) where T : ICommandWrapper
{
// Project water normal onto camera plane.
_Meniscus.Material.SetVector(ShaderIDs.s_HorizonNormal, new Vector2
(
Vector3.Dot(Vector3.up, camera.transform.right),
Vector3.Dot(Vector3.up, camera.transform.up)
));
#if d_CrestPortals
if (_Water.Portals.Active && !(_Water.Underwater.UseLegacyMask && _Water._Portals.Mode == Portals.PortalMode.Tunnel))
{
_Water._Portals.RenderMeniscus(commands, _Meniscus.Material);
}
else
#endif
{
commands.DrawFullScreenTriangle(_Meniscus.Material, pass: _Water._Underwater.UseLegacyMask ? 4 : 0);
}
}
}
}
}

View File

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