139 lines
5.3 KiB
C#
139 lines
5.3 KiB
C#
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
|
|
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
|
|
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
|
|
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
|
|
|
|
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace StylizedWater3
|
|
{
|
|
/// <summary>
|
|
/// Utility for creating an orthographic top-down projection
|
|
/// </summary>
|
|
public class PlanarProjection
|
|
{
|
|
private static readonly Quaternion viewRotation = Quaternion.Euler(new Vector3(90f, 0f, 0f));
|
|
private static readonly Vector3 viewScale = new Vector3(1, 1, -1);
|
|
private static readonly Plane[] frustrumPlanes = new Plane[6];
|
|
|
|
//Input
|
|
public Vector3 center;
|
|
public Vector3 offset;
|
|
|
|
public float scale;
|
|
public int resolution;
|
|
public bool expandHeight = true;
|
|
|
|
//Output
|
|
public Matrix4x4 projection;
|
|
public Matrix4x4 view;
|
|
public Rect viewportRect;
|
|
public Vector3 boundsMin;
|
|
public Vector3 boundsMax;
|
|
|
|
//Important to snap the projection to the nearest texel. Otherwise pixel swimming is introduced when moving, due to bilinear filtering
|
|
private static Vector3 Stabilize(Vector3 pos, float texelSize)
|
|
{
|
|
float Snap(float coord, float cellSize) => Mathf.FloorToInt(coord / cellSize) * (cellSize) + (cellSize * 0.5f);
|
|
|
|
return new Vector3(Snap(pos.x, texelSize), Snap(pos.y, texelSize), Snap(pos.z, texelSize));
|
|
}
|
|
|
|
public void Recalculate()
|
|
{
|
|
float extent = scale * 0.5f;
|
|
|
|
Vector3 centerPosition = center + offset;
|
|
|
|
//var frustumHeight = 2.0f * scale * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad); //Still clips, plus doesn't support orthographc
|
|
var frustumHeight = expandHeight ? 10000f : scale;
|
|
centerPosition += (Vector3.up * frustumHeight * 0.5f);
|
|
|
|
centerPosition = Stabilize(centerPosition, scale / resolution);
|
|
|
|
projection = Matrix4x4.Ortho(-extent, extent, -extent, extent, 0.02f, frustumHeight);
|
|
|
|
view = Matrix4x4.TRS(centerPosition, viewRotation, viewScale).inverse;
|
|
|
|
viewportRect = new Rect(0, 0, resolution, resolution);
|
|
|
|
boundsMin.x = centerPosition.x - extent;
|
|
boundsMin.y = centerPosition.y - extent;
|
|
boundsMin.z = centerPosition.z - extent;
|
|
|
|
boundsMax.x = centerPosition.z + extent;
|
|
boundsMax.y = centerPosition.z + extent;
|
|
boundsMax.z = centerPosition.z + extent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets a Vector4 uniform up to be passed onto shader land, where a world-space position can be used to calculate a sampling UV
|
|
/// </summary>
|
|
/// <param name="coords"></param>
|
|
public void SetUV(ref Vector4 coords)
|
|
{
|
|
coords.x = boundsMin.x;
|
|
coords.y = boundsMin.z;
|
|
coords.z = scale;
|
|
coords.w = 1; //Enable sampling shaders
|
|
}
|
|
|
|
public void SetProjection(RasterCommandBuffer cmd)
|
|
{
|
|
cmd.SetViewProjectionMatrices(view, projection);
|
|
|
|
//Unity 6000.0.30f1+ only
|
|
//RenderingUtils.SetViewAndProjectionMatrices(cmd, view, projection, true);
|
|
}
|
|
|
|
public static int CalculateResolution(float scale, int texelsPerUnit, int min, int max)
|
|
{
|
|
int res = Mathf.RoundToInt(scale * texelsPerUnit);
|
|
//if(NON_POWER_OF_TWO == false) res = Mathf.NextPowerOfTwo(res);
|
|
|
|
return Mathf.Clamp(res, min, max);
|
|
}
|
|
|
|
public static float FadePercentageToLength(float renderRange, float fadePercentage)
|
|
{
|
|
fadePercentage = Mathf.Max(0.01f, fadePercentage);
|
|
|
|
return (renderRange * 0.5f) * (fadePercentage / 100f);
|
|
}
|
|
|
|
public void CalculateFrustumPlanes()
|
|
{
|
|
GeometryUtility.CalculateFrustumPlanes(projection * view, frustrumPlanes);
|
|
}
|
|
|
|
public bool TestPlanesAABB(Bounds bounds)
|
|
{
|
|
return GeometryUtility.TestPlanesAABB(frustrumPlanes, bounds);
|
|
}
|
|
|
|
//Using data only from the matrices, to ensure what you're seeing closely represents them
|
|
public void DrawOrthographicViewGizmo()
|
|
{
|
|
Gizmos.matrix = Matrix4x4.identity;
|
|
|
|
CalculateFrustumPlanes();
|
|
|
|
float near = frustrumPlanes[4].distance;
|
|
float far = frustrumPlanes[5].distance;
|
|
float height = near + far;
|
|
|
|
Vector3 position = new Vector3(view.inverse.m03, view.inverse.m13, view.inverse.m23);
|
|
Vector3 orthoSize = new Vector3((frustrumPlanes[0].distance + frustrumPlanes[1].distance), height, frustrumPlanes[2].distance + frustrumPlanes[3].distance);
|
|
|
|
//orthoSize = Vector3.one * 50f;
|
|
Gizmos.DrawSphere(position, 1f);
|
|
|
|
position -= Vector3.up * height * 0.5f;
|
|
Gizmos.DrawWireCube(position, orthoSize);
|
|
Gizmos.color = Color.white * 0.25f;
|
|
Gizmos.DrawCube(position, orthoSize);
|
|
}
|
|
}
|
|
} |