Game.Rendering.LightingSystem
Assembly:
Likely Assembly-CSharp or the game's "Game" assembly (compiled into the game's runtime).
Namespace:
Game.Rendering
Type:
public class LightingSystem
Base:
GameSystemBase
Summary:
Handles the game's day/night lighting and post-processing setup. It reads planetary light data (sun, moon, night lights) from PlanetarySystem, evaluates the current time-of-day state (dawn, sunrise, day, sunset, dusk, night), adjusts exposure, sky parameters, color grading, indirect lighting multipliers, shadow enable/disable for lights, and blends 3D LUTs (look-up textures) for color grading transitions. It also creates and manages a persistent Volume with HDRP post-processing components used by the system (Exposure, PhysicallyBasedSky, ColorAdjustments, Tonemapping, IndirectLightingController) and can blend LUTs using a compute shader.
Fields
-
private static class ShaderID
Contains cached shader property IDs used by the LUT blending compute shader: _TargetLUT, _SourceLUT, _DestinationLUT and _LUTBlend. These are obtained via Shader.PropertyToID for efficient shader parameter lookups. -
public enum State { Dawn, Sunrise, Day, Sunset, Dusk, Night, Invalid }
Represents the discrete lighting states used by the system to drive transitions and parameter blending. -
private PlanetarySystem m_PlanetarySystem
Reference to the PlanetarySystem (used to get SunLight, MoonLight, NightLight and overrideTime). -
protected EntityQuery m_TimeSettingGroup
EntityQuery to ensure the system updates only when time settings exist (required for update). -
private Exposure m_Exposure
HDRP Exposure volume component controlled by this system. -
private PhysicallyBasedSky m_PhysicallyBasedSky
HDRP PhysicallyBasedSky volume component controlled by this system. -
private ColorAdjustments m_ColorAdjustments
HDRP ColorAdjustments component (color filter, contrast). -
private IndirectLightingController m_Indirect
HDRP IndirectLightingController controlling reflection/indirect multipliers. -
private Tonemapping m_Tonemap
HDRP Tonemapping component used for LUT assignment and contribution. -
private bool m_PostProcessingSetup
Tracks whether the post-processing Volume and components have been created/initialized. -
private DayNightCycleData m_NightDayCycleData
Data asset containing configuration values for exposures, colors, LUTs, angles and intensities used for day/night transitions. Loaded from Resources ("DayNight/Default"). -
private Volume m_Volume
The created persistent GameObject's Volume component used to host the profile. -
private VolumeProfile m_Profile
The VolumeProfile instance used to add and hold the HDRP components. -
private RenderTexture m_BlendResult
A 3D RenderTexture used as the target when blending two 3D LUTs with the compute shader. -
private ComputeShader m_LUTBlend
Compute shader used to blend two 3D LUTs into m_BlendResult (loaded from "DayNight/LUTBlend"). -
private int m_KernalBlend = -1
Cached kernel index for the compute shader ("CSBlend"). -
private State m_LastState = State.Invalid
Stores the last evaluated state to stabilize transitions when overrideTime is not set. -
private float m_LastDelta = -1f
Stores the last delta (blend factor) used for transition smoothing. -
private float m_dayLightBrightness
(backed by propertydayLightBrightness
)
Internal backing for public dayLightBrightness property (exposed via auto-property in code).
Note: the class also declares a private auto-property:
- private bool shadowDisabled { get; set; }
Controls whether shadow enabling is globally disabled based on quality settings.
Properties
-
private bool shadowDisabled { get; set; }
Private property set each update from shared graphics settings (ShadowsQualitySettings.enabled). Used to prevent enabling shadows when quality settings disable them. -
public float dayLightBrightness { get; private set; }
Public read-only property (private setter) exposing a normalized daylight brightness value computed each update from the sun light's intensity. -
public State state { get }
Read-only property that returns the current evaluated State. Calculates the state based on the PlanetarySystem's sun light transform (position and direction). If sun light is invalid, returns State.Invalid.
Constructors
public LightingSystem()
Default constructor (has [Preserve] attribute). Initialization happens primarily in OnCreate; constructor does not perform heavy setup.
Methods
-
protected override void OnCreate()
Initializes the system: acquires PlanetarySystem, loads DayNightCycleData ("DayNight/Default"), sets up post-processing Volume (calls SetupPostprocessing), loads the LUT blend compute shader, creates a 3D RenderTexture target for LUT blending, prepares the entity query for time settings, and marks the system as required for update (RequireForUpdate). This is where resources are loaded and GPU resources (RenderTexture) are created. -
protected override void OnDestroy()
Cleans up created objects: destroys the persistent Volume GameObject and the m_BlendResult RenderTexture if they exist. -
private float CalcObscured(PlanetarySystem.LightData moon, PlanetarySystem.LightData night, float range = 0.3f)
Calculates how obscured the night light is by the moon geometry using the vertical positions of the moon and the night light. Returns a clamped factor [0,1] used to blend night/moon intensities. -
private void EnableShadows(PlanetarySystem.LightData lightData, bool enabled)
Enables/disables shadows on the given light's additionalData, while respecting the system-wide shadowDisabled flag (from quality settings). -
protected override void OnUpdate()
Main update loop. Reads ShadowsQualitySettings to set shadowDisabled, queries PlanetarySystem lights (sun, moon, night), early-exits if any required data is invalid, computes dayLightBrightness, evaluates the current State and delta (with logic to avoid flicker when planetary overrideTime is used), computes various intensity and indirect multipliers (taking into account moon/night obscuration), sets exposure, sky, color adjustments, indirect multipliers, and per-state logic for enabling/disabling shadows and color grading (including blending or assigning LUTs). Finally resets the VolumeProfile to apply changes. -
private State CalculateState(float3 sunPosition, float3 sunDirection, out float delta)
Determines the lighting State (Dawn, Sunrise, Day, Sunset, Dusk, Night) based on sun position and direction and the thresholds in DayNightCycleData (angles for dawn/sunrise/sunset/dusk). Outputs a delta value representing blend factor inside transitions. If m_NightDayCycleData is null it returns Day and delta = 1. -
private State NextState(State value)
Returns the next chronological State (Dawn -> Sunrise -> Day -> Sunset -> Dusk -> Night -> Dawn). Useful for transition stability. -
private void SetupPostprocessing()
Creates a persistent GameObject named "LightingPostProcessVolume" (DontDestroyOnLoad) and adds a Volume component. It sets Volume.priority and adds required HDRP volume components to the profile: Exposure, PhysicallyBasedSky, ColorAdjustments, IndirectLightingController, Tonemapping. Components are configured with sensible default override states and values used by the day/night logic. This method is guarded so it only sets up once. -
private void BlendLUT(Texture3D source, Texture3D destination, float delta, float lutContribution)
Blends two 3D LUT textures. If both exist and a compute shader is available, it dispatches the compute shader into m_BlendResult, then assigns m_BlendResult to the Tonemapping LUT. If compute shader isn't available it picks source/destination based on delta. Handles cases where only one of source/destination exists by lerping lutContribution appropriately. If neither exist it clears the tonemap LUT.
Usage Example
// Typical override location inside the system life cycle:
[Preserve]
protected override void OnCreate()
{
base.OnCreate();
// LightingSystem loads DayNightCycleData, sets up HDRP volume components
// and prepares compute shader / render textures for LUT blending.
}
// Example: reading public state and brightness inside another system or debug:
var lightingSystem = World.GetExistingSystemManaged<Game.Rendering.LightingSystem>();
if (lightingSystem != null)
{
var currentState = lightingSystem.state; // Dawn / Day / Night / etc.
float brightness = lightingSystem.dayLightBrightness; // normalized daylight intensity
}
Notes and tips for modders: - DayNightCycleData (Resources/DayNight/Default) holds the configurable parameters (angles, colors, LUTs, intensities). Replacing or editing this asset allows customizing transitions and colors. - LUT blending requires the "DayNight/LUTBlend" compute shader and a 3D RenderTexture target with GraphicsFormat.R16G16B16A16_SFloat. If the compute shader is missing, the system falls back to a simple choice between source and destination LUTs. - The system respects the game's ShadowsQualitySettings to disable shadows globally. - The Volume created is persistent (DontDestroyOnLoad) and has a high priority (1000) to ensure its overrides are applied. Modifying or replacing this VolumeProfile at runtime may interfere with LightingSystem updates; prefer editing DayNightCycleData or change component values via the Volume's profile entries.