red-sim-light-volumesudon/VRCLightVolumes/PointLightVolume.cs
2025-09-17 01:38:27 +01:00

268 lines
No EOL
8.4 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using UnityEngine;
namespace VRCLightVolumes
{
[ExecuteAlways]
public class PointLightVolume : MonoBehaviour
{
[Tooltip("Defines whether this point light volume can be moved in runtime. Disabling this option slightly improves performance.")]
public bool Dynamic = false;
[Tooltip("Enables baked shadows for this light. This setting is only available for static lights, which cannot move. You must re-bake your volumes after changing this setting. This incurs some runtime VRAM and performance overhead.")]
public bool BakedShadows = false;
[Min(0f)]
[Tooltip("Shadow radius for the baked shadows. Higher values will produce softer shadows.")]
public float BakedShadowRadius = 0.1f;
[Tooltip("Point light is the most performant type. Area light is the heaviest and best suited for dynamic, movable sources. For static lighting, it's recommended to bake regular additive light volumes instead.")]
public PointLightVolume.LightType Type = PointLightVolume.LightType.PointLight;
[Min(0.0001f)]
[Tooltip("Physical radius of a light source if it was a matte glowing sphere for a point light, or a flashlight reflector for a spot light. Larger size emmits more light without increasing overall intensity.")]
public float LightSourceSize = 0.25f;
[Min(0.0001f)]
[Tooltip("Radius in meters beyond which light is culled. Fewer overlapping lights result in better performance.")]
public float Range = 10f;
[ColorUsage(false)]
[Tooltip("Multiplies the point light volumes color by this value.")]
public UnityEngine.Color Color = UnityEngine.Color.get_white();
[Tooltip("Brightness of the point light volume.")]
public float Intensity = 1f;
[Tooltip("Parametric uses settings to compute light falloff. LUT uses a texture: X - cone falloff, Y - attenuation (Y only for point lights). Cookie projects a texture for spot lights. Cubemap projects a cubemap for point lights.")]
public PointLightVolume.LightShape Shape = PointLightVolume.LightShape.Parametric;
[Range(0.1f, 360f)]
[Tooltip("Angle of a spotlight cone in degrees.")]
public float Angle = 60f;
[Range(0.001f, 1f)]
[Tooltip("Cone falloff.")]
public float Falloff = 1f;
[Tooltip("X - cone falloff, Y - attenuation. No compression and RGBA Float or RGBA Half format is recommended.")]
public Texture2D FalloffLUT = null;
[Tooltip("Projects a square texture for spot lights.")]
public Texture2D Cookie = null;
[Tooltip("Projects a cubemap for point lights.")]
public UnityEngine.Cubemap Cubemap = null;
[Tooltip("Shows overdrawing range gizmo. Less point light volumes intersections - more performance!")]
public bool DebugRange = false;
public int CustomID = 0;
public VRCLightVolumes.PointLightVolumeInstance PointLightVolumeInstance;
public VRCLightVolumes.LightVolumeSetup LightVolumeSetup;
private Texture2D _falloffLUTPrev = null;
private Texture2D _cookiePrev = null;
private UnityEngine.Cubemap _cubemapPrev = null;
private PointLightVolume.LightShape _shapePrev = PointLightVolume.LightShape.Parametric;
private PointLightVolume.LightType _typePrev = PointLightVolume.LightType.PointLight;
private Vector3 _prevPos = Vector3.get_zero();
private Quaternion _prevRot = Quaternion.get_identity();
private Vector3 _prevScl = Vector3.get_one();
private bool _isValidated = false;
public PointLightVolume()
{
}
public Texture GetCustomTexture()
{
Texture falloffLUT;
if ((this.Shape == PointLightVolume.LightShape.Parametric ? false : this.Type != PointLightVolume.LightType.AreaLight))
{
if (this.Type != PointLightVolume.LightType.PointLight)
{
if (this.Type == PointLightVolume.LightType.SpotLight)
{
if (this.Shape == PointLightVolume.LightShape.LUT)
{
falloffLUT = this.FalloffLUT;
return falloffLUT;
}
else if (this.Shape == PointLightVolume.LightShape.Custom)
{
falloffLUT = this.Cookie;
return falloffLUT;
}
}
}
else if (this.Shape == PointLightVolume.LightShape.LUT)
{
falloffLUT = this.FalloffLUT;
return falloffLUT;
}
else if (this.Shape == PointLightVolume.LightShape.Custom)
{
falloffLUT = this.Cubemap;
return falloffLUT;
}
falloffLUT = null;
}
else
{
falloffLUT = null;
}
return falloffLUT;
}
private void OnDestroy()
{
if (this.LightVolumeSetup != null)
{
this.FalloffLUT = null;
this.Cookie = null;
this.Cubemap = null;
this.LightVolumeSetup.RefreshVolumesList();
this.LightVolumeSetup.SyncUdonScript();
}
}
private void OnDisable()
{
if (this.LightVolumeSetup != null)
{
this.LightVolumeSetup.RefreshVolumesList();
this.LightVolumeSetup.SyncUdonScript();
}
}
private void OnEnable()
{
this.SetupDependencies();
this.LightVolumeSetup.RefreshVolumesList();
this.LightVolumeSetup.SyncUdonScript();
}
private void OnValidate()
{
this._isValidated = true;
}
private void Reset()
{
this.SetupDependencies();
this.SyncUdonScript();
this.LightVolumeSetup.RefreshVolumesList();
this.LightVolumeSetup.SyncUdonScript();
}
public void SetupDependencies()
{
if ((this.PointLightVolumeInstance != null ? false : !base.TryGetComponent<VRCLightVolumes.PointLightVolumeInstance>(ref this.PointLightVolumeInstance)))
{
this.PointLightVolumeInstance = base.get_gameObject().AddComponent<VRCLightVolumes.PointLightVolumeInstance>();
}
if (this.LightVolumeSetup == null)
{
this.LightVolumeSetup = UnityEngine.Object.FindObjectOfType<VRCLightVolumes.LightVolumeSetup>();
if (this.LightVolumeSetup == null)
{
this.LightVolumeSetup = (new GameObject("Light Volume Manager")).AddComponent<VRCLightVolumes.LightVolumeSetup>();
this.LightVolumeSetup.SyncUdonScript();
}
}
}
public void SyncUdonScript()
{
if (base.get_gameObject() != null)
{
this.SetupDependencies();
this.PointLightVolumeInstance.IsInitialized = true;
this.PointLightVolumeInstance.LightVolumeManager = this.LightVolumeSetup.LightVolumeManager;
this.PointLightVolumeInstance.IsDynamic = this.Dynamic;
this.PointLightVolumeInstance.Color = this.Color;
this.PointLightVolumeInstance.Intensity = this.Intensity;
this.PointLightVolumeInstance.IsRangeDirty = true;
if (this.Type == PointLightVolume.LightType.PointLight)
{
if ((this.Shape != PointLightVolume.LightShape.Custom ? false : this.Cubemap != null))
{
this.PointLightVolumeInstance.SetLightSourceSize(this.LightSourceSize);
this.PointLightVolumeInstance.SetCustomTexture(this.CustomID);
}
else if ((this.Shape != PointLightVolume.LightShape.LUT ? true : this.FalloffLUT == null))
{
this.PointLightVolumeInstance.SetLightSourceSize(this.LightSourceSize);
this.PointLightVolumeInstance.SetParametric();
}
else
{
this.PointLightVolumeInstance.SetLightSourceSize(this.Range);
this.PointLightVolumeInstance.SetLut(this.CustomID);
}
this.PointLightVolumeInstance.SetPointLight();
this.PointLightVolumeInstance.UpdateRotation();
}
else if (this.Type == PointLightVolume.LightType.SpotLight)
{
this.PointLightVolumeInstance.SetLightSourceSize(this.Range);
if ((this.Shape != PointLightVolume.LightShape.Custom ? false : this.Cookie != null))
{
this.PointLightVolumeInstance.SetLightSourceSize(this.LightSourceSize);
this.PointLightVolumeInstance.SetCustomTexture(this.CustomID);
}
else if ((this.Shape != PointLightVolume.LightShape.LUT ? true : this.FalloffLUT == null))
{
this.PointLightVolumeInstance.SetLightSourceSize(this.LightSourceSize);
this.PointLightVolumeInstance.SetParametric();
}
else
{
this.PointLightVolumeInstance.SetLightSourceSize(this.Range);
this.PointLightVolumeInstance.SetLut(this.CustomID);
}
this.PointLightVolumeInstance.SetSpotLight(this.Angle, this.Falloff);
this.PointLightVolumeInstance.UpdateRotation();
}
else if (this.Type == PointLightVolume.LightType.AreaLight)
{
this.PointLightVolumeInstance.SetAreaLight();
this.PointLightVolumeInstance.UpdateRotation();
}
}
}
private void Update()
{
if (base.get_gameObject() != null)
{
this.SetupDependencies();
}
}
public enum LightShape
{
Parametric,
LUT,
Custom
}
public enum LightType
{
PointLight,
SpotLight,
AreaLight
}
}
}