Files
2026-03-04 10:03:45 +08:00

299 lines
10 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace AQUAS
{
public class AQUAS_ProjectedGrid : MonoBehaviour
{
public GameObject waterplane;
private GameObject ContainerObj;
public Transform[] children;
private AQUAS_Caustics[] causticComponents;
private Camera cam;
private GameObject projectorObj;
private Camera projector;
private Vector3[] farFrustumCorners;
private Vector3[] nearFrustumCorners;
private Vector3[] pFarFrustumCorners;
private Vector3[] pNearFrustumCorners;
private Material[] materials;
public float waterLevel;
private List<Vector3> intersectionPoints;
private Vector4 minMax;
private void Start()
{
children = new Transform[waterplane.transform.childCount];
List<AQUAS_Caustics> list = new List<AQUAS_Caustics>();
for (int i = 0; i < waterplane.transform.childCount; i++)
{
children[i] = waterplane.transform.GetChild(i);
if (waterplane.transform.GetChild(i).GetComponent<AQUAS_Caustics>() != null)
{
list.Add(waterplane.transform.GetChild(i).GetComponent<AQUAS_Caustics>());
}
}
Transform[] array = children;
foreach (Transform transform in array)
{
if (transform.name == "Static Boundary")
{
transform.parent = null;
}
if (transform.GetComponent<AQUAS_Caustics>() != null)
{
transform.parent = null;
}
}
causticComponents = list.ToArray();
cam = GetComponent<Camera>();
materials = waterplane.GetComponent<SkinnedMeshRenderer>().sharedMaterials;
nearFrustumCorners = new Vector3[4];
farFrustumCorners = new Vector3[4];
pFarFrustumCorners = new Vector3[4];
pNearFrustumCorners = new Vector3[4];
waterLevel = waterplane.transform.position.y;
projectorObj = new GameObject("Projector Object (" + base.transform.name + ")");
projectorObj.hideFlags = HideFlags.HideAndDontSave;
projector = projectorObj.AddComponent<Camera>();
projector.CopyFrom(cam);
projector.depth = cam.depth - 1f;
projector.enabled = false;
intersectionPoints = new List<Vector3>();
ContainerObj = waterplane.transform.parent.gameObject;
if (GetComponent<AQUAS_UnderWaterEffect_Simple>() != null)
{
GetComponent<AQUAS_UnderWaterEffect_Simple>().waterLevel = waterLevel;
array = children;
foreach (Transform transform2 in array)
{
if (transform2.name == "Static Boundary" && GetComponent<AQUAS_UnderWaterEffect>() != null)
{
GetComponent<AQUAS_UnderWaterEffect>().dynamicBoundary = transform2.gameObject;
}
}
}
if (!(GetComponent<AQUAS_UnderWaterEffect>() != null))
{
return;
}
GetComponent<AQUAS_UnderWaterEffect>().waterLevel = waterLevel;
array = children;
foreach (Transform transform3 in array)
{
if (transform3.name == "Static Boundary")
{
GetComponent<AQUAS_UnderWaterEffect>().dynamicBoundary = transform3.gameObject;
}
}
}
private void Update()
{
if (!projectorObj)
{
Start();
}
Vector3 vector = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, -1f));
projector.transform.position = new Vector3(vector.x, Mathf.Max(waterLevel + Mathf.Abs(waterLevel - cam.transform.position.y), waterLevel + 3f), vector.z);
AQUAS_Caustics[] array = causticComponents;
foreach (AQUAS_Caustics obj in array)
{
obj.waterLevel = waterLevel;
obj.overrideWaterLevel = true;
}
cam.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), cam.farClipPlane, Camera.MonoOrStereoscopicEye.Mono, farFrustumCorners);
cam.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), cam.nearClipPlane, Camera.MonoOrStereoscopicEye.Mono, nearFrustumCorners);
projector.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), projector.farClipPlane, Camera.MonoOrStereoscopicEye.Mono, pFarFrustumCorners);
projector.CalculateFrustumCorners(new Rect(0f, 0f, 1f, 1f), projector.nearClipPlane, Camera.MonoOrStereoscopicEye.Mono, pNearFrustumCorners);
for (int j = 0; j < 4; j++)
{
farFrustumCorners[j] = base.transform.TransformPoint(farFrustumCorners[j]);
nearFrustumCorners[j] = base.transform.TransformPoint(nearFrustumCorners[j]);
pFarFrustumCorners[j] = projectorObj.transform.TransformPoint(pFarFrustumCorners[j]);
pNearFrustumCorners[j] = projectorObj.transform.TransformPoint(pNearFrustumCorners[j]);
}
intersectionPoints.Clear();
GetAllIntersectionPoints(waterLevel);
GetAllIntersectionPoints(waterLevel + 1f);
GetAllIntersectionPoints(waterLevel - 1f);
projector.aspect = cam.aspect;
projector.fieldOfView = cam.fieldOfView;
projector.transform.LookAt(AimProjector());
}
private void OnPreCull()
{
Transform[] array = children;
foreach (Transform transform in array)
{
if (!(transform == null))
{
if (transform.name == "PrimaryCausticsProjector" || transform.name == "SecondaryCausticsProjector")
{
transform.position = new Vector3(base.transform.position.x, waterLevel, base.transform.position.z);
transform.eulerAngles = new Vector3(90f, 0f, 0f);
}
else
{
transform.position = new Vector3(base.transform.position.x, waterLevel, base.transform.position.z);
transform.eulerAngles = new Vector3(0f, 0f, 0f);
transform.localScale = new Vector3(cam.farClipPlane / 2f, cam.farClipPlane / 2f, cam.farClipPlane / 2f);
}
}
}
PositionPlane();
minMax = GetBordersInViewport();
float num = Vector3.Distance(pNearFrustumCorners[0], pNearFrustumCorners[3]);
float num2 = Vector3.Distance(pNearFrustumCorners[0], pNearFrustumCorners[1]);
Material[] array2 = materials;
foreach (Material material in array2)
{
material.SetVector("_ObjectScale", new Vector2(num / projector.nearClipPlane, num2 / projector.nearClipPlane));
material.SetVector("_RangeVector", minMax);
material.SetFloat("_waterLevel", waterLevel);
material.SetFloat("_ProjectGrid", 1f);
if (material.HasProperty("_PhysicalNormalStrength"))
{
material.SetFloat("_PhysicalNormalStrength", 1f);
}
}
}
private void OnPostRender()
{
waterplane.transform.parent = ContainerObj.transform;
}
private void PositionPlane()
{
waterplane.transform.position = projector.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, projector.nearClipPlane));
waterplane.transform.eulerAngles = new Vector3(projector.transform.eulerAngles.x - 90f, projector.transform.eulerAngles.y, projector.transform.eulerAngles.z);
waterplane.transform.parent = projectorObj.transform;
}
private void GetAllIntersectionPoints(float level)
{
Vector3 planeOrigin = new Vector3(0f, level, 0f);
for (int i = 0; i < 4; i++)
{
int num = ((i != 3) ? (i + 1) : 0);
if (LinePlaneIntersection(nearFrustumCorners[i], nearFrustumCorners[num], planeOrigin))
{
intersectionPoints.Add(GetIntersectionPoint(nearFrustumCorners[i], nearFrustumCorners[num], planeOrigin));
}
if (LinePlaneIntersection(farFrustumCorners[i], farFrustumCorners[num], planeOrigin))
{
intersectionPoints.Add(GetIntersectionPoint(farFrustumCorners[i], farFrustumCorners[num], planeOrigin));
}
if (LinePlaneIntersection(nearFrustumCorners[i], farFrustumCorners[i], planeOrigin))
{
intersectionPoints.Add(GetIntersectionPoint(nearFrustumCorners[i], farFrustumCorners[i], planeOrigin));
}
}
}
private bool LinePlaneIntersection(Vector3 startPoint, Vector3 targetPoint, Vector3 planeOrigin)
{
Vector3 up = Vector3.up;
float num = Vector3.Dot(up, startPoint - planeOrigin);
float num2 = Vector3.Dot(up, targetPoint - planeOrigin);
if (num * num2 <= 0f)
{
return true;
}
return false;
}
private Vector3 GetIntersectionPoint(Vector3 startPoint, Vector3 targetPoint, Vector3 planeOrigin)
{
Vector3 up = Vector3.up;
float num = Vector3.Dot(up, targetPoint - planeOrigin);
Vector3 vector = (targetPoint - startPoint) / Vector3.Magnitude(targetPoint - startPoint);
float num2 = Vector3.Dot(up, vector);
return targetPoint - vector * (num / num2);
}
private Vector3 AimProjector()
{
Vector3 zero = Vector3.zero;
if (LinePlaneIntersection(cam.transform.position, cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)), new Vector3(0f, waterLevel, 0f)))
{
Vector3 vector = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane));
if (cam.transform.position.y > waterLevel)
{
Vector3 startPoint = new Vector3(cam.transform.position.x, Mathf.Max(cam.transform.position.y, waterLevel + 3f), cam.transform.position.z);
zero = GetIntersectionPoint(startPoint, cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)), new Vector3(0f, waterLevel, 0f));
}
else if (cam.transform.position.y < waterLevel)
{
Vector3 startPoint = new Vector3(cam.transform.position.x, Mathf.Min(cam.transform.position.y, waterLevel - 3f), cam.transform.position.z);
zero = GetIntersectionPoint(startPoint, cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)), new Vector3(0f, waterLevel, 0f));
}
else
{
vector = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane));
zero = new Vector3(vector.x, waterLevel, vector.z);
}
}
else
{
Vector3 vector2 = cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane));
zero = new Vector3(vector2.x, 0f - Mathf.Abs(vector2.y), vector2.z);
}
return zero;
}
private Vector4 GetBordersInViewport()
{
float num = 1f;
float num2 = 0f;
float num3 = 1f;
float num4 = 0f;
for (int i = 0; i < intersectionPoints.Count; i++)
{
if (projector.WorldToViewportPoint(intersectionPoints[i]).x < num)
{
num = projector.WorldToViewportPoint(intersectionPoints[i]).x;
}
}
for (int j = 0; j < intersectionPoints.Count; j++)
{
if (projector.WorldToViewportPoint(intersectionPoints[j]).x > num2)
{
num2 = projector.WorldToViewportPoint(intersectionPoints[j]).x;
}
}
for (int k = 0; k < intersectionPoints.Count; k++)
{
if (projector.WorldToViewportPoint(intersectionPoints[k]).y < num3)
{
num3 = projector.WorldToViewportPoint(intersectionPoints[k]).y;
}
}
for (int l = 0; l < intersectionPoints.Count; l++)
{
if (projector.WorldToViewportPoint(intersectionPoints[l]).y > num4)
{
num4 = projector.WorldToViewportPoint(intersectionPoints[l]).y;
}
}
return new Vector4((num - 0.5f) * 1.1f, num3 - 0.5f, (num2 - 0.5f) * 1.1f, num4 - 0.5f);
}
}
}