318 lines
7.9 KiB
C#
318 lines
7.9 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UltimateWater.Internal
|
|
{
|
|
[Serializable]
|
|
public class WaterGeometry
|
|
{
|
|
public enum Type
|
|
{
|
|
RadialGrid = 0,
|
|
ProjectionGrid = 1,
|
|
UniformGrid = 2,
|
|
CustomMeshes = 3
|
|
}
|
|
|
|
[FormerlySerializedAs("type")]
|
|
[SerializeField]
|
|
[Tooltip("Geometry type used for display.")]
|
|
private Type _Type;
|
|
|
|
[FormerlySerializedAs("baseVertexCount")]
|
|
[SerializeField]
|
|
[Tooltip("Water geometry vertex count at 1920x1080.")]
|
|
private int _BaseVertexCount = 500000;
|
|
|
|
[FormerlySerializedAs("tesselatedBaseVertexCount")]
|
|
[SerializeField]
|
|
[Tooltip("Water geometry vertex count at 1920x1080 on systems with tessellation support. Set it a bit lower as tessellation will place additional, better distributed vertices in shader.")]
|
|
private int _TesselatedBaseVertexCount = 16000;
|
|
|
|
[FormerlySerializedAs("adaptToResolution")]
|
|
[SerializeField]
|
|
private bool _AdaptToResolution = true;
|
|
|
|
[FormerlySerializedAs("radialGrid")]
|
|
[SerializeField]
|
|
private WaterRadialGrid _RadialGrid;
|
|
|
|
[FormerlySerializedAs("projectionGrid")]
|
|
[SerializeField]
|
|
private WaterProjectionGrid _ProjectionGrid;
|
|
|
|
[FormerlySerializedAs("uniformGrid")]
|
|
[SerializeField]
|
|
private WaterUniformGrid _UniformGrid;
|
|
|
|
[FormerlySerializedAs("customSurfaceMeshes")]
|
|
[SerializeField]
|
|
private WaterCustomSurfaceMeshes _CustomSurfaceMeshes;
|
|
|
|
private Water _Water;
|
|
|
|
private Type _PreviousType;
|
|
|
|
private int _PreviousTargetVertexCount;
|
|
|
|
private int _ThisSystemVertexCount;
|
|
|
|
private int _FrameCount;
|
|
|
|
private readonly WaterQuadGeometry _QuadGeometry = new WaterQuadGeometry();
|
|
|
|
public Type GeometryType
|
|
{
|
|
get
|
|
{
|
|
return _Type;
|
|
}
|
|
set
|
|
{
|
|
_Type = value;
|
|
}
|
|
}
|
|
|
|
public int VertexCount
|
|
{
|
|
get
|
|
{
|
|
return _BaseVertexCount;
|
|
}
|
|
}
|
|
|
|
public int TesselatedBaseVertexCount
|
|
{
|
|
get
|
|
{
|
|
return _TesselatedBaseVertexCount;
|
|
}
|
|
}
|
|
|
|
public bool AdaptToResolution
|
|
{
|
|
get
|
|
{
|
|
return _AdaptToResolution;
|
|
}
|
|
}
|
|
|
|
public bool Triangular
|
|
{
|
|
get
|
|
{
|
|
return _Type == Type.CustomMeshes && _CustomSurfaceMeshes.Triangular;
|
|
}
|
|
}
|
|
|
|
public WaterCustomSurfaceMeshes CustomSurfaceMeshes
|
|
{
|
|
get
|
|
{
|
|
return _CustomSurfaceMeshes;
|
|
}
|
|
}
|
|
|
|
public Mesh[] GetMeshes(WaterGeometryType geometryType, int vertexCount, bool volume)
|
|
{
|
|
if (geometryType == WaterGeometryType.ProjectionGrid)
|
|
{
|
|
throw new InvalidOperationException("Projection grid needs camera to be retrieved. Use GetTransformedMeshes instead.");
|
|
}
|
|
if (_Type == Type.CustomMeshes)
|
|
{
|
|
geometryType = WaterGeometryType.Auto;
|
|
}
|
|
Matrix4x4 matrix;
|
|
switch (geometryType)
|
|
{
|
|
case WaterGeometryType.Auto:
|
|
switch (_Type)
|
|
{
|
|
case Type.RadialGrid:
|
|
return _RadialGrid.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
case Type.ProjectionGrid:
|
|
return _ProjectionGrid.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
case Type.UniformGrid:
|
|
return _UniformGrid.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
case Type.CustomMeshes:
|
|
return _CustomSurfaceMeshes.GetTransformedMeshes(null, out matrix, volume);
|
|
default:
|
|
throw new InvalidOperationException("Unknown water geometry type.");
|
|
}
|
|
case WaterGeometryType.RadialGrid:
|
|
return _RadialGrid.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
case WaterGeometryType.ProjectionGrid:
|
|
return _ProjectionGrid.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
case WaterGeometryType.UniformGrid:
|
|
return _UniformGrid.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
case WaterGeometryType.QuadGeometry:
|
|
return _QuadGeometry.GetTransformedMeshes(null, out matrix, vertexCount, volume);
|
|
default:
|
|
throw new InvalidOperationException("Unknown water geometry type.");
|
|
}
|
|
}
|
|
|
|
public Mesh[] GetTransformedMeshes(Camera camera, out Matrix4x4 matrix, WaterGeometryType geometryType, bool volume, int vertexCount = 0)
|
|
{
|
|
if (vertexCount == 0)
|
|
{
|
|
vertexCount = ComputeVertexCountForCamera(camera);
|
|
}
|
|
if (_Type == Type.CustomMeshes)
|
|
{
|
|
geometryType = WaterGeometryType.Auto;
|
|
}
|
|
switch (geometryType)
|
|
{
|
|
case WaterGeometryType.Auto:
|
|
switch (_Type)
|
|
{
|
|
case Type.RadialGrid:
|
|
return _RadialGrid.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
case Type.ProjectionGrid:
|
|
return _ProjectionGrid.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
case Type.UniformGrid:
|
|
return _UniformGrid.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
case Type.CustomMeshes:
|
|
return _CustomSurfaceMeshes.GetTransformedMeshes(null, out matrix, volume);
|
|
default:
|
|
throw new InvalidOperationException("Unknown water geometry type.");
|
|
}
|
|
case WaterGeometryType.RadialGrid:
|
|
return _RadialGrid.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
case WaterGeometryType.ProjectionGrid:
|
|
return _ProjectionGrid.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
case WaterGeometryType.UniformGrid:
|
|
return _UniformGrid.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
case WaterGeometryType.QuadGeometry:
|
|
return _QuadGeometry.GetTransformedMeshes(camera, out matrix, vertexCount, volume);
|
|
default:
|
|
throw new InvalidOperationException("Unknown water geometry type.");
|
|
}
|
|
}
|
|
|
|
public int ComputeVertexCountForCamera(Camera camera)
|
|
{
|
|
return (!_AdaptToResolution) ? _ThisSystemVertexCount : ((int)((float)_ThisSystemVertexCount * ((float)(camera.pixelWidth * camera.pixelHeight) / 2073600f) + 0.5f));
|
|
}
|
|
|
|
private void UpdateVertexCount()
|
|
{
|
|
_ThisSystemVertexCount = ((!SystemInfo.supportsComputeShaders) ? Mathf.Min(_BaseVertexCount, WaterQualitySettings.Instance.MaxVertexCount) : Mathf.Min(_TesselatedBaseVertexCount, WaterQualitySettings.Instance.MaxTesselatedVertexCount));
|
|
}
|
|
|
|
internal void Awake(Water water)
|
|
{
|
|
_Water = water;
|
|
}
|
|
|
|
internal void OnEnable()
|
|
{
|
|
OnValidate();
|
|
UpdateVertexCount();
|
|
_RadialGrid.OnEnable(_Water);
|
|
_ProjectionGrid.OnEnable(_Water);
|
|
_UniformGrid.OnEnable(_Water);
|
|
_CustomSurfaceMeshes.OnEnable(_Water);
|
|
}
|
|
|
|
internal void OnDisable()
|
|
{
|
|
if (_RadialGrid != null)
|
|
{
|
|
_RadialGrid.OnDisable();
|
|
}
|
|
if (_ProjectionGrid != null)
|
|
{
|
|
_ProjectionGrid.OnDisable();
|
|
}
|
|
if (_UniformGrid != null)
|
|
{
|
|
_UniformGrid.OnDisable();
|
|
}
|
|
if (_CustomSurfaceMeshes != null)
|
|
{
|
|
_CustomSurfaceMeshes.OnDisable();
|
|
}
|
|
}
|
|
|
|
internal void OnValidate()
|
|
{
|
|
if (_RadialGrid == null)
|
|
{
|
|
_RadialGrid = new WaterRadialGrid();
|
|
}
|
|
if (_ProjectionGrid == null)
|
|
{
|
|
_ProjectionGrid = new WaterProjectionGrid();
|
|
}
|
|
if (_UniformGrid == null)
|
|
{
|
|
_UniformGrid = new WaterUniformGrid();
|
|
}
|
|
if (_CustomSurfaceMeshes == null)
|
|
{
|
|
_CustomSurfaceMeshes = new WaterCustomSurfaceMeshes();
|
|
}
|
|
if (_PreviousType != _Type)
|
|
{
|
|
switch (_PreviousType)
|
|
{
|
|
case Type.RadialGrid:
|
|
_RadialGrid.RemoveFromMaterial(_Water);
|
|
break;
|
|
case Type.ProjectionGrid:
|
|
_ProjectionGrid.RemoveFromMaterial(_Water);
|
|
break;
|
|
case Type.UniformGrid:
|
|
_UniformGrid.RemoveFromMaterial(_Water);
|
|
break;
|
|
}
|
|
switch (_Type)
|
|
{
|
|
case Type.RadialGrid:
|
|
_RadialGrid.AddToMaterial(_Water);
|
|
break;
|
|
case Type.ProjectionGrid:
|
|
_ProjectionGrid.AddToMaterial(_Water);
|
|
break;
|
|
case Type.UniformGrid:
|
|
_UniformGrid.AddToMaterial(_Water);
|
|
break;
|
|
}
|
|
_PreviousType = _Type;
|
|
}
|
|
UpdateVertexCount();
|
|
if (_PreviousTargetVertexCount != _ThisSystemVertexCount)
|
|
{
|
|
_RadialGrid.Dispose();
|
|
_UniformGrid.Dispose();
|
|
_ProjectionGrid.Dispose();
|
|
_PreviousTargetVertexCount = _ThisSystemVertexCount;
|
|
}
|
|
}
|
|
|
|
internal void Update()
|
|
{
|
|
if (++_FrameCount > 8)
|
|
{
|
|
_FrameCount = 0;
|
|
}
|
|
switch (_FrameCount)
|
|
{
|
|
case 0:
|
|
_RadialGrid.Update();
|
|
break;
|
|
case 3:
|
|
_ProjectionGrid.Update();
|
|
break;
|
|
case 6:
|
|
_UniformGrid.Update();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|