Skip to content

Game.Effects.LightCullingSystem

Assembly:
Game (runtime assembly — may be Assembly-CSharp or a game-specific assembly in Cities: Skylines 2)

Namespace:
Game.Effects

Type:
class

Base:
GameSystemBase

Summary:
LightCullingSystem gathers, culls and sorts light effect instances (LightEffect / LightEffectData + enabled effect instances) and prepares the runtime HDRP punctual light buffers used by the HDRP lighting pipeline (HDRPDotsInputs). It uses Burst-compiled parallel jobs to determine visibility against the camera frustum and LOD/distance criteria, then sorts visible lights by distance and writes out compact arrays of VisibleLight/HDRP-specific data for rendering. The system also reads prefab light parameters and converts Game light representations to HDRP render data.


Fields

  • private PrefabSystem m_PrefabSystem
    {{ This holds a reference to the game's PrefabSystem used to access EffectPrefabs (LightEffect components) for each prefab entity. }}

  • private RenderingSystem m_RenderingSystem
    {{ Reference to the rendering system. Used to read rendering settings such as maxLightCount. }}

  • private EffectControlSystem m_EffectControlSystem
    {{ Reference to the effect control system that provides the enabled effect instances and LOD/camera parameters. }}

  • private EntityQuery m_LightEffectPrefabQuery
    {{ An EntityQuery that selects entities with LightEffectData and PrefabData to build per-prefab culling data. }}

  • private NativeParallelHashMap<Entity, LightEffectCullData> m_LightEffectCullData
    {{ Per-prefab precomputed culling and render indices (range, spot angle, inv distance factor, prefab index, game light type). Populated every frame in ComputeLightEffectCullData. }}

  • private static DefaultLightParams s_DefaultLightParams
    {{ A small struct populated once (ReadDefaultLightParams) with default HDAdditionalLightData parameters used as a fallback for missing values. }}

  • private NativeQueue<VisibleLightData> m_VisibleLights
    {{ Thread-safe queue used by the LightCullingJob (parallel writer) to enqueue VisibleLightData for later sorting/building. }}

  • private NativeReference<float> m_LastFrameMaxPunctualLightDistance
    {{ Small persistent native container storing the max distance of visible punctual lights from the previous frame. Used to apply min/max scale optimization across frames. }}

  • public static bool s_enableMinMaxLightCullingOptim
    {{ Global toggle (static) to enable/disable the min/max distance culling optimization that relies on previous-frame max distance. Default true. }}

  • public static float s_maxLightDistanceScale
    {{ Global multiplier applied to last-frame max distance to compute auto-reject threshold (default 1.5). }}

  • public static float s_minLightDistanceScale
    {{ Minimum distance scale applied when selecting/sorting lights (default 0.5). }}

  • private TypeHandle __TypeHandle
    {{ Internal container for Entity/ComponentTypeHandles used when reading archetype chunk arrays in ComputeLightEffectCullData. }}

  • (Nested data structs) LightEffectCullData, DefaultLightParams, VisibleLightData
    {{ Small structs used by the system and the jobs: LightEffectCullData stores per-prefab parameters used during culling; DefaultLightParams stores defaults from HD light; VisibleLightData represents an enqueued visible light instance for sorting/consuming by HDRP writer. }}

  • (Nested job types) LightCullingJob, SortAndBuildPunctualLightsJob
    {{ Burst-compiled jobs used to cull enabled effect instances in parallel and to sort/build HDRP punctual light buffers respectively. Their details are described under Methods. }}

Properties

  • (none)
    {{ This system does not expose public C# properties. It exposes public static fields for tuning and otherwise manages its state internally. }}

Constructors

  • public LightCullingSystem()
    {{ Default empty constructor — initialization of native containers and system references is performed in OnCreate. }}

Methods

  • protected override void OnCreate()
    {{ Initializes system references (PrefabSystem, RenderingSystem, EffectControlSystem), creates entity query for LightEffect prefabs, allocates persistent native containers (m_LightEffectCullData, m_VisibleLights, m_LastFrameMaxPunctualLightDistance) and reads default HD light parameters via ReadDefaultLightParams(). This method is marked [Preserve] to ensure it isn't stripped. }}

  • protected override void OnDestroy()
    {{ Cleans up persistent resources: completes outstanding HDRPDotsInputs.punctualLightsJobHandle, disposes NativeReference/NativeQueue/NativeParallelHashMap and clears HDRPDotsInputs frame light data. Always call base.OnDestroy() at the end. }}

  • protected override void OnUpdate()
    {{ Main per-frame logic:

  • Completes any previous punctual lights job.
  • Sets HDRPDotsInputs.MaxPunctualLights from rendering system.
  • Clears HDRPDotsInputs per-frame data.
  • Retrieves Camera.main; if null, skip.
  • Gets LOD parameters and camera transform info from EffectControlSystem.
  • Calls ComputeLightEffectCullData to rebuild per-prefab culling info.
  • Computes camera frustum planes and packs them into a NativeArray for the job.
  • Computes an autoRejectDistance based on previous-frame max distance (if optimization enabled).
  • Schedules LightCullingJob (Burst parallel) over enabled effect instances.
  • Schedules SortAndBuildPunctualLightsJob which dequeues visible lights, sorts by distance and writes HDRP-visible arrays (HDRPDotsInputs) and updates m_LastFrameMaxPunctualLightDistance. }}

  • private void ReadDefaultLightParams()
    {{ Creates a temporary GameObject and HD Additional Light to read default HD parameters (shapeWidth, shapeHeight, spotIESCutoffPercent01, shapeRadius). Destroys the temporary object. Used to fill s_DefaultLightParams so the system has sensible defaults. }}

  • private UnityEngine.Rendering.HighDefinition.SpotLightShape GetUnitySpotShape(Game.Rendering.SpotLightShape spotlightShape)
    {{ Maps the game's SpotLightShape enum to HDRP's SpotLightShape enum (Pyramid/Box/Cone). Returns Cone by default. }}

  • private UnityEngine.Rendering.HighDefinition.AreaLightShape GetUnityAreaShape(Game.Rendering.AreaLightShape arealightShape)
    {{ Maps the game's AreaLightShape enum to HDRP's AreaLightShape enum (Tube/Rectangle). Returns Rectangle by default. }}

  • private void GetRenderDataFromLigthEffet(ref HDLightRenderData hdLightRenderData, LightEffectData lightEffectData, LightEffect lightEffect, float4 lodParameters)
    {{ Fills an HDLightRenderData structure from the game's LightEffect and LightEffectData plus LOD parameters. Copies many parameters (range, spot angle, shapes, dims, volumetric settings, shape size, barn door, etc.) and sets various HDRP flags (disable ray-traced shadows, screen-space shadows, interactions with sky etc.) This is used to populate HDRPDotsInputs.s_HdLightRenderData per prefab index. }}

  • private void ComputeLightEffectCullData(float4 lodParameters)
    {{ Rebuilds the m_LightEffectCullData map:

  • Clears the current map.
  • Iterates archetype chunks from m_LightEffectPrefabQuery to access all prefab entities with LightEffectData and PrefabData.
  • For each prefab entity, fetches the EffectPrefab and its LightEffect component, computes the inv-distance factor (scaled by lodParameters), reserves a slot in HDRPDotsInputs.s_lightEffectPrefabData/s_hDLightRenderData and fills it using GetRenderDataFromLigthEffet.
  • Populates m_LightEffectCullData with LightEffectCullData mapping for each prefab entity. This is executed on the main thread (not in a job) and completes dependencies before accessing archetype chunks. }}

  • private static GPULightType GetGPULightType(LightEffect lightEffect)
    {{ Helper that maps Game.Rendering.LightType + shapes to an internal GPULightType enum used by GPU light consumers (Spot, ProjectorPyramid, ProjectorBox, Point, Rectangle, Tube). Throws NotImplementedException for unknown combinations. }}

  • (Nested/Burst job) private struct LightCullingJob : IJobParallelForDefer
    {{ Burst compiled parallel job: iterates enabled effect instances (EnabledEffectData) and performs:

  • Checks effect flags to ensure instance is enabled and is a light.
  • Performs frustum plane early-reject using prefab range from m_LightEffectCullData.
  • Computes a relative distance using RenderingUtils.CalculateMinDistance (with Bounds3, camera pos/dir, LOD parameters) multiplied by prefab inv-distance factor.
  • If relative distance < m_AutoRejectDistance, enqueues a VisibleLightData to m_VisibleLights queue. It uses DeallocateOnJobCompletion for the plane array and reads m_EnabledEffectData as a deferred list. }}

  • (Nested/Burst job) private struct SortAndBuildPunctualLightsJob : IJob
    {{ Single-threaded job that:

  • Dequeues all VisibleLightData from the m_VisibleLights queue into a temporary list.
  • Splits near/far lists relative to a minDistance threshold (m_MaxDistance.Value * m_minDistanceScale) for prioritization.
  • Sorts near list by m_RelativeDistance (custom comparer using unsafe pointer into the array), then selects up to m_maxLights items.
  • Writes VisibleLight objects into m_VisibleLightsOut (native array expected by HDRP), populates m_PunctualLightsOut and m_LightEffectPrefabData arrays and HDRPDotsInputs.s_lightEffectPrefabData entries (cookie mode/other defaults).
  • Updates m_MaxDistance (native reference) with the maximum relative distance of the written lights (used next frame for optimization).
  • Disposes temporaries. The job prepares the compacted set that HDRP will consume for rendering punctual lights. }}

  • private void __AssignQueries(ref SystemState state) and protected override void OnCreateForCompiler()
    {{ Internal generator/IL2CPP/Entities scaffolding methods used by the ECS codegen/compilation pipeline to set up queries and type handles. Not intended for direct use. }}

Usage Example

// LightCullingSystem is created/managed by the ECS world. Typical usage is to tune static fields
// or to rely on the system running automatically each frame.

// Example: Disable the min/max distance optimization at runtime:
Game.Effects.LightCullingSystem.s_enableMinMaxLightCullingOptim = false;

// Example: Increase maximum search scale (makes previous frame distance less strict)
Game.Effects.LightCullingSystem.s_maxLightDistanceScale = 2.0f;

// If you need to force one frame's rebuild or debug, you can get the system and call complete on its job handles:
var world = World.DefaultGameObjectInjectionWorld;
var lightCulling = world.GetExistingSystemManaged<Game.Effects.LightCullingSystem>();
// The system itself will run in its OnUpdate automatically each frame; avoid calling internal jobs directly.

Notes and implementation considerations: - The system relies on HDRPDotsInputs global buffers — ensure compatibility if modding or replacing HDRP light ingestion. - Be careful with native allocations: the system holds persistent Native containers and completes HDRPDotsInputs.punctualLightsJobHandle in OnDestroy and at the start of OnUpdate. - The distance-based optimization is frame-dependent (uses m_LastFrameMaxPunctualLightDistance). If you see popping when teleporting the camera or large camera jumps, try toggling s_enableMinMaxLightCullingOptim to false. - The code maps game light shapes to HDRP shapes and deliberately disables certain HDRP shadow features to match the game's expected rendering pipeline (raytrace/SS shadows disabled).