升级水插件
This commit is contained in:
@@ -1,161 +1,94 @@
|
||||
// Crest Water System
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
// Built-in Render Pipeline
|
||||
partial class WaterRenderer
|
||||
{
|
||||
internal const string k_DrawWater = "Crest.DrawWater";
|
||||
internal const string k_DrawCopyColor = "CopyColor";
|
||||
internal const string k_DrawCopyDepth = "CopyDepth";
|
||||
|
||||
partial class ShaderIDs
|
||||
{
|
||||
public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture");
|
||||
public static readonly int s_ShadowMapTexture = Shader.PropertyToID("_ShadowMapTexture");
|
||||
public static readonly int s_ScreenSpaceShadowTexture = Shader.PropertyToID("_Crest_ScreenSpaceShadowTexture");
|
||||
public static readonly int s_TemporaryDepthTexture = Shader.PropertyToID("_Crest_TemporaryDepthTexture");
|
||||
public static readonly int s_PrimaryLightHasCookie = Shader.PropertyToID("g_Crest_PrimaryLightHasCookie");
|
||||
|
||||
public static class Unity
|
||||
{
|
||||
public static readonly int s_CameraOpaqueTexture = Shader.PropertyToID("_CameraOpaqueTexture");
|
||||
}
|
||||
}
|
||||
|
||||
CommandBuffer _CopyColorTextureBuffer;
|
||||
RenderTexture _CameraColorTexture;
|
||||
bool _DoneMatrices;
|
||||
|
||||
CommandBuffer _ScreenSpaceShadowMapBuffer;
|
||||
CommandBuffer _DeferredShadowMapBuffer;
|
||||
CommandBuffer _UpdateColorDepthTexturesBuffer;
|
||||
|
||||
internal DefaultFormat LikelyFrameBufferFormat
|
||||
internal Rendering.BIRP.FrameBufferFormatOverride FrameBufferFormatOverride =>
|
||||
!_OverrideRenderHDR
|
||||
? Rendering.BIRP.FrameBufferFormatOverride.None
|
||||
: _RenderHDR
|
||||
? Rendering.BIRP.FrameBufferFormatOverride.HDR
|
||||
: Rendering.BIRP.FrameBufferFormatOverride.LDR;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
static void InitializeOnLoad()
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_OverrideRenderHDR)
|
||||
{
|
||||
return _RenderHDR ? DefaultFormat.HDR : DefaultFormat.LDR;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
var target = UnityEditor.EditorUserBuildSettings.activeBuildTarget;
|
||||
if (target is UnityEditor.BuildTarget.Android or UnityEditor.BuildTarget.iOS or UnityEditor.BuildTarget.tvOS)
|
||||
{
|
||||
return DefaultFormat.LDR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UNITY_ANDROID || UNITY_IOS || UNITY_TVOS
|
||||
return DefaultFormat.LDR;
|
||||
#else
|
||||
return DefaultFormat.HDR;
|
||||
#endif
|
||||
}
|
||||
// Fixes error on first frame.
|
||||
Shader.SetGlobalTexture(Crest.ShaderIDs.Unity.s_ShadowMapTexture, Texture2D.whiteTexture);
|
||||
}
|
||||
|
||||
void OnPreRenderCamera(Camera camera)
|
||||
internal void UpdateMatrices(Camera camera)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UpdateLastActiveSceneCamera(camera);
|
||||
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
OnPreRenderWaterLevelDepthTexture(camera);
|
||||
}
|
||||
#endif
|
||||
|
||||
OnBeginCameraRendering(camera);
|
||||
|
||||
if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer))
|
||||
if (_DoneMatrices)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
XRHelpers.Update(camera);
|
||||
XRHelpers.SetInverseViewProjectionMatrix(camera);
|
||||
Rendering.BIRP.SetMatrices(camera);
|
||||
|
||||
_CopyColorTextureBuffer ??= new() { name = "Crest Copy Color Texture" };
|
||||
_DeferredShadowMapBuffer ??= new() { name = "Crest Deferred Shadow Data" };
|
||||
_ScreenSpaceShadowMapBuffer ??= new() { name = "Crest Screen-Space Shadow Data" };
|
||||
_CopyColorTextureBuffer.Clear();
|
||||
_DeferredShadowMapBuffer.Clear();
|
||||
_ScreenSpaceShadowMapBuffer.Clear();
|
||||
_DoneMatrices = true;
|
||||
}
|
||||
|
||||
// Create or update RT.
|
||||
void OnBeginCameraRenderingLegacy(Camera camera)
|
||||
{
|
||||
if (PrimaryLight == null)
|
||||
{
|
||||
var descriptor = XRHelpers.GetRenderTextureDescriptor(camera);
|
||||
|
||||
// Format must be correct for CopyTexture to work. Hopefully this is good enough.
|
||||
if (camera.allowHDR && QualitySettings.activeColorSpace == ColorSpace.Linear)
|
||||
{
|
||||
descriptor.graphicsFormat = SystemInfo.GetGraphicsFormat(LikelyFrameBufferFormat);
|
||||
}
|
||||
|
||||
// Occurred in a build and caused a black screen.
|
||||
if (descriptor.width <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_CameraColorTexture == null)
|
||||
{
|
||||
_CameraColorTexture = new(descriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
_CameraColorTexture.Release();
|
||||
_CameraColorTexture.descriptor = descriptor;
|
||||
}
|
||||
|
||||
_CameraColorTexture.Create();
|
||||
return;
|
||||
}
|
||||
|
||||
var target = new RenderTargetIdentifier(_CameraColorTexture, 0, CubemapFace.Unknown, -1);
|
||||
|
||||
// Use blit instead of CopyTexture as it will smooth out issues with format
|
||||
// differences which is very hard to get right for BIRP.
|
||||
_CopyColorTextureBuffer.Blit(BuiltinRenderTextureType.CameraTarget, target);
|
||||
_CopyColorTextureBuffer.SetGlobalTexture(ShaderIDs.s_CameraOpaqueTexture, _CameraColorTexture);
|
||||
|
||||
camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CopyColorTextureBuffer);
|
||||
|
||||
if (QualitySettings.shadows != ShadowQuality.Disable && PrimaryLight != null)
|
||||
// Force shadow map to remain for transparent pass and beyond.
|
||||
{
|
||||
_ScreenSpaceShadowMapBuffer ??= new() { name = "Crest.CausticsOcclusion" };
|
||||
_ScreenSpaceShadowMapBuffer.Clear();
|
||||
|
||||
// Make the screen-space shadow texture available for the water shader for caustic occlusion.
|
||||
_ScreenSpaceShadowMapBuffer.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, BuiltinRenderTextureType.CurrentActive);
|
||||
PrimaryLight.AddCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer);
|
||||
// Call this regardless of rendering path as it has no negative consequences for forward.
|
||||
_DeferredShadowMapBuffer.SetGlobalTexture(ShaderIDs.s_ShadowMapTexture, BuiltinRenderTextureType.CurrentActive);
|
||||
PrimaryLight.AddCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer);
|
||||
}
|
||||
|
||||
{
|
||||
// Always set these in case shadow maps are disabled in the graphics settings which
|
||||
// we cannot check at runtime.
|
||||
// Black for shadowed. White for unshadowed.
|
||||
if (camera.stereoEnabled && XRHelpers.IsSinglePass)
|
||||
{
|
||||
Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, XRHelpers.WhiteTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, Texture2D.whiteTexture);
|
||||
}
|
||||
Shader.SetGlobalTexture(ShaderIDs.s_ScreenSpaceShadowTexture, Rendering.BIRP.GetWhiteTexture(camera));
|
||||
}
|
||||
|
||||
Helpers.SetGlobalBoolean(ShaderIDs.s_PrimaryLightHasCookie, PrimaryLight.cookie != null);
|
||||
}
|
||||
|
||||
void OnPostRenderCamera(Camera camera)
|
||||
void OnEndCameraRenderingLegacy(Camera camera)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
OnPostRenderWaterLevelDepthTexture(camera);
|
||||
}
|
||||
#endif
|
||||
_DoneMatrices = false;
|
||||
_DoneCameraOpaqueTexture = false;
|
||||
|
||||
if (!Helpers.MaskIncludesLayer(camera.cullingMask, Layer))
|
||||
if (_UpdateColorDepthTexturesBuffer != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_CopyColorTextureBuffer != null)
|
||||
{
|
||||
camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _CopyColorTextureBuffer);
|
||||
camera.RemoveCommandBuffer(RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha, _UpdateColorDepthTexturesBuffer);
|
||||
}
|
||||
|
||||
if (QualitySettings.shadows != ShadowQuality.Disable && PrimaryLight != null)
|
||||
@@ -164,11 +97,153 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
PrimaryLight.RemoveCommandBuffer(LightEvent.AfterScreenspaceMask, _ScreenSpaceShadowMapBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (_DeferredShadowMapBuffer != null)
|
||||
Shader.SetGlobalTexture(ShaderIDs.Unity.s_CameraOpaqueTexture, Texture2D.grayTexture);
|
||||
}
|
||||
|
||||
// Needs to be separate, as it needs to run after the water volume pass.
|
||||
void OnLegacyCopyPass(Camera camera)
|
||||
{
|
||||
if (!ShouldRender(camera, Surface.Layer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Surface.Material == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SurfaceRenderer.IsTransparent(Surface.Material))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Our reflections do not need them.
|
||||
if (camera == WaterReflections.CurrentCamera)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_UpdateColorDepthTexturesBuffer ??= new() { name = k_DrawWater };
|
||||
_UpdateColorDepthTexturesBuffer.Clear();
|
||||
|
||||
var buffer = _UpdateColorDepthTexturesBuffer;
|
||||
|
||||
if (WriteToColorTexture)
|
||||
{
|
||||
UpdateCameraOpaqueTexture(camera, buffer);
|
||||
}
|
||||
|
||||
if (WriteToDepthTexture && Shader.GetGlobalTexture(Crest.ShaderIDs.Unity.s_CameraDepthTexture) is RenderTexture depthRT)
|
||||
{
|
||||
buffer.BeginSample(k_DrawCopyDepth);
|
||||
|
||||
// There is no way to update the depth texture with the depth buffer, as we cannot
|
||||
// get a reference to it. We have to render water depth separately and then merge
|
||||
// the results.
|
||||
|
||||
var target = new RenderTargetIdentifier(depthRT, 0, CubemapFace.Unknown, -1);
|
||||
|
||||
var id = ShaderIDs.s_TemporaryDepthTexture;
|
||||
|
||||
buffer.GetTemporaryRT(id, depthRT.descriptor);
|
||||
CoreUtils.SetRenderTarget(buffer, id, ClearFlag.Depth);
|
||||
|
||||
Surface.Render(camera, buffer, pass: Surface.Material.FindPass("DepthOnly"), culled: true);
|
||||
|
||||
buffer.SetGlobalTexture(Helpers.ShaderIDs.s_MainTexture, id);
|
||||
|
||||
Helpers.Blit(buffer, target, Rendering.BIRP.UtilityMaterial, (int)Rendering.BIRP.UtilityPass.MergeDepth);
|
||||
|
||||
// TODO: add debug toggle
|
||||
// buffer.Blit(target, BuiltinRenderTextureType.CameraTarget);
|
||||
|
||||
buffer.ReleaseTemporaryRT(id);
|
||||
|
||||
buffer.EndSample(k_DrawCopyDepth);
|
||||
}
|
||||
|
||||
if (WriteToColorTexture || WriteToDepthTexture)
|
||||
{
|
||||
camera.AddCommandBuffer(RenderBeforeTransparency ? CameraEvent.BeforeForwardAlpha : CameraEvent.AfterForwardAlpha, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Camera Opaque Texture.
|
||||
partial class WaterRenderer
|
||||
{
|
||||
bool _DoneCameraOpaqueTexture;
|
||||
RenderTexture _CameraOpaqueTexture;
|
||||
CommandBuffer _CameraOpaqueTextureCommands;
|
||||
|
||||
internal void UpdateCameraOpaqueTexture(Camera camera, CommandBuffer commands)
|
||||
{
|
||||
commands.BeginSample(k_DrawCopyColor);
|
||||
|
||||
var target = new RenderTargetIdentifier(_CameraOpaqueTexture, 0, CubemapFace.Unknown, -1);
|
||||
|
||||
// Use blit instead of CopyTexture as it will smooth out issues with format
|
||||
// differences which is very hard to get right for BIRP.
|
||||
commands.Blit(BuiltinRenderTextureType.CameraTarget, target);
|
||||
|
||||
commands.EndSample(k_DrawCopyColor);
|
||||
}
|
||||
|
||||
internal void OnBeginCameraOpaqueTexture(Camera camera)
|
||||
{
|
||||
if (_DoneCameraOpaqueTexture)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var descriptor = Rendering.BIRP.GetCameraTargetDescriptor(camera, FrameBufferFormatOverride);
|
||||
|
||||
// Occurred in a build and caused a black screen.
|
||||
if (descriptor.width <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_CameraOpaqueTexture == null)
|
||||
{
|
||||
_CameraOpaqueTexture = new(descriptor)
|
||||
{
|
||||
PrimaryLight.RemoveCommandBuffer(LightEvent.AfterShadowMap, _DeferredShadowMapBuffer);
|
||||
}
|
||||
name = "_CameraOpaqueTexture",
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
_CameraOpaqueTexture.Release();
|
||||
_CameraOpaqueTexture.descriptor = descriptor;
|
||||
}
|
||||
|
||||
_CameraOpaqueTexture.Create();
|
||||
|
||||
_CameraOpaqueTextureCommands ??= new()
|
||||
{
|
||||
name = "Crest.DrawWater",
|
||||
};
|
||||
|
||||
_CameraOpaqueTextureCommands.Clear();
|
||||
|
||||
// Do every frame as we set to default texture at end of rendering.
|
||||
_CameraOpaqueTextureCommands.SetGlobalTexture(Crest.ShaderIDs.Unity.s_CameraOpaqueTexture, _CameraOpaqueTexture);
|
||||
|
||||
UpdateCameraOpaqueTexture(camera, _CameraOpaqueTextureCommands);
|
||||
|
||||
camera.AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _CameraOpaqueTextureCommands);
|
||||
|
||||
_DoneCameraOpaqueTexture = true;
|
||||
}
|
||||
|
||||
internal void OnEndCameraOpaqueTexture(Camera camera)
|
||||
{
|
||||
if (_CameraOpaqueTextureCommands != null)
|
||||
{
|
||||
camera.RemoveCommandBuffer(CameraEvent.BeforeForwardAlpha, _CameraOpaqueTextureCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user