升级水插件

This commit is contained in:
2026-01-08 22:30:55 +08:00
parent febff82d24
commit ca68084264
415 changed files with 18138 additions and 7134 deletions

View File

@@ -16,21 +16,19 @@ namespace WaveHarmonic.Crest
/// <summary>
/// What side of the water surface to render planar reflections for.
/// </summary>
[@GenerateDoc]
public enum WaterReflectionSide
{
/// <summary>
/// Both sides. Most expensive.
/// </summary>
/// <inheritdoc cref="Generated.WaterReflectionSide.Both"/>
[Tooltip("Both sides. Most expensive.")]
Both,
/// <summary>
/// Above only. Typical for planar reflections.
/// </summary>
/// <inheritdoc cref="Generated.WaterReflectionSide.Above"/>
[Tooltip("Above only. Typical for planar reflections.")]
Above,
/// <summary>
/// Below only. For total internal reflections.
/// </summary>
/// <inheritdoc cref="Generated.WaterReflectionSide.Below"/>
[Tooltip("Below only. For total internal reflections.")]
Below,
}
@@ -269,27 +267,48 @@ namespace WaveHarmonic.Crest
}
}
internal void OnPreRenderCamera(Camera camera)
bool ShouldRender(Camera camera)
{
// If no surface, then do not execute the reflection camera.
if (!WaterRenderer.ShouldRender(camera, _Water.Surface.Layer))
{
return false;
}
// This method could be executed twice: once by the camera rendering the surface,
// and once again by the planar reflection camera. For the latter, we do not want
// to proceed or infinite recursion. For safety.
if (camera == CurrentCamera)
{
return false;
}
// Avoid these types for now.
if (camera.cameraType == CameraType.Reflection)
{
return false;
}
return true;
}
internal void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera)
{
if (!ShouldRender(camera))
{
return;
}
if (SupportsRecursiveRendering)
{
if (camera.cameraType is CameraType.Preview or CameraType.Reflection)
{
return;
}
if (!Helpers.MaskIncludesLayer(camera.cullingMask, _Water.Layer))
{
return;
}
// This option only valid for recursive, otherwise, it is always single camera.
if (_RenderOnlySingleCamera && camera != _Water.Viewer)
{
return;
}
_CameraViewpoint = camera;
LateUpdate();
LateUpdate(context);
}
if (camera == _CameraViewpoint)
@@ -299,13 +318,17 @@ namespace WaveHarmonic.Crest
}
}
internal void OnAfterCameraRender(Camera camera)
internal void OnEndCameraRendering(Camera camera)
{
if (SupportsRecursiveRendering && !_RenderOnlySingleCamera) return;
if (!ShouldRender(camera))
{
return;
}
Shader.SetGlobalTexture(ShaderIDs.s_ReflectionTexture, Texture2D.blackTexture);
}
internal void LateUpdate()
internal void LateUpdate(ScriptableRenderContext context)
{
// Frame rate limiter.
if (_LastRefreshOnFrame > 0 && RefreshPerFrames > 1)
@@ -362,7 +385,7 @@ namespace WaveHarmonic.Crest
}
// We do not want the water plane when rendering planar reflections.
_Water.Root.gameObject.SetActive(false);
_Water.Surface.Root.gameObject.SetActive(false);
CurrentCamera = _CameraReflections;
@@ -390,7 +413,7 @@ namespace WaveHarmonic.Crest
try
#endif
{
Render();
Render(context);
}
#if UNITY_EDITOR
// Ensure that any global settings are restored.
@@ -414,15 +437,18 @@ namespace WaveHarmonic.Crest
_QualitySettingsOverride.Restore();
CurrentCamera = null;
_Water.Root.gameObject.SetActive(true);
_Water.Surface.Root.gameObject.SetActive(true);
// Remember this frame as last refreshed.
_LastRefreshOnFrame = Time.renderedFrameCount;
}
}
void Render()
void Render(ScriptableRenderContext context)
{
#if UNITY_6000_0_OR_NEWER && d_UnityURP
_CameraReflections.targetTexture = _ReflectionTexture;
#else
var descriptor = _ReflectionTexture.descriptor;
descriptor.dimension = TextureDimension.Tex2D;
descriptor.volumeDepth = 1;
@@ -430,6 +456,7 @@ namespace WaveHarmonic.Crest
// No need to clear, as camera clears using the skybox.
var target = RenderTexture.GetTemporary(descriptor);
_CameraReflections.targetTexture = target;
#endif
if (_Mode != WaterReflectionSide.Below)
{
@@ -441,8 +468,11 @@ namespace WaveHarmonic.Crest
_CameraReflections.cullingMask = _Layers & ~(1 << _UnderWater.Layer);
}
RenderCamera(_CameraReflections, Vector3.up, false);
RenderCamera(context, _CameraReflections, Vector3.up, false, 0);
#if !(UNITY_6000_0_OR_NEWER && d_UnityURP)
Graphics.CopyTexture(target, 0, 0, _ReflectionTexture, 0, 0);
#endif
_CameraReflections.ResetProjectionMatrix();
}
@@ -459,29 +489,33 @@ namespace WaveHarmonic.Crest
_CameraReflections.depthTextureMode = DepthTextureMode.Depth;
}
RenderCamera(_CameraReflections, Vector3.down, _NonObliqueNearSurface);
RenderCamera(context, _CameraReflections, Vector3.down, _NonObliqueNearSurface, 1);
#if !(UNITY_6000_0_OR_NEWER && d_UnityURP)
Graphics.CopyTexture(target, 0, 0, _ReflectionTexture, 1, 0);
#endif
_CameraReflections.ResetProjectionMatrix();
}
#if !(UNITY_6000_0_OR_NEWER && d_UnityURP)
RenderTexture.ReleaseTemporary(target);
#endif
_ReflectionTexture.GenerateMips();
Shader.SetGlobalVectorArray(ShaderIDs.s_ReflectionPositionNormal, _ReflectionPositionNormal);
}
void RenderCamera(Camera camera, Vector3 planeNormal, bool nonObliqueNearSurface)
void RenderCamera(ScriptableRenderContext context, Camera camera, Vector3 planeNormal, bool nonObliqueNearSurface, int slice)
{
// Find out the reflection plane: position and normal in world space
var planePosition = _Water.Root.position;
var planePosition = _Water.Position;
var offset = _ClipPlaneOffset;
{
var viewpoint = _CameraViewpoint.transform;
if (offset == 0f && viewpoint.position.y == 0f && viewpoint.rotation.eulerAngles.y == 0f)
if (offset == 0f && viewpoint.position.y == planePosition.y)
{
// Minor offset to prevent "Screen position out of view frustum". Smallest number
// to work with both above and below. Smallest number to work with both above and
@@ -518,7 +552,7 @@ namespace WaveHarmonic.Crest
if (SupportsRecursiveRendering)
{
Helpers.RenderCamera(camera, _Water._Context);
Helpers.RenderCamera(camera, context, slice);
}
else
{