123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace VolumetricFogAndMist2 {
- [ExecuteInEditMode]
- [DefaultExecutionOrder(100)]
- public class PointLightManager : MonoBehaviour, IVolumetricFogManager {
- public static bool usingPointLights;
- public string managerName {
- get {
- return "Point Light Manager";
- }
- }
- public const int MAX_POINT_LIGHTS = 16;
- [Header("Point Light Search Settings")]
- [Tooltip("Point lights are sorted by distance to tracking center object")]
- public Transform trackingCenter;
- [Tooltip("Point lights are sorted by camera distance every certain time interval to ensure the nearest 16 point lights are used.")]
- public float distanceSortTimeInterval = 3f;
- [Tooltip("Ignore point lights behind camera")]
- public bool excludeLightsBehind = true;
- [Header("Common Settings")]
- [Tooltip("Global inscattering multiplier for point lights")]
- public float inscattering = 1f;
- [Tooltip("Global intensity multiplier for point lights")]
- public float intensity = 1f;
- [Tooltip("Reduces light intensity near point lights")]
- public float insideAtten;
- readonly static List<FogPointLight> pointLights = new List<FogPointLight>();
- static bool requireRefresh;
- int lastPointLightsCount;
- Vector4[] pointLightColorBuffer;
- Vector4[] pointLightPositionBuffer;
- float distanceSortLastTime;
- private void OnEnable() {
- if (trackingCenter == null) {
- Camera cam = null;
- Tools.CheckCamera(ref cam);
- if (cam != null) {
- trackingCenter = cam.transform;
- }
- }
- if (pointLightColorBuffer == null || pointLightColorBuffer.Length != MAX_POINT_LIGHTS) {
- pointLightColorBuffer = new Vector4[MAX_POINT_LIGHTS];
- }
- if (pointLightPositionBuffer == null || pointLightPositionBuffer.Length != MAX_POINT_LIGHTS) {
- pointLightPositionBuffer = new Vector4[MAX_POINT_LIGHTS];
- }
- requireRefresh = true;
- }
- private void LateUpdate() {
- if (!usingPointLights) return;
- usingPointLights = false;
- int pointLightsCount = pointLights.Count;
- if (lastPointLightsCount != pointLightsCount) {
- lastPointLightsCount = pointLightsCount;
- requireRefresh = true;
- }
- if (requireRefresh) {
- requireRefresh = false;
- TrackPointLights(true);
- } else {
- if (pointLightsCount == 0) return;
- TrackPointLights();
- }
- SubmitPointLightData();
- }
- void SubmitPointLightData() {
- int count = 0;
- bool appIsRunning = Application.isPlaying;
- Vector3 trackingCenterPosition;
- Vector3 trackingCenterForward;
- bool isExcludingLightsBehind = excludeLightsBehind && appIsRunning;
- if (isExcludingLightsBehind && trackingCenter != null) {
- trackingCenterPosition = trackingCenter.position;
- trackingCenterForward = trackingCenter.forward;
- } else {
- trackingCenterPosition = trackingCenterForward = Vector3.zero;
- isExcludingLightsBehind = false;
- }
- int pointLightsCount = pointLights.Count;
- for (int i = 0; count < MAX_POINT_LIGHTS && i < pointLightsCount; i++) {
- FogPointLight fogPointLight = pointLights[i];
- if (fogPointLight == null || !fogPointLight.isActiveAndEnabled) continue;
- Light light = pointLights[i].pointLight;
- if (light == null || !light.isActiveAndEnabled || light.type != LightType.Point) continue;
- Vector3 pos = light.transform.position;
- float range = light.range;
- range *= fogPointLight.inscattering * inscattering / 25f; // note: 25 comes from Unity point light attenuation equation
- // if point light is behind camera and beyond the range, ignore it
- if (isExcludingLightsBehind) {
- Vector3 toLight = pos - trackingCenterPosition;
- float dot = Vector3.Dot(trackingCenterForward, pos - trackingCenterPosition);
- if (dot < 0 && toLight.sqrMagnitude > range * range) {
- continue;
- }
- }
- // add light to the buffer if intensity is enough
- float multiplier = light.intensity * fogPointLight.intensity * intensity;
- if (range > 0 && multiplier > 0) {
- pointLightPositionBuffer[count].x = pos.x;
- pointLightPositionBuffer[count].y = pos.y;
- pointLightPositionBuffer[count].z = pos.z;
- pointLightPositionBuffer[count].w = 0;
- Color color = light.color;
- pointLightColorBuffer[count].x = color.r * multiplier;
- pointLightColorBuffer[count].y = color.g * multiplier;
- pointLightColorBuffer[count].z = color.b * multiplier;
- pointLightColorBuffer[count].w = range;
- count++;
- }
- }
- Shader.SetGlobalInt(ShaderParams.PointLightCount, count);
- if (count > 0) {
- Shader.SetGlobalVectorArray(ShaderParams.PointLightColors, pointLightColorBuffer);
- Shader.SetGlobalVectorArray(ShaderParams.PointLightPositions, pointLightPositionBuffer);
- Shader.SetGlobalFloat(ShaderParams.PointLightInsideAtten, insideAtten);
- }
- }
- public static void RegisterPointLight(FogPointLight fogPointLight) {
- if (fogPointLight != null) {
- pointLights.Add(fogPointLight);
- requireRefresh = true;
- }
- }
- public static void UnregisterPointLight(FogPointLight fogPointLight) {
- if (fogPointLight != null && pointLights.Contains(fogPointLight)) {
- pointLights.Remove(fogPointLight);
- requireRefresh = true;
- }
- }
- /// <summary>
- /// Look for nearest point lights
- /// </summary>
- public void TrackPointLights(bool forceImmediateUpdate = false) {
- // Look for new lights?
- if (pointLights != null && pointLights.Count > 0 && (forceImmediateUpdate || !Application.isPlaying || (distanceSortTimeInterval > 0 && Time.time - distanceSortLastTime > distanceSortTimeInterval))) {
- if (trackingCenter != null) {
- distanceSortLastTime = Time.time;
- pointLights.Sort(pointLightsDistanceComparer);
- }
- }
- }
- int pointLightsDistanceComparer(FogPointLight l1, FogPointLight l2) {
- float dist1 = (l1.transform.position - trackingCenter.position).sqrMagnitude;
- float dist2 = (l2.transform.position - trackingCenter.position).sqrMagnitude;
- if (dist1 < dist2) return -1;
- if (dist1 > dist2) return 1;
- return 0;
- }
- public void Refresh() {
- requireRefresh = true;
- }
- }
- }
|