Skip to content

Game.Rendering.LightUtils

Assembly: Game
Namespace: Game.Rendering

Type: public static class LightUtils

Base: System.Object (static utility class)

Summary:
Utility helper for converting between different photometric and radiometric light units used by the game (Lumen, Candela, Lux, Ev100, Nits/luminance) for punctual (point/spot/frustum), area (rectangle/tube) and line lights. Provides formulas for solid-angle based conversions, area luminance conversions, and helpers to convert with a distance or spot geometry. Several routines rely on ColorUtils.s_LightMeterCalibrationConstant for EV <-> luminance conversions.


Fields

  • private static float s_LuminanceToEvFactor
    Calculated factor used when converting luminance (candela) to Ev (EV100). It equals Log2(100 / ColorUtils.s_LightMeterCalibrationConstant). Used to offset the base-2 log when computing EV100 from luminance.

  • private static float s_EvToLuminanceFactor
    The negative of s_LuminanceToEvFactor (i.e. -Log2(100 / ColorUtils.s_LightMeterCalibrationConstant)). Used when converting EV100 back to a luminance (candela).

Properties

  • This class exposes only static methods and contains no public instance or get/set properties.

Constructors

  • This is a static utility class — there are no public constructors or instance constructors.

Methods

  • public static float ConvertSpotLightLumenToCandela(float intensity, float angle, bool exact)
    Converts a spot light's luminous flux (lumen) to luminous intensity (candela).
    Parameters: intensity (lumens), angle (spot cone angle, expected in radians when calling this method directly), exact (if false a simplified approximation is used).
    Behavior: If exact == false returns intensity / π. If exact == true returns intensity / (2 * (1 - cos(angle/2)) * π) — i.e. lumen divided by the spot cone solid angle.

  • public static float ConvertFrustrumLightLumenToCandela(float intensity, float angleA, float angleB)
    Converts frustum/pyramid-shaped spot lumen to candela using solid angle = 4 * asin(sin(angleA/2) * sin(angleB/2)). Angles are in radians.

  • public static float ConvertPunctualLightLumenToCandela(LightType lightType, float lumen, float initialIntensity, bool enableSpotReflector)
    Dispatch helper that returns candela for a punctual light. For Spot with enableSpotReflector = true it returns initialIntensity (the editor already provides a candela-like value); otherwise falls back to point light formula.

  • public static float ConvertPointLightLumenToCandela(float intensity)
    Converts spherical point light lumen -> candela by dividing by total solid angle of a sphere: intensity / (4π).

  • public static float ConvertPunctualLightLumenToLux(LightType lightType, float lumen, float initialIntensity, bool enableSpotReflector, float distance)
    Converts punctual light lumen -> lux at a given distance. Internally converts lumen->candela then candela->lux. Distance is in meters; lux = candela / distance^2.

  • public static float ConvertCandelaToLux(float candela, float distance)
    Converts luminous intensity (candela) to illuminance (lux) at a distance: lux = candela / (distance^2).

  • public static float ConvertPunctualLightLumenToEv(LightType lightType, float lumen, float initialIntensity, bool enableSpotReflector)
    Converts lumen to EV100 for a punctual light. Internally converts to candela then to EV using log2.

  • public static float ConvertCandelaToEv(float candela)
    Converts candela (treated as luminance here) to EV100 via ConvertLuminanceToEv.

  • public static float ConvertLuminanceToEv(float luminance)
    Converts luminance (candela units used as the luminance value) to EV100: EV = log2(luminance) + s_LuminanceToEvFactor. Uses base-2 logarithm.

  • public static float ConvertPunctualLightCandelaToLumen(LightType lightType, SpotLightShape spotLightShape, float candela, bool enableSpotReflector, float spotAngle, float aspectRatio)
    Converts a punctual light's candela back to lumen. For Spot + enableSpotReflector it branches by spot shape:

  • Cone: calls ConvertSpotLightCandelaToLumen, expects spotAngle in radians (the method that calls this converts degrees->radians).
  • Pyramid: calculates axis angles from aspect ratio then uses frustum conversion.
  • Default: uses point light formula.

  • public static float ConvertSpotLightCandelaToLumen(float intensity, float angle, bool exact)
    Inverse of ConvertSpotLightLumenToCandela. If exact==false multiplies by π. If exact==true multiplies by solid angle: intensity * (2 * (1 - cos(angle/2)) * π). Angle expects radians.

  • public static float ConvertFrustrumLightCandelaToLumen(float intensity, float angleA, float angleB)
    Inverse of frustum candela->lumen: intensity * (4 * asin(sin(angleA/2) * sin(angleB/2))). Angles in radians.

  • public static float ConvertPointLightCandelaToLumen(float intensity)
    Inverse of point light: intensity * (4π).

  • public static void CalculateAnglesForPyramid(float aspectRatio, float spotAngle, out float angleA, out float angleB)
    Given a pyramid spotAngle (in radians) and aspect ratio, calculates the two opening angles for the pyramid frustum. If aspectRatio < 1 it inverts it (so the wider side is handled). angleA is the provided spotAngle; angleB is computed from tan relationships.

  • public static float ConvertPunctualLightLuxToLumen(LightType lightType, SpotLightShape spotLightShape, float lux, bool enableSpotReflector, float spotAngle, float aspectRatio, float distance)
    Converts illuminance (lux) at distance back to lumen by converting lux->candela (lux * d^2) then candela->lumen using ConvertPunctualLightCandelaToLumen.

  • public static float ConvertLuxToCandela(float lux, float distance)
    Converts lux to candela: candela = lux * distance^2.

  • public static float ConvertLuxToEv(float lux, float distance)
    Converts lux at distance to EV100 by converting to candela then to EV via ConvertLuminanceToEv.

  • public static float ConvertPunctualLightEvToLumen(LightType lightType, SpotLightShape spotLightShape, float ev, bool enableSpotReflector, float spotAngle, float aspectRatio)
    Converts EV100 to lumen for punctual lights: ev -> candela -> lumen (taking into account spot shape/reflector).

  • public static float ConvertEvToCandela(float ev)
    Converts EV100 to luminance/candela via ConvertEvToLuminance.

  • public static float ConvertEvToLuminance(float ev)
    Converts EV100 to luminance: luminance = 2^(ev + s_EvToLuminanceFactor).

  • public static float ConvertEvToLux(float ev, float distance)
    Converts EV100 to lux at a distance by converting EV->candela (luminance) then candela->lux.

  • public static float ConvertAreaLightLumenToLuminance(AreaLightShape areaLightShape, float lumen, float width, float height = 0f)
    Converts area light lumen to luminance (nits) depending on shape:

  • Tube -> CalculateLineLightLumenToLuminance
  • Rectangle -> ConvertRectLightLumenToLuminance
  • Default -> returns lumen as-is

  • public static float ConvertRectLightLumenToLuminance(float intensity, float width, float height)
    Rectangle area luminance: intensity / (width * height * π). (π factor converts to radiometric convention used in game.)

  • public static float CalculateLineLightLumenToLuminance(float intensity, float lineWidth)
    Tube/line light lumen -> luminance: intensity / (π * 4 * lineWidth).

  • public static float ConvertAreaLightLuminanceToLumen(AreaLightShape areaLightShape, float luminance, float width, float height = 0f)
    Inverse of ConvertAreaLightLumenToLuminance. Dispatches by AreaLightShape:

  • Tube -> CalculateLineLightLuminanceToLumen
  • Rectangle -> ConvertRectLightLuminanceToLumen

  • public static float CalculateLineLightLuminanceToLumen(float intensity, float lineWidth)
    Inverse for tube: intensity * (π * 4 * lineWidth).

  • public static float ConvertRectLightLuminanceToLumen(float intensity, float width, float height)
    Inverse for rectangle: intensity * (width * height * π).

  • public static float ConvertAreaLightEvToLumen(AreaLightShape AreaLightShape, float ev, float width, float height)
    Converts EV100 for area light -> luminance -> lumen by calling ConvertEvToLuminance then ConvertAreaLightLuminanceToLumen.

  • public static float ConvertAreaLightLumenToEv(AreaLightShape AreaLightShape, float lumen, float width, float height)
    Converts area lumen -> luminance -> EV100 via ConvertAreaLightLumenToLuminance then ConvertLuminanceToEv.

  • public static float ConvertLightIntensity(LightUnit oldLightUnit, LightUnit newLightUnit, LightEffect editor, float intensity)
    High-level helper used by the editor to convert an editor-supplied intensity value between LightUnit enums (Lumen, Candela, Lux, Ev100, Nits). Uses LightEffect editor fields (m_Type, m_EnableSpotReflector, m_SpotShape, m_SpotAngle, m_AspectRatio, m_LuxAtDistance, m_AreaShape, m_ShapeWidth, m_ShapeHeight) to perform context-aware conversions depending on whether the light is punctual or area. Returns the converted intensity.

Notes: - Angles: low-level methods ConvertSpotLight... and frustum methods expect angles in radians. The editor-level conversion (ConvertPunctualLightCandelaToLumen) converts spotAngle from degrees to radians before calling the low-level routines. So when calling low-level spot/frustum methods directly, pass radians. - Distances: distances are in world units (meters). Lux/candela conversions assume inverse-square law: lux = candela / distance^2. - EV conversions: depend on ColorUtils.s_LightMeterCalibrationConstant. Changing that calibration constant will shift EV <-> luminance mappings. - Units: - Lumen: total luminous flux (lm) - Candela: luminous intensity (cd) - Lux: illuminance at a surface (lx) - Nits / luminance: cd/m^2 - Ev / EV100: photographic exposure value normalized to ISO 100

Usage Example

// Convert a 1200 lumen point light to candela and lux at 2 meters:
float lumens = 1200f;
float candela = LightUtils.ConvertPointLightLumenToCandela(lumens); // lumens / (4*pi)
float luxAt2m = LightUtils.ConvertCandelaToLux(candela, 2f);        // candela / (2^2)

// Convert a spot defined in the editor from lumen -> candela (editor uses degrees for spotAngle)
LightEffect editor = /* existing LightEffect with m_Type = LightType.Spot */;
float lumenValue = 800f;
float candelaFromEditor = LightUtils.ConvertPunctualLightLumenToCandela(editor.m_Type, lumenValue, lumenValue, editor.m_EnableSpotReflector);

If you want, I can also provide a short cheat-sheet table summarizing the main formulas (point/spot/frustum/area and EV conversions).