升级水插件
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f03dd318ef494ed4793cac667ef2858f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9d8168ffc7eeda4fad34275d57c585d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Shared")]
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9d248516e9d84702a7da49167649f40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"reference": "GUID:df380645f10b7bc4b97d4f5eb6303d95"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a761b4f3cc5b4e468121ec3c51dda5a
|
||||
AssemblyDefinitionReferenceImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -4,3 +4,4 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest")]
|
||||
[assembly: InternalsVisibleTo("WaveHarmonic.Crest.Shared")]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Crest Water System
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using System.Collections;
|
||||
@@ -42,6 +42,16 @@ namespace WaveHarmonic.Crest.Utility
|
||||
_NeedsSorting = true;
|
||||
}
|
||||
|
||||
public bool Contains(TValue value)
|
||||
{
|
||||
foreach (var item in _BackingList)
|
||||
{
|
||||
if (item.Value.Equals(value)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Remove(TValue value)
|
||||
{
|
||||
// This remove function has a fairly high complexity, as we need to search
|
||||
|
||||
@@ -84,6 +84,16 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
[AttributeUsage(AttributeTargets.Enum, AllowMultiple = false, Inherited = false)]
|
||||
sealed class GenerateDoc : Attribute
|
||||
{
|
||||
public GenerateDoc()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#if !UNITY_EDITOR
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
|
||||
@@ -102,12 +112,21 @@ namespace WaveHarmonic.Crest
|
||||
sealed class Disabled : Decorator { }
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class AttachMaterialEditor : Decorator { }
|
||||
sealed class AttachMaterialEditor : Attribute
|
||||
{
|
||||
public AttachMaterialEditor(int order = 0) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class InlineToggle : Decorator
|
||||
{
|
||||
public InlineToggle(bool fix = false) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
sealed class Embedded : Decorator
|
||||
{
|
||||
public Embedded(int margin = 0) { }
|
||||
public Embedded(int margin = 0, string defaultPropertyName = null) { }
|
||||
}
|
||||
|
||||
[Conditional(Symbols.k_UnityEditor)]
|
||||
|
||||
@@ -21,8 +21,13 @@ namespace WaveHarmonic.Crest.Internal
|
||||
bool _IsFirstOnValidate = true;
|
||||
internal bool _IsPrefabStageInstance;
|
||||
|
||||
private protected virtual bool CanRunInEditMode => true;
|
||||
|
||||
private protected virtual void Awake()
|
||||
{
|
||||
// Prevents allocations.
|
||||
useGUILayout = false;
|
||||
|
||||
// When copy and pasting from one scene to another, destroy instance objects as
|
||||
// they will have bad state.
|
||||
foreach (var generated in transform.GetComponentsInChildren<ManagedGameObject>(includeInactive: true))
|
||||
@@ -37,7 +42,7 @@ namespace WaveHarmonic.Crest.Internal
|
||||
/// <summary>
|
||||
/// Start method. Must be called if overriden.
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
private protected virtual void Start()
|
||||
{
|
||||
if (Application.isPlaying && !(bool)s_ExecuteValidators.Invoke(null, new object[] { this }))
|
||||
{
|
||||
@@ -63,6 +68,11 @@ namespace WaveHarmonic.Crest.Internal
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CanRunInEditMode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_IsFirstOnValidate)
|
||||
{
|
||||
var attribute = Helpers.GetCustomAttribute<ExecuteDuringEditMode>(GetType());
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65e84a69730de24458beac07cc1bde92
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest.Utility
|
||||
{
|
||||
static class DebugUtility
|
||||
{
|
||||
public delegate void DrawLine(Vector3 position, Vector3 up, Color color, float duration);
|
||||
|
||||
public static void DrawCross(DrawLine draw, Vector3 position, float r, Color color, float duration = 0f)
|
||||
{
|
||||
draw(position - Vector3.up * r, position + Vector3.up * r, color, duration);
|
||||
draw(position - Vector3.right * r, position + Vector3.right * r, color, duration);
|
||||
draw(position - Vector3.forward * r, position + Vector3.forward * r, color, duration);
|
||||
}
|
||||
|
||||
public static void DrawCross(DrawLine draw, Vector3 position, Vector3 up, float r, Color color, float duration = 0f)
|
||||
{
|
||||
up.Normalize();
|
||||
var right = Vector3.Normalize(Vector3.Cross(up, Vector3.forward));
|
||||
var forward = Vector3.Cross(up, right);
|
||||
draw(position - up * r, position + up * r, color, duration);
|
||||
draw(position - right * r, position + right * r, color, duration);
|
||||
draw(position - forward * r, position + forward * r, color, duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afcafd3203e384a54aa71d2c40f2025c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -21,6 +21,18 @@ 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");
|
||||
@@ -128,31 +140,6 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
public static WaitForEndOfFrame WaitForEndOfFrame { get; } = new();
|
||||
|
||||
static Material s_UtilityMaterial;
|
||||
public static Material UtilityMaterial
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_UtilityMaterial == null)
|
||||
{
|
||||
s_UtilityMaterial = new(Shader.Find("Hidden/Crest/Utility/Blit"));
|
||||
}
|
||||
|
||||
return s_UtilityMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
// Need to cast to int but no conversion cost.
|
||||
// https://stackoverflow.com/a/69148528
|
||||
internal enum UtilityPass
|
||||
{
|
||||
CopyColor,
|
||||
CopyDepth,
|
||||
ClearDepth,
|
||||
ClearStencil,
|
||||
Copy,
|
||||
}
|
||||
|
||||
// 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).
|
||||
@@ -220,15 +207,22 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses PrefabUtility.InstantiatePrefab in editor and GameObject.Instantiate in standalone.
|
||||
/// Uses PrefabUtility.InstantiatePrefab in edit mode, otherwise uses GameObject.Instantiate.
|
||||
/// </summary>
|
||||
public static GameObject InstantiatePrefab(GameObject prefab)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefab);
|
||||
#else
|
||||
return GameObject.Instantiate(prefab);
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
// Previously we always used this in the editor, including play mode. But it was
|
||||
// reported to have failed (null return) when Asset Bundles were used in play mode.
|
||||
return (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(prefab);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return Object.Instantiate(prefab);
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from Unity
|
||||
@@ -343,7 +337,7 @@ namespace WaveHarmonic.Crest
|
||||
if (RenderPipelineHelper.IsUniversal)
|
||||
{
|
||||
// MSAA will be the same for every camera if XR rendering.
|
||||
isMSAA = isMSAA || XRHelpers.IsRunning;
|
||||
isMSAA = isMSAA || Rendering.EnabledXR;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -588,7 +582,7 @@ namespace WaveHarmonic.Crest
|
||||
/// <summary>
|
||||
/// Uses Destroy in play mode or DestroyImmediate in edit mode.
|
||||
/// </summary>
|
||||
public static void Destroy(Object @object)
|
||||
public static void Destroy(Object @object, bool undo = false)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// We must use DestroyImmediate in edit mode. As it apparently has an overhead, use recommended Destroy in
|
||||
@@ -596,7 +590,14 @@ namespace WaveHarmonic.Crest
|
||||
// https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
Object.DestroyImmediate(@object);
|
||||
if (undo)
|
||||
{
|
||||
UnityEditor.Undo.DestroyObjectImmediate(@object);
|
||||
}
|
||||
else
|
||||
{
|
||||
Object.DestroyImmediate(@object);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -605,11 +606,13 @@ namespace WaveHarmonic.Crest
|
||||
}
|
||||
}
|
||||
|
||||
static readonly Matrix4x4 s_ScaleMatrix = Matrix4x4.Scale(new(1f, 1f, -1f));
|
||||
|
||||
// Borrowed from SRP code:
|
||||
// https://github.com/Unity-Technologies/Graphics/blob/7d292932bec3b4257a4defaf698fc7d77e2027f5/com.unity.render-pipelines.high-definition/Runtime/Core/Utilities/GeometryUtils.cs#L181-L184
|
||||
public static Matrix4x4 CalculateWorldToCameraMatrixRHS(Vector3 position, Quaternion rotation)
|
||||
{
|
||||
return Matrix4x4.Scale(new(1, 1, -1)) * Matrix4x4.TRS(position, rotation, Vector3.one).inverse;
|
||||
return s_ScaleMatrix * Matrix4x4.TRS(position, rotation, Vector3.one).inverse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -618,14 +621,7 @@ namespace WaveHarmonic.Crest
|
||||
/// </summary>
|
||||
public static void Blit(CommandBuffer buffer, RenderTargetIdentifier target, Material material, int pass = -1, MaterialPropertyBlock properties = null)
|
||||
{
|
||||
if (!RenderPipelineHelper.IsLegacy)
|
||||
{
|
||||
CoreUtils.SetRenderTarget(buffer, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.SetRenderTarget(target);
|
||||
}
|
||||
CoreUtils.SetRenderTarget(buffer, target);
|
||||
|
||||
buffer.DrawProcedural
|
||||
(
|
||||
@@ -795,7 +791,7 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
static readonly UnityEngine.Rendering.RenderPipeline.StandardRequest s_RenderStandardRequest = new();
|
||||
|
||||
public static void RenderCamera(Camera camera, ScriptableRenderContext context)
|
||||
public static void RenderCamera(Camera camera, ScriptableRenderContext context, int slice)
|
||||
{
|
||||
#if d_UnityURP
|
||||
if (RenderPipelineHelper.IsUniversal)
|
||||
@@ -804,7 +800,9 @@ namespace WaveHarmonic.Crest
|
||||
// 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
|
||||
// TODO: pass destination texture and slice instead of copying later.
|
||||
// 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
|
||||
@@ -828,7 +826,44 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
}
|
||||
|
||||
// Undo
|
||||
static partial class Helpers
|
||||
{
|
||||
public static class Undo
|
||||
{
|
||||
static class Symbols
|
||||
{
|
||||
public const string k_UnityEditor = "UNITY_EDITOR";
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional(Symbols.k_UnityEditor)]
|
||||
public static void RecordObject(Object @object, string label)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.Undo.RecordObject(@object, label);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional(Symbols.k_UnityEditor)]
|
||||
public static void SetSiblingIndex(Transform transform, int index, string label)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.Undo.SetSiblingIndex(transform, index, label);
|
||||
#endif
|
||||
}
|
||||
|
||||
[System.Diagnostics.Conditional(Symbols.k_UnityEditor)]
|
||||
public static void RegisterCreatedObjectUndo(Object @object, string label)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.Undo.RegisterCreatedObjectUndo(@object, label);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Terrain
|
||||
#if d_Unity_Terrain
|
||||
static partial class Helpers
|
||||
{
|
||||
static readonly List<Terrain> s_Terrains = new();
|
||||
@@ -838,6 +873,11 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
foreach (var terrain in s_Terrains)
|
||||
{
|
||||
if (terrain.terrainData == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var rect = new Rect(terrain.transform.position.XZ(), terrain.terrainData.size.XZ());
|
||||
|
||||
// Return the first one.
|
||||
@@ -850,6 +890,7 @@ namespace WaveHarmonic.Crest
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#endif // d_Unity_Terrain
|
||||
|
||||
namespace Internal
|
||||
{
|
||||
@@ -869,6 +910,7 @@ namespace WaveHarmonic.Crest
|
||||
public static Vector4 XYNN(this Vector2 v, float n = 0f) => new(v.x, v.y, n, n);
|
||||
public static Vector4 XYNN(this Vector2 v, Vector2 n) => new(v.x, v.y, n.x, n.y);
|
||||
public static Vector4 NNZW(this Vector2 v, float n = 0f) => new(n, n, v.x, v.y);
|
||||
public static Vector4 XNZW(this Vector4 v, float n) => new(v.x, n, v.z, v.w);
|
||||
public static float Maximum(this Vector3 v) => Mathf.Max(Mathf.Max(v.x, v.y), v.z);
|
||||
|
||||
public static Vector2 Absolute(this Vector2 v) => new
|
||||
@@ -961,6 +1003,12 @@ namespace WaveHarmonic.Crest
|
||||
return GeometryUtility.CalculateBounds(s_BoundsPoints, transform.localToWorldMatrix);
|
||||
}
|
||||
|
||||
public static bool IntersectsXZ(this Bounds a, Bounds b)
|
||||
{
|
||||
return a.min.x <= b.max.x && a.max.x >= b.min.x &&
|
||||
a.min.z <= b.max.z && a.max.z >= b.min.z;
|
||||
}
|
||||
|
||||
public static Rect RectXZ(this Bounds bounds)
|
||||
{
|
||||
return Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z);
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
interface ICommandWrapper : IPropertyWrapper
|
||||
{
|
||||
void SetInvertCulling(bool invert);
|
||||
void DrawFullScreenTriangle(Material material, int pass, MaterialPropertyBlock block = null);
|
||||
void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int pass = -1, MaterialPropertyBlock block = null);
|
||||
}
|
||||
|
||||
|
||||
readonly struct CommandWrapper : ICommandWrapper
|
||||
{
|
||||
public CommandBuffer Commands { get; }
|
||||
public CommandWrapper(CommandBuffer commands) => Commands = commands;
|
||||
public void SetFloat(int param, float value) => Commands.SetGlobalFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => Commands.SetGlobalFloatArray(param, value);
|
||||
public void SetTexture(int param, Texture value) => Commands.SetGlobalTexture(param, value);
|
||||
public void SetVector(int param, Vector4 value) => Commands.SetGlobalVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => Commands.SetGlobalVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => Commands.SetGlobalMatrix(param, value);
|
||||
public void SetInteger(int param, int value) => Commands.SetGlobalInteger(param, value);
|
||||
public void SetBoolean(int param, bool value) => Commands.SetGlobalInteger(param, value ? 1 : 0);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
|
||||
public void SetInvertCulling(bool invert) => Commands.SetInvertCulling(invert);
|
||||
|
||||
public void DrawFullScreenTriangle(Material material, int pass = -1, MaterialPropertyBlock block = null)
|
||||
{
|
||||
Commands.DrawProcedural
|
||||
(
|
||||
Matrix4x4.identity,
|
||||
material,
|
||||
pass,
|
||||
MeshTopology.Triangles,
|
||||
vertexCount: 3,
|
||||
instanceCount: 1,
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int pass = -1, MaterialPropertyBlock block = null)
|
||||
{
|
||||
Commands.DrawMesh
|
||||
(
|
||||
mesh,
|
||||
matrix,
|
||||
material,
|
||||
submeshIndex: 0,
|
||||
pass,
|
||||
block
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_6000_0_OR_NEWER
|
||||
readonly struct RasterCommandWrapper : ICommandWrapper
|
||||
{
|
||||
public RasterCommandBuffer Commands { get; }
|
||||
public RasterCommandWrapper(RasterCommandBuffer commands) => Commands = commands;
|
||||
public void SetFloat(int param, float value) => Commands.SetGlobalFloat(param, value);
|
||||
public void SetFloatArray(int param, float[] value) => Commands.SetGlobalFloatArray(param, value);
|
||||
// WARNING: bypasses RG checks. Only use for textures external to RG.
|
||||
public void SetTexture(int param, Texture value) => Commands.m_WrappedCommandBuffer.SetGlobalTexture(param, value);
|
||||
public void SetVector(int param, Vector4 value) => Commands.SetGlobalVector(param, value);
|
||||
public void SetVectorArray(int param, Vector4[] value) => Commands.SetGlobalVectorArray(param, value);
|
||||
public void SetMatrix(int param, Matrix4x4 value) => Commands.SetGlobalMatrix(param, value);
|
||||
public void SetInteger(int param, int value) => Commands.SetGlobalInteger(param, value);
|
||||
public void SetBoolean(int param, bool value) => Commands.SetGlobalInteger(param, value ? 1 : 0);
|
||||
|
||||
public void GetBlock() { }
|
||||
public void SetBlock() { }
|
||||
|
||||
public void SetInvertCulling(bool invert) => Commands.SetInvertCulling(invert);
|
||||
|
||||
public void DrawFullScreenTriangle(Material material, int pass, MaterialPropertyBlock block = null)
|
||||
{
|
||||
Commands.DrawProcedural
|
||||
(
|
||||
Matrix4x4.identity,
|
||||
material,
|
||||
pass,
|
||||
MeshTopology.Triangles,
|
||||
vertexCount: 3,
|
||||
instanceCount: 1,
|
||||
block
|
||||
);
|
||||
}
|
||||
|
||||
public void DrawMesh(Mesh mesh, Matrix4x4 matrix, Material material, int pass = -1, MaterialPropertyBlock block = null)
|
||||
{
|
||||
Commands.DrawMesh
|
||||
(
|
||||
mesh,
|
||||
matrix,
|
||||
material,
|
||||
submeshIndex: 0,
|
||||
pass,
|
||||
block
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif // UNITY_6000_0_OR_NEWER
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a5766c3523cc4af586139878192e12d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -9,6 +9,12 @@ using UnityEngine.Rendering.HighDefinition;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
class CustomPass : UnityEngine.Rendering.HighDefinition.CustomPass
|
||||
{
|
||||
internal GameObject _GameObject;
|
||||
internal CustomPassVolume _Volume;
|
||||
}
|
||||
|
||||
static class CustomPassHelpers
|
||||
{
|
||||
internal static List<CustomPassVolume> s_Volumes = new();
|
||||
@@ -62,7 +68,8 @@ namespace WaveHarmonic.Crest
|
||||
GameObject gameObject,
|
||||
ref T pass,
|
||||
string name,
|
||||
CustomPassInjectionPoint injectionPoint
|
||||
CustomPassInjectionPoint injectionPoint,
|
||||
int priority = 0
|
||||
)
|
||||
where T : CustomPass, new()
|
||||
{
|
||||
@@ -85,14 +92,15 @@ namespace WaveHarmonic.Crest
|
||||
volume = gameObject.AddComponent<CustomPassVolume>();
|
||||
volume.injectionPoint = injectionPoint;
|
||||
volume.isGlobal = true;
|
||||
volume.priority = priority;
|
||||
}
|
||||
|
||||
// Create custom pass.
|
||||
pass ??= new()
|
||||
{
|
||||
name = $"Crest {name}",
|
||||
targetColorBuffer = CustomPass.TargetBuffer.None,
|
||||
targetDepthBuffer = CustomPass.TargetBuffer.None,
|
||||
name = name,
|
||||
targetColorBuffer = UnityEngine.Rendering.HighDefinition.CustomPass.TargetBuffer.None,
|
||||
targetDepthBuffer = UnityEngine.Rendering.HighDefinition.CustomPass.TargetBuffer.None,
|
||||
};
|
||||
|
||||
// Add custom pass.
|
||||
@@ -100,6 +108,27 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
volume.customPasses.Add(pass);
|
||||
}
|
||||
|
||||
pass._GameObject = gameObject;
|
||||
pass._Volume = volume;
|
||||
}
|
||||
|
||||
public static void Update<T>(GameObject go, T pass, CustomPassInjectionPoint point, int priority = 0) where T : CustomPass
|
||||
{
|
||||
CustomPassVolume volume = null;
|
||||
go.GetComponents(s_Volumes);
|
||||
|
||||
foreach (var v in s_Volumes)
|
||||
{
|
||||
if (v.customPasses.Contains(pass))
|
||||
{
|
||||
volume = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
volume.injectionPoint = point;
|
||||
volume.priority = priority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adapted from:
|
||||
// https://github.com/keijiro/LightProbeUtility/blob/85c93577338e10a52dd53f263056de08d883337a/Assets/LightProbeUtility.cs
|
||||
|
||||
// With fixes from:
|
||||
// https://github.com/keijiro/LightProbeUtility/pull/2
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class LightProbeUtility
|
||||
{
|
||||
static readonly int[] s_SHA =
|
||||
{
|
||||
Shader.PropertyToID("unity_SHAr"),
|
||||
Shader.PropertyToID("unity_SHAg"),
|
||||
Shader.PropertyToID("unity_SHAb")
|
||||
};
|
||||
|
||||
static readonly int[] s_SHB =
|
||||
{
|
||||
Shader.PropertyToID("unity_SHBr"),
|
||||
Shader.PropertyToID("unity_SHBg"),
|
||||
Shader.PropertyToID("unity_SHBb")
|
||||
};
|
||||
|
||||
static readonly int s_SHC = Shader.PropertyToID("unity_SHC");
|
||||
|
||||
public static void SetSHCoefficients<T>(this T properties, Vector3 position) where T : IPropertyWrapper
|
||||
{
|
||||
LightProbes.GetInterpolatedProbe(position, null, out var sh);
|
||||
|
||||
// Constant + Linear.
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
properties.SetVector(s_SHA[i], new(sh[i, 3], sh[i, 1], sh[i, 2], sh[i, 0] - sh[i, 6]));
|
||||
}
|
||||
|
||||
// Quadratic polynomials.
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
properties.SetVector(s_SHB[i], new(sh[i, 4], sh[i, 5], sh[i, 6] * 3, sh[i, 7]));
|
||||
}
|
||||
|
||||
// Final quadratic polynomial.
|
||||
properties.SetVector(s_SHC, new(sh[0, 8], sh[1, 8], sh[2, 8], 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf4aa5298ac5b4562a8c1f0466045eff
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
// Crest Water System
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// RTHandles for Built-In Render Pipeline.
|
||||
// We cannot call dispose ourselves, but it does not seem to be a problem.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace WaveHarmonic.Crest.Utility
|
||||
{
|
||||
static class RTHandles
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
if (!RenderPipelineHelper.IsLegacy)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether already initialized.
|
||||
if (UnityEngine.Rendering.RTHandles.maxWidth > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnityEngine.Rendering.RTHandles.Initialize(Screen.width, Screen.height);
|
||||
UnityEngine.Rendering.RTHandles.SetHardwareDynamicResolutionState(false);
|
||||
}
|
||||
|
||||
public static void OnBeginCameraRendering(Camera camera)
|
||||
{
|
||||
// Forget Dynamic Scaling, as is broken for Shader Graph and Post-Processing anyway.
|
||||
// The only foreseeable problem is if a third party calls this with a different size.
|
||||
UnityEngine.Rendering.RTHandles.SetReferenceSize(camera.pixelWidth, camera.pixelHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fed5f2fe3fcaa450f9c621080f7989ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -34,18 +34,48 @@ namespace WaveHarmonic.Crest
|
||||
public static implicit operator TextureHandle(Handle texture) => texture._TextureHandle;
|
||||
}
|
||||
|
||||
static readonly FieldInfo s_RenderContext = typeof(InternalRenderGraphContext).GetField("renderContext", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo s_WrappedContext = typeof(UnsafeGraphContext).GetField("wrappedContext", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
static readonly FieldInfo s_FrameData = typeof(RenderingData).GetField("frameData", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
public static ScriptableRenderContext GetRenderContext(this UnsafeGraphContext unsafeContext)
|
||||
{
|
||||
return (ScriptableRenderContext)s_RenderContext.GetValue((InternalRenderGraphContext)s_WrappedContext.GetValue(unsafeContext));
|
||||
return ((InternalRenderGraphContext)s_WrappedContext.GetValue(unsafeContext)).renderContext;
|
||||
}
|
||||
|
||||
public static ContextContainer GetFrameData(this ref RenderingData renderingData)
|
||||
{
|
||||
return (ContextContainer)s_FrameData.GetValue(renderingData);
|
||||
return renderingData.frameData;
|
||||
}
|
||||
|
||||
internal class PassData
|
||||
{
|
||||
#pragma warning disable IDE1006 // Naming Styles
|
||||
public UniversalCameraData cameraData;
|
||||
public UniversalRenderingData renderingData;
|
||||
public Handle colorTargetHandle;
|
||||
public Handle depthTargetHandle;
|
||||
#pragma warning restore IDE1006 // Naming Styles
|
||||
|
||||
public void Init(ContextContainer frameData, IUnsafeRenderGraphBuilder builder = null)
|
||||
{
|
||||
var resources = frameData.Get<UniversalResourceData>();
|
||||
cameraData = frameData.Get<UniversalCameraData>();
|
||||
renderingData = frameData.Get<UniversalRenderingData>();
|
||||
|
||||
if (builder == null)
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
colorTargetHandle = cameraData.renderer.cameraColorTargetHandle;
|
||||
depthTargetHandle = cameraData.renderer.cameraDepthTargetHandle;
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
else
|
||||
{
|
||||
colorTargetHandle = resources.activeColorTexture;
|
||||
depthTargetHandle = resources.activeDepthTexture;
|
||||
builder.UseTexture(colorTargetHandle, AccessFlags.ReadWrite);
|
||||
builder.UseTexture(depthTargetHandle, AccessFlags.ReadWrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// ENABLE_VR is defined if the platform supports XR.
|
||||
// d_UnityModuleVR is defined if the VR module is installed.
|
||||
// VR module depends on XR module (which does nothing by itself) so we only need to check the VR module.
|
||||
#if ENABLE_VR && d_UnityModuleVR
|
||||
#define _XR_ENABLED
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.HighDefinition;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static partial class Rendering
|
||||
{
|
||||
// Adaptor layer for XR module similar to Unity's XRGraphics/XRSRPSettings.
|
||||
// We cannot use theirs as they keep on renaming it…
|
||||
|
||||
static readonly GlobalKeyword s_SinglePassInstancedKeyword = new("STEREO_INSTANCING_ON");
|
||||
static readonly GlobalKeyword s_SinglePassMultiViewKeyword = new("STEREO_MULTIVIEW_ON");
|
||||
|
||||
#if _XR_ENABLED
|
||||
internal static GlobalKeyword SinglePassKeyword => XRSettings.stereoRenderingMode switch
|
||||
{
|
||||
XRSettings.StereoRenderingMode.SinglePassInstanced => s_SinglePassInstancedKeyword,
|
||||
XRSettings.StereoRenderingMode.SinglePassMultiview => s_SinglePassMultiViewKeyword,
|
||||
_ => throw new System.NotImplementedException(),
|
||||
};
|
||||
#endif
|
||||
|
||||
public static bool EnabledXR
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return XRSettings.enabled;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool SinglePassXR
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return XRSettings.enabled && (XRSettings.stereoRenderingMode is XRSettings.StereoRenderingMode.SinglePassInstanced or XRSettings.StereoRenderingMode.SinglePassMultiview);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static bool MultiPassXR
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return XRSettings.enabled && XRSettings.stereoRenderingMode is XRSettings.StereoRenderingMode.MultiPass;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class BIRP
|
||||
{
|
||||
[Conditional("_XR_ENABLED")]
|
||||
public static void EnableXR(CommandBuffer commands, Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!SinglePassXR || !camera.stereoEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commands.EnableKeyword(SinglePassKeyword);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("_XR_ENABLED")]
|
||||
public static void DisableXR(CommandBuffer commands, Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!SinglePassXR || !camera.stereoEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commands.DisableKeyword(SinglePassKeyword);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Stereo Rendering
|
||||
//
|
||||
|
||||
#if _XR_ENABLED
|
||||
public static partial class BIRP
|
||||
{
|
||||
// NOTE: This is the same value as Unity, but in the future it could be higher.
|
||||
const int k_MaximumViewsXR = 2;
|
||||
|
||||
static partial class ShaderIDs
|
||||
{
|
||||
public static readonly int s_StereoInverseViewProjection = Shader.PropertyToID("_Crest_StereoInverseViewProjection");
|
||||
}
|
||||
|
||||
static readonly List<XRDisplaySubsystem> s_DisplayListXR = new();
|
||||
|
||||
// Unity only supports one display right now.
|
||||
static XRDisplaySubsystem DisplayXR => XRSettings.enabled ? s_DisplayListXR[0] : null;
|
||||
|
||||
static Matrix4x4[] InverseViewProjectionMatrixXR { get; set; } = new Matrix4x4[2];
|
||||
|
||||
static Texture2DArray s_WhiteTextureXR = null;
|
||||
public static Texture2DArray WhiteTextureXR
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_WhiteTextureXR == null)
|
||||
{
|
||||
s_WhiteTextureXR = TextureArrayHelpers.CreateTexture2DArray(Texture2D.whiteTexture, k_MaximumViewsXR);
|
||||
s_WhiteTextureXR.name = "_Crest_WhiteTextureXR";
|
||||
}
|
||||
|
||||
return s_WhiteTextureXR;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetMatricesXR(Camera camera)
|
||||
{
|
||||
if (!camera.stereoEnabled || !SinglePassXR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SubsystemManager.GetSubsystems(s_DisplayListXR);
|
||||
// XR SPI only has one pass by definition.
|
||||
DisplayXR.GetRenderPass(renderPassIndex: 0, out var xrPass);
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrLeftEye);
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 1, out var xrRightEye);
|
||||
// We must opt for renderIntoTexture for Unity to handle Y flip.
|
||||
InverseViewProjectionMatrixXR[0] = (GL.GetGPUProjectionMatrix(xrLeftEye.projection, true) * xrLeftEye.view).inverse;
|
||||
InverseViewProjectionMatrixXR[1] = (GL.GetGPUProjectionMatrix(xrRightEye.projection, true) * xrRightEye.view).inverse;
|
||||
Shader.SetGlobalMatrixArray(ShaderIDs.s_StereoInverseViewProjection, InverseViewProjectionMatrixXR);
|
||||
}
|
||||
}
|
||||
#endif // _XR_ENABLED
|
||||
}
|
||||
}
|
||||
|
||||
#if d_UnityURP
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
#if !UNITY_6000_0_OR_NEWER
|
||||
using UniversalCameraData = CameraData;
|
||||
#endif
|
||||
|
||||
static partial class Rendering
|
||||
{
|
||||
public static class URP
|
||||
{
|
||||
[Conditional("_XR_ENABLED")]
|
||||
public static void EnableXR(CommandBuffer commands, UniversalCameraData camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
// We need to check the mask or it will cause entire pipeline to output black. Appears to only affect URP.
|
||||
if (!SinglePassXR || !camera.xrRendering || camera.camera.stereoTargetEye != StereoTargetEyeMask.Both)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commands.EnableKeyword(SinglePassKeyword);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("_XR_ENABLED")]
|
||||
public static void DisableXR(CommandBuffer commands, UniversalCameraData camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!SinglePassXR || !camera.xrRendering || camera.camera.stereoTargetEye != StereoTargetEyeMask.Both)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commands.DisableKeyword(SinglePassKeyword);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // d_UnityURP
|
||||
|
||||
#if d_UnityHDRP
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static partial class Rendering
|
||||
{
|
||||
public static class HDRP
|
||||
{
|
||||
[Conditional("_XR_ENABLED")]
|
||||
public static void EnableXR(CommandBuffer commands, HDAdditionalCameraData camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!SinglePassXR || camera == null || !camera.xrRendering)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commands.EnableKeyword(SinglePassKeyword);
|
||||
#endif
|
||||
}
|
||||
|
||||
[Conditional("_XR_ENABLED")]
|
||||
public static void DisableXR(CommandBuffer commands, HDAdditionalCameraData camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!SinglePassXR || camera == null || !camera.xrRendering)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
commands.DisableKeyword(SinglePassKeyword);
|
||||
#endif
|
||||
}
|
||||
|
||||
public static bool SkipPassXR(ref int index, HDAdditionalCameraData data)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (MultiPassXR && data != null && data.xrRendering)
|
||||
{
|
||||
// Alternate between left and right eye.
|
||||
index += 1;
|
||||
index %= 2;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
index = -1;
|
||||
}
|
||||
|
||||
// Skip if rendering the right eye.
|
||||
return index == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // d_UnityHDRP
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: beeb15d60da12461bb224ab1b3a6a12a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,124 @@
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
#if ENABLE_VR && d_UnityModuleVR
|
||||
#define _XR_ENABLED
|
||||
#endif
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Experimental.Rendering;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static partial class Rendering
|
||||
{
|
||||
public static partial class BIRP
|
||||
{
|
||||
static partial class ShaderIDs
|
||||
{
|
||||
public static readonly int s_InverseViewProjection = Shader.PropertyToID("_Crest_InverseViewProjection");
|
||||
}
|
||||
|
||||
public static Texture GetWhiteTexture(Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (camera.stereoEnabled && SinglePassXR)
|
||||
{
|
||||
return WhiteTextureXR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return Texture2D.whiteTexture;
|
||||
}
|
||||
|
||||
public static void SetMatrices(Camera camera)
|
||||
{
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, (GL.GetGPUProjectionMatrix(camera.projectionMatrix, true) * camera.worldToCameraMatrix).inverse);
|
||||
|
||||
#if _XR_ENABLED
|
||||
SetMatricesXR(camera);
|
||||
#endif
|
||||
}
|
||||
|
||||
public enum FrameBufferFormatOverride
|
||||
{
|
||||
None,
|
||||
LDR,
|
||||
HDR,
|
||||
}
|
||||
|
||||
public static RenderTextureDescriptor GetCameraTargetDescriptor(Camera camera, FrameBufferFormatOverride hdrOverride = FrameBufferFormatOverride.None)
|
||||
{
|
||||
RenderTextureDescriptor descriptor;
|
||||
|
||||
#if _XR_ENABLED
|
||||
if (camera.stereoEnabled)
|
||||
{
|
||||
// Will not set the following correctly:
|
||||
// - HDR format
|
||||
descriptor = XRSettings.eyeTextureDesc;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// As recommended by Unity, in 2021.2 using SystemInfo.GetGraphicsFormat with DefaultFormat.LDR is
|
||||
// necessary or gamma color space texture is returned:
|
||||
// https://docs.unity3d.com/ScriptReference/Experimental.Rendering.DefaultFormat.html
|
||||
descriptor = new(camera.pixelWidth, camera.pixelHeight, SystemInfo.GetGraphicsFormat(DefaultFormat.LDR), 0);
|
||||
}
|
||||
|
||||
// Set HDR format.
|
||||
if (camera.allowHDR && QualitySettings.activeColorSpace == ColorSpace.Linear)
|
||||
{
|
||||
var format = DefaultFormat.HDR;
|
||||
|
||||
if (hdrOverride is not FrameBufferFormatOverride.None)
|
||||
{
|
||||
format = hdrOverride is FrameBufferFormatOverride.HDR ? DefaultFormat.HDR : DefaultFormat.LDR;
|
||||
}
|
||||
#if UNITY_ANDROID || UNITY_IOS || UNITY_TVOS
|
||||
else
|
||||
{
|
||||
format = DefaultFormat.LDR;
|
||||
}
|
||||
#endif
|
||||
|
||||
descriptor.graphicsFormat = SystemInfo.GetGraphicsFormat(format);
|
||||
}
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static partial class Rendering
|
||||
{
|
||||
// Blit
|
||||
public static partial class BIRP
|
||||
{
|
||||
// Need to cast to int but no conversion cost.
|
||||
// https://stackoverflow.com/a/69148528
|
||||
internal enum UtilityPass
|
||||
{
|
||||
CopyDepth,
|
||||
Copy,
|
||||
MergeDepth,
|
||||
}
|
||||
|
||||
static Material s_UtilityMaterial;
|
||||
public static Material UtilityMaterial
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_UtilityMaterial == null)
|
||||
{
|
||||
s_UtilityMaterial = new(Shader.Find("Hidden/Crest/Legacy/Blit"));
|
||||
}
|
||||
|
||||
return s_UtilityMaterial;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33d8472e9ea11461b8bf02d7c4a72ec4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,4 +1,4 @@
|
||||
// Crest Water System
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
using UnityEngine;
|
||||
@@ -7,7 +7,7 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class TextureArrayHelpers
|
||||
{
|
||||
const int k_SmallTextureSize = 4;
|
||||
internal const int k_SmallTextureSize = 4;
|
||||
|
||||
public static Texture2D CreateTexture2D(Color color, TextureFormat format)
|
||||
{
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
"UNITY_2022_3_OR_NEWER"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.modules.terrain",
|
||||
"expression": "",
|
||||
"define": "d_Unity_Terrain"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.modules.xr",
|
||||
"expression": "",
|
||||
|
||||
@@ -1,183 +1,4 @@
|
||||
// Crest Water System
|
||||
// Crest Water System
|
||||
// Copyright © 2024 Wave Harmonic. All rights reserved.
|
||||
|
||||
// Adaptor layer for XR module. Could be replaced with the following one day:
|
||||
// com.unity.render-pipelines.core/Runtime/Common/XRGraphics.cs
|
||||
|
||||
// Currently, only the horizon line uses it.
|
||||
|
||||
// ENABLE_VR is defined if platform support XR.
|
||||
// d_UnityModuleVR is defined if VR module is installed.
|
||||
// VR module depends on XR module so we only need to check the VR module.
|
||||
#if ENABLE_VR && d_UnityModuleVR
|
||||
#define _XR_ENABLED
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
static class XRHelpers
|
||||
{
|
||||
// NOTE: This is the same value as Unity, but in the future it could be higher.
|
||||
const int k_MaximumViews = 2;
|
||||
|
||||
#if _XR_ENABLED
|
||||
static readonly List<XRDisplaySubsystem> s_DisplayList = new();
|
||||
|
||||
// Unity only supports one display right now.
|
||||
static XRDisplaySubsystem Display => IsRunning ? s_DisplayList[0] : null;
|
||||
#endif
|
||||
|
||||
static Matrix4x4 LeftEyeProjectionMatrix { get; set; }
|
||||
static Matrix4x4 RightEyeProjectionMatrix { get; set; }
|
||||
static Matrix4x4 LeftEyeViewMatrix { get; set; }
|
||||
static Matrix4x4 RightEyeViewMatrix { get; set; }
|
||||
static Matrix4x4 LeftInverseViewProjectionMatrixGPU { get; set; }
|
||||
static Matrix4x4 RightInverseViewProjectionMatrixGPU { get; set; }
|
||||
|
||||
static class ShaderIDs
|
||||
{
|
||||
public static readonly int s_InverseViewProjection = Shader.PropertyToID("_Crest_InverseViewProjection");
|
||||
public static readonly int s_InverseViewProjectionRight = Shader.PropertyToID("_Crest_InverseViewProjectionRight");
|
||||
}
|
||||
|
||||
internal static bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return XRSettings.enabled;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsSinglePass
|
||||
{
|
||||
get
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
return IsRunning && (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassInstanced ||
|
||||
XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static Texture2DArray s_WhiteTexture = null;
|
||||
public static Texture2DArray WhiteTexture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_WhiteTexture == null)
|
||||
{
|
||||
s_WhiteTexture = TextureArrayHelpers.CreateTexture2DArray(Texture2D.whiteTexture, k_MaximumViews);
|
||||
s_WhiteTexture.name = "Crest White Texture XR";
|
||||
}
|
||||
return s_WhiteTexture;
|
||||
}
|
||||
}
|
||||
|
||||
public static RenderTextureDescriptor GetRenderTextureDescriptor(Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (camera.stereoEnabled)
|
||||
{
|
||||
return XRSettings.eyeTextureDesc;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// As recommended by Unity, in 2021.2 using SystemInfo.GetGraphicsFormat with DefaultFormat.LDR is
|
||||
// necessary or gamma color space texture is returned:
|
||||
// https://docs.unity3d.com/ScriptReference/Experimental.Rendering.DefaultFormat.html
|
||||
return new(camera.pixelWidth, camera.pixelHeight, SystemInfo.GetGraphicsFormat(UnityEngine.Experimental.Rendering.DefaultFormat.LDR), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetViewProjectionMatrices(Camera camera, int passIndex)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (!XRSettings.enabled || IsSinglePass)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Not going to use cached values here just in case.
|
||||
Display.GetRenderPass(passIndex, out var xrPass);
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrEye);
|
||||
camera.projectionMatrix = xrEye.projection;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void UpdatePassIndex(ref int passIndex)
|
||||
{
|
||||
if (IsRunning)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
if (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.MultiPass)
|
||||
{
|
||||
// Alternate between left and right eye.
|
||||
passIndex += 1;
|
||||
passIndex %= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
passIndex = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
passIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetInverseViewProjectionMatrix(Camera camera)
|
||||
{
|
||||
// Have to set these explicitly as the built-in transforms aren't in world-space for the blit function.
|
||||
if (camera.stereoEnabled && IsSinglePass)
|
||||
{
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, LeftInverseViewProjectionMatrixGPU);
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjectionRight, RightInverseViewProjectionMatrixGPU);
|
||||
}
|
||||
else
|
||||
{
|
||||
Shader.SetGlobalMatrix(ShaderIDs.s_InverseViewProjection, LeftInverseViewProjectionMatrixGPU);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Update(Camera camera)
|
||||
{
|
||||
#if _XR_ENABLED
|
||||
SubsystemManager.GetSubsystems(s_DisplayList);
|
||||
#endif
|
||||
|
||||
if (!camera.stereoEnabled || !IsSinglePass)
|
||||
{
|
||||
// Built-in renderer does not provide these matrices.
|
||||
LeftInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(camera.projectionMatrix, false) * camera.worldToCameraMatrix).inverse;
|
||||
return;
|
||||
}
|
||||
|
||||
#if _XR_ENABLED
|
||||
// XR SPI only has one pass by definition.
|
||||
Display.GetRenderPass(renderPassIndex: 0, out var xrPass);
|
||||
// Grab left and right eye.
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 0, out var xrLeftEye);
|
||||
xrPass.GetRenderParameter(camera, renderParameterIndex: 1, out var xrRightEye);
|
||||
// Store all the matrices.
|
||||
LeftEyeViewMatrix = xrLeftEye.view;
|
||||
RightEyeViewMatrix = xrRightEye.view;
|
||||
LeftEyeProjectionMatrix = xrLeftEye.projection;
|
||||
RightEyeProjectionMatrix = xrRightEye.projection;
|
||||
LeftInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(LeftEyeProjectionMatrix, false) * LeftEyeViewMatrix).inverse;
|
||||
RightInverseViewProjectionMatrixGPU = (GL.GetGPUProjectionMatrix(RightEyeProjectionMatrix, false) * RightEyeViewMatrix).inverse;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
// Empty.
|
||||
|
||||
Reference in New Issue
Block a user