Files
2025-05-15 15:37:45 +08:00

230 lines
8.1 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using Random = UnityEngine.Random;
// VolFx © NullTale - https://x.com/NullTale
namespace VolFx.Tools
{
public static class Utils
{
public static int s_MainTexId = Shader.PropertyToID("_MainTex");
private static Mesh s_FullscreenQuad;
private static Mesh s_FullscreenTriangle;
public static Mesh FullscreenMesh
{
get
{
_initFullScreenMeshes();
return s_FullscreenTriangle;
}
}
private static Matrix4x4 s_IndentityInvert = new Matrix4x4(new Vector4(1, 0, 0, 0), new Vector4(0, -1, 0, 0), new Vector4(0, 0, 1, 0), new Vector4(0, 0, 0, 1));
// =======================================================================
private static void _initFullScreenMeshes()
{
// quad
if (s_FullscreenQuad == null)
{
s_FullscreenQuad = new Mesh { name = "Fullscreen Quad" };
s_FullscreenQuad.SetVertices(new List<Vector3>
{
new Vector3(-1.0f, -1.0f, 0.0f),
new Vector3(-1.0f, 1.0f, 0.0f),
new Vector3(1.0f, -1.0f, 0.0f),
new Vector3(1.0f, 1.0f, 0.0f)
});
s_FullscreenQuad.SetUVs(0, new List<Vector2>
{
new Vector2(0.0f, 1f),
new Vector2(0.0f, 0f),
new Vector2(1.0f, 1f),
new Vector2(1.0f, 0f)
});
s_FullscreenQuad.SetIndices(new[] { 0, 1, 2, 2, 1, 3 }, MeshTopology.Triangles, 0, false);
s_FullscreenQuad.UploadMeshData(true);
}
// triangle
if (s_FullscreenTriangle == null)
{
s_FullscreenTriangle = new Mesh() { name = "Fullscreen Triangle" };
s_FullscreenTriangle.vertices = _verts(0f);
s_FullscreenTriangle.uv = _texCoords();
s_FullscreenTriangle.triangles = new int[3] { 0, 1, 2 };
s_FullscreenTriangle.UploadMeshData(true);
// -----------------------------------------------------------------------
Vector3[] _verts(float z)
{
var r = new Vector3[3];
for (var i = 0; i < 3; i++)
{
var uv = new Vector2((i << 1) & 2, i & 2);
r[i] = new Vector3(uv.x * 2f - 1f, uv.y * 2f - 1f, z);
}
return r;
}
Vector2[] _texCoords()
{
var r = new Vector2[3];
for (var i = 0; i < 3; i++)
{
if (SystemInfo.graphicsUVStartsAtTop)
r[i] = new Vector2((i << 1) & 2, 1.0f - (i & 2));
else
r[i] = new Vector2((i << 1) & 2, i & 2);
}
return r;
}
}
}
public static void Blit(CommandBuffer cmd, RTHandle destination, Material material, int pass = 0, bool invert = false, int mip = 0)
{
cmd.SetRenderTarget(destination, mip);
cmd.DrawMesh(FullscreenMesh, invert ? s_IndentityInvert : Matrix4x4.identity, material, 0, pass);
}
public static void Blit(CommandBuffer cmd, RTHandle source, RTHandle destination, Material material, int pass = 0, bool invert = false, int mip = 0)
{
cmd.SetGlobalTexture(s_MainTexId, source);
cmd.SetRenderTarget(destination, mip);
cmd.DrawMesh(FullscreenMesh, invert ? s_IndentityInvert : Matrix4x4.identity, material, 0, pass);
}
public static void Blit(CommandBuffer cmd, RenderTargetIdentifier source, RTHandle destination, Material material, int pass = 0, bool invert = false, int mip = 0)
{
cmd.SetGlobalTexture(s_MainTexId, source);
cmd.SetRenderTarget(destination, mip);
cmd.DrawMesh(FullscreenMesh, invert ? s_IndentityInvert : Matrix4x4.identity, material, 0, pass);
}
public static void Blit(CommandBuffer cmd, RenderTargetIdentifier source, RTHandle destination, Material material, int pass = 0, bool invert = false, int mip = 0, MaterialPropertyBlock prop = null)
{
cmd.SetGlobalTexture(s_MainTexId, source);
cmd.SetRenderTarget(destination, mip);
cmd.DrawMesh(FullscreenMesh, invert ? s_IndentityInvert : Matrix4x4.identity, material, 0, pass, prop);
}
public static Vector2 ToNormal(this float rad)
{
return new Vector2(Mathf.Cos(rad), Mathf.Sin(rad));
}
public static float Round(this float f)
{
return Mathf.Round(f);
}
public static float Clamp01(this float f)
{
return Mathf.Clamp01(f);
}
public static float OneMinus(this float f)
{
return 1f - f;
}
public static float Remap(this float f, float min, float max)
{
return min + (max - min) * f;
}
public static Color Color()
{
return new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f),
Random.Range(0.0f, 1.0f), 1.0f);
}
public static Vector3 WithZ(this Vector3 vector, float z)
{
return new Vector3(vector.x, vector.y, z);
}
public static Vector2 To2DXY(this Vector3 vector)
{
return new Vector2(vector.x, vector.y);
}
public static Vector3 To3DXZ(this Vector2 vector)
{
return vector.To3DXZ(0);
}
public static Vector3 To3DXZ(this Vector2 vector, float y)
{
return new Vector3(vector.x, y, vector.y);
}
public static Vector3 To3DXY(this Vector2 vector, float z)
{
return new Vector3(vector.x, vector.y, z);
}
public static Vector2 ToVector2XY(this float value)
{
return new Vector2(value, value);
}
public static Color MulA(this Color color, float a)
{
return new Color(color.r, color.g, color.b, color.a * a);
}
public static Rect GetRect(this Texture2D texture)
{
return new Rect(0, 0, texture.width, texture.height);
}
public static int RoundToInt(this float f)
{
return Mathf.RoundToInt(f);
}
public static TKey MaxOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, TSource noOptionsValue = default)
{
var result = source.MaxOrDefault(selector, Comparer<TKey>.Default, noOptionsValue);
if (Equals(result, default))
return default;
return selector(result);
}
public static TSource MaxOrDefault<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IComparer<TKey> comparer, TSource fallback = default)
{
using (var sourceIterator = source.GetEnumerator())
{
if (sourceIterator.MoveNext() == false)
return fallback;
var max = sourceIterator.Current;
var maxKey = selector(max);
while (sourceIterator.MoveNext())
{
var candidate = sourceIterator.Current;
var candidateProjected = selector(candidate);
if (comparer.Compare(candidateProjected, maxKey) > 0)
{
max = candidate;
maxKey = candidateProjected;
}
}
return max;
}
}
}
}