升级6.4.升级水,升级天气

This commit is contained in:
2026-04-05 00:26:54 +08:00
parent 63bc9b5536
commit 5f7cbfb713
635 changed files with 34718 additions and 22567 deletions

View File

@@ -10,7 +10,7 @@ using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering.Universal;
using WaveHarmonic.Crest.Internal;
#if !UNITY_2023_2_OR_NEWER
#if !UNITY_6000_0_OR_NEWER
using GraphicsFormatUsage = UnityEngine.Experimental.Rendering.FormatUsage;
#endif
@@ -21,18 +21,6 @@ namespace WaveHarmonic.Crest
/// </summary>
static partial class Helpers
{
// Adapted from:
// Packages/com.unity.render-pipelines.universal/Runtime/UniversalRenderer.cs
#if UNITY_SWITCH || UNITY_ANDROID || UNITY_EMBEDDED_LINUX || UNITY_QNX
internal const GraphicsFormat k_DepthStencilFormat = GraphicsFormat.D24_UNorm_S8_UInt;
internal const int k_DepthBufferBits = 24;
internal const DepthBits k_DepthBits = DepthBits.Depth24;
#else
internal const GraphicsFormat k_DepthStencilFormat = GraphicsFormat.D32_SFloat_S8_UInt;
internal const int k_DepthBufferBits = 32;
internal const DepthBits k_DepthBits = DepthBits.Depth32;
#endif
public static class ShaderIDs
{
public static readonly int s_MainTexture = Shader.PropertyToID("_Utility_MainTexture");
@@ -92,6 +80,24 @@ namespace WaveHarmonic.Crest
return result != 0 ? result : 1;
}
public static Object[] FindObjectsByType(System.Type type, FindObjectsInactive inactive = FindObjectsInactive.Exclude)
{
#if UNITY_6000_4_OR_NEWER
return Object.FindObjectsByType(type, inactive);
#else
return Object.FindObjectsByType(type, inactive, FindObjectsSortMode.None);
#endif
}
public static T[] FindObjectsByType<T>(FindObjectsInactive inactive = FindObjectsInactive.Exclude) where T : Object
{
#if UNITY_6000_4_OR_NEWER
return Object.FindObjectsByType<T>(inactive);
#else
return Object.FindObjectsByType<T>(inactive, FindObjectsSortMode.None);
#endif
}
static Vector2Int CalculateResolution(Vector2 resolution, int maximum)
{
// Enforce maximum and scale to maintain aspect ratio.
@@ -138,8 +144,17 @@ namespace WaveHarmonic.Crest
return (T)System.Attribute.GetCustomAttribute(type, typeof(T));
}
/// <inheritdoc cref="UnityEngine.WaitForEndOfFrame"/>
/// <remarks>
/// Does not work in batch mode or with the scene view.
/// </remarks>
public static WaitForEndOfFrame WaitForEndOfFrame { get; } = new();
public static float Fmod(float x, float y)
{
return x - y * (float)System.Math.Truncate(x / y);
}
// Taken from:
// https://github.com/Unity-Technologies/Graphics/blob/871df5563d88e1ba778c82a43f39c9afc95368e6/Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl#L1149-L1152
// Z buffer to linear 0..1 depth (0 at camera position, 1 at far plane).
@@ -374,6 +389,16 @@ namespace WaveHarmonic.Crest
return mask == (mask | (1 << layer));
}
// https://docs.unity3d.com/6000.3/Documentation/Manual/WebGPU-limitations.html
public static bool IsWebGPU =>
#if UNITY_6000_0_OR_NEWER
SystemInfo.graphicsDeviceType is GraphicsDeviceType.WebGPU;
#else
false;
#endif
public static bool RequiresCustomClear => IsWebGPU || Application.platform == RuntimePlatform.PS5;
// R16G16B16A16_SFloat appears to be the most compatible format.
// https://docs.unity3d.com/Manual/class-TextureImporterOverride.html#texture-compression-support-platforms
// https://learn.microsoft.com/en-us/windows/win32/direct3d12/typed-unordered-access-view-loads#supported-formats-and-api-calls
@@ -386,10 +411,44 @@ namespace WaveHarmonic.Crest
&& SystemInfo.SupportsRandomWriteOnRenderTextureFormat(rtFormat);
}
static GraphicsFormat GetWebGPUTextureFormat(GraphicsFormat format)
{
// WebGPU is very limited in format usage - especially read-write.
return GraphicsFormatUtility.GetComponentCount(format) switch
{
1 => GraphicsFormat.R32_SFloat,
_ => GraphicsFormat.R32G32B32A32_SFloat,
};
}
internal static readonly GraphicsFormatUsage s_DataGraphicsFormatUsage =
// Ensures a non compressed format is returned. This is a prerequisite for random
// write, but not random write itself according to a dubious comment in the
// Graphics repository. Search UUM-91313.
GraphicsFormatUsage.LoadStore |
// All these textures are sampled at some point.
GraphicsFormatUsage.Sample |
// Always use linear filtering.
GraphicsFormatUsage.Linear;
internal static GraphicsFormat GetCompatibleTextureFormat(GraphicsFormat format, GraphicsFormatUsage usage, string label, bool randomWrite = false)
{
var result = SystemInfo.GetCompatibleFormat(format, usage);
var useFallback = result == GraphicsFormat.None;
var isMetal = GraphicsDeviceType.Metal == SystemInfo.graphicsDeviceType;
#if CREST_DISABLE_PLATFORM_RTFORMAT_OVERRIDES
isMetal = false;
#endif
#if !UNITY_6000_0_OR_NEWER
// Weird bug on macOS where unknown format is returned, but it is really the same
// as the input (R32G32B32A32_SFloat).
if (isMetal && (int)result == 89)
{
result = GraphicsFormat.R32G32B32A32_SFloat;
}
#endif
#if CREST_DEBUG_LOG_FORMAT_CHANGES
if (useFallback)
@@ -402,29 +461,57 @@ namespace WaveHarmonic.Crest
}
#endif
// NOTE: Disabling for now. RenderTextureFormat is a subset of GraphicsFormat and
// there is not always an equivalent.
// if (!useFallback && randomWrite && !SupportsRandomWriteOnRenderTextureFormat(result))
// {
// Debug.Log($"Crest: The graphics device does not support the render texture format {result} with random read/write. Will attempt to use fallback.");
// useFallback = true;
// }
#if !CREST_DISABLE_RANDOMWRITE_CHECK
// Metal will return false for any two channel texture, as per the below link, but
// they work without issue. Lets trust the API, but only for other platforms.
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
if (!isMetal && !useFallback && randomWrite && !SupportsRandomWriteOnRenderTextureFormat(result))
{
#if CREST_DEBUG_LOG_FORMAT_CHANGES
Debug.Log($"Crest: The graphics device does not support the render texture format {result} with random read/write. Will attempt to use fallback. ({label})");
#endif
useFallback = true;
}
#endif
#if CREST_DEBUG_LOG_FORMAT_CHANGES
// Check if fallback is compatible before using it.
if (useFallback && format == s_FallbackGraphicsFormat)
{
Debug.Log($"Crest: Fallback {s_FallbackGraphicsFormat} is not supported on this device. Please inform us. ({label})");
useFallback = false;
Debug.Log($"Crest: Fallback {s_FallbackGraphicsFormat} is not supported on this device. This may be a false positive. Please inform us if you have any issues. ({label})");
}
#endif
if (useFallback)
{
result = s_FallbackGraphicsFormat;
}
#if !CREST_DISABLE_PLATFORM_RTFORMAT_OVERRIDES
if (randomWrite && IsWebGPU)
{
// Pass the requested format otherwise GetCompatibleFormat may change the component
// count which we need to pick the right format.
result = GetWebGPUTextureFormat(format);
}
#endif
return result;
}
public static GraphicsFormat GetCompatibleTextureFormat(GraphicsFormat format, bool randomWrite)
{
#if !CREST_DISABLE_PLATFORM_RTFORMAT_OVERRIDES
if (randomWrite && IsWebGPU)
{
format = GetWebGPUTextureFormat(format);
}
#endif
return format;
}
public static void SetGlobalKeyword(string keyword, bool enabled)
{
if (enabled)
@@ -711,12 +798,12 @@ namespace WaveHarmonic.Crest
public static bool GetGlobalBoolean(int id)
{
return Shader.GetGlobalInteger(id) == 1;
return Shader.GetGlobalFloat(id) != 0f;
}
public static void SetGlobalBoolean(int id, bool value)
{
Shader.SetGlobalInteger(id, value ? 1 : 0);
Shader.SetGlobalFloat(id, value ? 1f : 0f);
}
#if d_UnityURP
@@ -731,6 +818,12 @@ namespace WaveHarmonic.Crest
internal static ScriptableRendererData[] UniversalRendererData(UniversalRenderPipelineAsset asset) =>
(ScriptableRendererData[])s_RenderDataListField.GetValue(asset);
#if UNITY_EDITOR
static readonly System.Type s_PlayModeViewType = typeof(UnityEditor.EditorWindow).Assembly.GetType("UnityEditor.PlayModeView");
static readonly FieldInfo s_RenderingViewField = s_PlayModeViewType.GetField("s_RenderingView", BindingFlags.Static | BindingFlags.NonPublic);
static readonly FieldInfo s_ShowGizmosField = s_PlayModeViewType.GetField("m_ShowGizmos", BindingFlags.NonPublic | BindingFlags.Instance);
#endif
internal static int GetRendererIndex(Camera camera)
{
var rendererIndex = (int)s_RendererIndex.GetValue(camera.GetUniversalAdditionalCameraData());
@@ -760,6 +853,92 @@ namespace WaveHarmonic.Crest
return false;
}
internal static void UniversalRenderCamera(ScriptableRenderContext context, Camera camera, int slice)
{
#if UNITY_EDITOR
// Fixes when using Render Graph:
// Attempting to render to a depth only surface with no dummy color attachment
var sceneView = UnityEditor.SceneView.currentDrawingSceneView;
var drawGizmos = false;
if (sceneView != null)
{
drawGizmos = sceneView.drawGizmos;
sceneView.drawGizmos = false;
}
var gameView = s_RenderingViewField.GetValue(null);
if (gameView != null)
{
drawGizmos = (bool)s_ShowGizmosField.GetValue(gameView);
s_ShowGizmosField.SetValue(gameView, false);
}
#endif
#if UNITY_6000_0_OR_NEWER
// SingleCameraRequest does not render the full camera stack, thus should exclude
// overlays which is likely desirable. Alternative approach worth investigating:
// https://docs.unity3d.com/6000.0/Documentation/Manual/urp/User-Render-Requests.html
// Setting destination silences a warning if Opaque Texture enabled.
s_RenderSingleCameraRequest.destination = camera.targetTexture;
s_RenderSingleCameraRequest.slice = slice;
UnityEngine.Rendering.RenderPipeline.SubmitRenderRequest(camera, s_RenderSingleCameraRequest);
#else
#pragma warning disable CS0618 // Type or member is obsolete
UniversalRenderPipeline.RenderSingleCamera(context, camera);
#pragma warning restore CS0618 // Type or member is obsolete
#endif
#if UNITY_EDITOR
if (sceneView != null)
{
sceneView.drawGizmos = drawGizmos;
}
if (gameView != null)
{
s_ShowGizmosField.SetValue(gameView, drawGizmos);
}
#endif
}
internal static void UniversalRenderCamera(ScriptableRenderContext context, Camera camera, int slice, bool noRenderFeatures)
{
// Get this every time as it could change.
var renderers = (ScriptableRendererData[])s_RenderDataListField.GetValue(UniversalRenderPipeline.asset);
var renderer = (UniversalRendererData)renderers[GetRendererIndex(camera)];
// On Unity 6.3, got exceptions if this was auto with SSAO enabled.
var safe = !noRenderFeatures && renderer.intermediateTextureMode == IntermediateTextureMode.Always;
if (!safe)
{
foreach (var feature in renderer.rendererFeatures)
{
// Null exception reported here. Might be null due to missing render features
if (feature == null) continue;
s_RenderFeatureActiveStates.Add(feature.isActive);
feature.SetActive(false);
}
}
UniversalRenderCamera(context, camera, slice);
if (!safe)
{
var index = 0;
foreach (var feature in renderer.rendererFeatures)
{
if (feature == null) continue;
feature.SetActive(s_RenderFeatureActiveStates[index++]);
}
s_RenderFeatureActiveStates.Clear();
}
}
internal static void RenderCameraWithoutCustomPasses(Camera camera)
{
// Get this every time as it could change.
@@ -791,24 +970,12 @@ namespace WaveHarmonic.Crest
static readonly UnityEngine.Rendering.RenderPipeline.StandardRequest s_RenderStandardRequest = new();
public static void RenderCamera(Camera camera, ScriptableRenderContext context, int slice)
public static void RenderCamera(Camera camera, ScriptableRenderContext context, int slice, bool noRenderFeatures = false)
{
#if d_UnityURP
if (RenderPipelineHelper.IsUniversal)
{
#if UNITY_6000_0_OR_NEWER
// SingleCameraRequest does not render the full camera stack, thus should exclude
// overlays which is likely desirable. Alternative approach worth investigating:
// https://docs.unity3d.com/6000.0/Documentation/Manual/urp/User-Render-Requests.html
// Setting destination silences a warning if Opaque Texture enabled.
s_RenderSingleCameraRequest.destination = camera.targetTexture;
s_RenderSingleCameraRequest.slice = slice;
UnityEngine.Rendering.RenderPipeline.SubmitRenderRequest(camera, s_RenderSingleCameraRequest);
#else
#pragma warning disable CS0618 // Type or member is obsolete
UniversalRenderPipeline.RenderSingleCamera(context, camera);
#pragma warning restore CS0618 // Type or member is obsolete
#endif
UniversalRenderCamera(context, camera, slice, noRenderFeatures);
return;
}
#endif
@@ -894,7 +1061,7 @@ namespace WaveHarmonic.Crest
namespace Internal
{
static class Extensions
static partial class Extensions
{
// Swizzle
public static Vector2 XZ(this Vector3 v) => new(v.x, v.z);
@@ -1003,6 +1170,18 @@ namespace WaveHarmonic.Crest
return GeometryUtility.CalculateBounds(s_BoundsPoints, transform.localToWorldMatrix);
}
public static Bounds Rotate(this Bounds bounds, Quaternion rotation)
{
var center = rotation * bounds.center;
// Rotation each axis separately gets closer to Unity's, but the difference is only
// epsilon in magnitude.
var extents = rotation * bounds.extents * 2f;
// Rotation can produce negatives.
return new(center, new(Mathf.Abs(extents.x), Mathf.Abs(extents.y), Mathf.Abs(extents.z)));
}
public static bool IntersectsXZ(this Bounds a, Bounds b)
{
return a.min.x <= b.max.x && a.max.x >= b.min.x &&
@@ -1083,24 +1262,17 @@ namespace WaveHarmonic.Crest
public static bool GetBoolean(this Material material, int id)
{
return (material.HasInteger(id) ? material.GetInteger(id) : material.GetInt(id)) != 0;
return material.GetFloat(id) != 0f;
}
public static void SetBoolean(this Material material, int id, bool value)
{
if (material.HasInteger(id))
{
material.SetInteger(id, value ? 1 : 0);
}
else
{
material.SetInt(id, value ? 1 : 0);
}
material.SetFloat(id, value ? 1f : 0f);
}
public static void SetGlobalBoolean(this CommandBuffer buffer, int id, bool value)
{
buffer.SetGlobalInteger(id, value ? 1 : 0);
buffer.SetGlobalFloat(id, value ? 1f : 0f);
}
public static bool IsEmpty(this UnityEngine.Events.UnityEvent @event)
@@ -1112,6 +1284,30 @@ namespace WaveHarmonic.Crest
{
return @event.GetPersistentEventCount() == 0;
}
public static bool Encapsulates(this Rect r1, Rect r2)
{
return r1.Contains(r2.min) && r1.Contains(r2.max);
}
}
static partial class Extensions
{
#if !UNITY_6000_3_OR_NEWER
internal static int GetEntityId(this Object @this)
{
return @this.GetInstanceID();
}
#endif
internal static ulong GetRawSceneHandle(this UnityEngine.SceneManagement.Scene @this)
{
#if UNITY_6000_4_OR_NEWER
return @this.handle.GetRawData();
#else
return (ulong)@this.handle;
#endif
}
}
}