162 lines
5.8 KiB
C#
162 lines
5.8 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace VolumetricFogAndMist2 {
|
|
|
|
[ExecuteInEditMode]
|
|
[DefaultExecutionOrder(100)]
|
|
public class FogVoidManager : MonoBehaviour, IVolumetricFogManager {
|
|
|
|
public static bool usingVoids;
|
|
|
|
public string managerName {
|
|
get {
|
|
return "Fog Void Manager";
|
|
}
|
|
}
|
|
|
|
public const int MAX_FOG_VOID = 8;
|
|
|
|
[Header("Void Search Settings")]
|
|
public Transform trackingCenter;
|
|
[Tooltip("Fog voids are sorted by camera distance every certain time interval to ensure the nearest 8 voids are used.")]
|
|
public float distanceSortTimeInterval = 3f;
|
|
|
|
readonly static List<FogVoid> fogVoids = new List<FogVoid>();
|
|
Vector4[] fogVoidPositions;
|
|
Vector4[] fogVoidSizes;
|
|
Matrix4x4[] fogVoidMatrices;
|
|
float distanceSortLastTime;
|
|
static bool requireRefresh;
|
|
int lastFogVoidCount;
|
|
|
|
private void OnEnable() {
|
|
if (trackingCenter == null) {
|
|
Camera cam = null;
|
|
Tools.CheckCamera(ref cam);
|
|
if (cam != null) {
|
|
trackingCenter = cam.transform;
|
|
}
|
|
}
|
|
if (fogVoidPositions == null || fogVoidPositions.Length != MAX_FOG_VOID) {
|
|
fogVoidPositions = new Vector4[MAX_FOG_VOID];
|
|
}
|
|
if (fogVoidSizes == null || fogVoidSizes.Length != MAX_FOG_VOID) {
|
|
fogVoidSizes = new Vector4[MAX_FOG_VOID];
|
|
}
|
|
if (fogVoidMatrices == null || fogVoidMatrices.Length != MAX_FOG_VOID) {
|
|
fogVoidMatrices = new Matrix4x4[MAX_FOG_VOID];
|
|
}
|
|
requireRefresh = true;
|
|
}
|
|
|
|
|
|
void LateUpdate() {
|
|
if (!usingVoids) return;
|
|
usingVoids = false;
|
|
|
|
int fogVoidsCount = fogVoids.Count;
|
|
if (fogVoidsCount != lastFogVoidCount) {
|
|
lastFogVoidCount = fogVoidsCount;
|
|
requireRefresh = true;
|
|
}
|
|
if (requireRefresh) {
|
|
requireRefresh = false;
|
|
TrackFogVoids(true);
|
|
} else {
|
|
if (fogVoidsCount == 0) return;
|
|
TrackFogVoids();
|
|
}
|
|
SubmitFogVoidData();
|
|
}
|
|
|
|
void SubmitFogVoidData() {
|
|
|
|
bool allowRotation = VolumetricFogManager.allowFogVoidRotation;
|
|
|
|
int count = 0;
|
|
int fogVoidsCount = fogVoids.Count;
|
|
for (int i = 0; count < MAX_FOG_VOID && i < fogVoidsCount; i++) {
|
|
FogVoid fogVoid = fogVoids[i];
|
|
if (fogVoid == null || !fogVoid.isActiveAndEnabled) continue;
|
|
Transform t = fogVoid.transform;
|
|
Vector3 pos = t.position;
|
|
Vector3 scale = t.lossyScale;
|
|
if (scale.x < 0.01f) scale.x = 0.01f;
|
|
if (scale.y < 0.01f) scale.y = 0.01f;
|
|
if (scale.z < 0.01f) scale.z = 0.01f;
|
|
scale.x *= 0.5f;
|
|
scale.y *= 0.5f;
|
|
scale.z *= 0.5f;
|
|
fogVoidPositions[count].x = pos.x;
|
|
fogVoidPositions[count].y = pos.y;
|
|
fogVoidPositions[count].z = pos.z;
|
|
fogVoidPositions[count].w = 10f * (1f - fogVoid.falloff) * (1f - fogVoid.falloff);
|
|
if (allowRotation) {
|
|
fogVoidMatrices[count] = Matrix4x4.TRS(pos, t.rotation, scale).inverse;
|
|
} else {
|
|
float width = scale.x;
|
|
float height = scale.y;
|
|
float depth = scale.z;
|
|
fogVoidSizes[count].x = 1f / (0.0001f + width * width);
|
|
fogVoidSizes[count].y = 1f / (0.0001f + height * height);
|
|
fogVoidSizes[count].z = 1f / (0.0001f + depth * depth);
|
|
}
|
|
fogVoidSizes[count].w = fogVoid.roundness;
|
|
count++;
|
|
}
|
|
Shader.SetGlobalInt(ShaderParams.VoidCount, count);
|
|
if (count > 0) {
|
|
Shader.SetGlobalVectorArray(ShaderParams.VoidPositions, fogVoidPositions);
|
|
if (allowRotation) {
|
|
Shader.SetGlobalMatrixArray(ShaderParams.VoidMatrices, fogVoidMatrices);
|
|
}
|
|
Shader.SetGlobalVectorArray(ShaderParams.VoidSizes, fogVoidSizes);
|
|
}
|
|
}
|
|
|
|
public static void RegisterFogVoid(FogVoid fogVoid) {
|
|
if (fogVoid != null) {
|
|
fogVoids.Add(fogVoid);
|
|
requireRefresh = true;
|
|
}
|
|
}
|
|
|
|
public static void UnregisterFogVoid(FogVoid fogVoid) {
|
|
if (fogVoid != null && fogVoids.Contains(fogVoid)) {
|
|
fogVoids.Remove(fogVoid);
|
|
requireRefresh = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Look for nearest voids
|
|
/// </summary>
|
|
public void TrackFogVoids(bool forceImmediateUpdate = false) {
|
|
|
|
// Look for new voids?
|
|
if (fogVoids != null && fogVoids.Count > 0 && (forceImmediateUpdate || !Application.isPlaying || (distanceSortTimeInterval > 0 && Time.time - distanceSortLastTime > distanceSortTimeInterval))) {
|
|
if (trackingCenter != null) {
|
|
distanceSortLastTime = Time.time;
|
|
fogVoids.Sort(fogVoidDistanceComparer);
|
|
}
|
|
}
|
|
}
|
|
|
|
int fogVoidDistanceComparer(FogVoid v1, FogVoid v2) {
|
|
float dist1 = (v1.transform.position - trackingCenter.position).sqrMagnitude;
|
|
float dist2 = (v2.transform.position - trackingCenter.position).sqrMagnitude;
|
|
if (dist1 < dist2) return -1;
|
|
if (dist1 > dist2) return 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
public void Refresh() {
|
|
requireRefresh = true;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
} |