Magnum::Trade::LightData class

Light data.

Usage

The class exposes light parameters in a way that makes sense as a whole, allowing to reduce branching in application code — e.g., a light defined by just its range has the quadratic attenuation factor set to one, with constant and linear attenuation being zero, or spot cone angles are the full circle everything except spotlights.

Populating an instance

You can choose a constructor overload that matches the subset of input parameters and let the class set the rest implicitly. For example, a LightType::Point light constructed using a range will have attenuation() implicitly set to {1.0f, 0.0f, 1.0f} and cone angles to 360.0_degf:

Trade::LightData data{Trade::LightType::Point,
    0xfff3d6_srgbf, 1.0f,
    15.0f};

Or, a LightType::Spot light constructed from a constant / linear / quadratic attenuation will have range() implicitly set to Constants::inf():

Trade::LightData data{Trade::LightType::Spot,
    0xf3d6ff_srgbf, 10.0f,
    {0.01f, 0.5f, 2.0f},
    25.0_degf, 55.0_degf};

And a LightType::Directional light that doesn't attenuate can be constructed without either, causing attenuation() to be {1.0f, 0.0f, 0.0f} and range() Constants::inf(), cancelling out the attenuation equation:

Trade::LightData data{Trade::LightType::Directional,
    0xd6fff3_srgbf, 0.25f};

Attenuation calculation

To support all common lighting calculations, the class exposes parameters in a combined equation containing both constant / linear / quadratic attenuation $ \color{m-success} K_c $ / $ \color{m-success} K_l $ / $ \color{m-success} K_q $ and a range parameter $ \color{m-info} R $ over a distance $ d $ :

\[ F_{att} = \frac{\operatorname{clamp}(1 - (\frac{d}{\color{m-info} R})^4, 0, 1)^2}{{\color{m-success} K_c} + {\color{m-success} K_l} d + {\color{m-success} K_q} d^2} \]

In most cases you'll have the light data using either one or the other approach. The classic constant/linear/quadratic equation allows for most control, but because the attenuated intensity never really reaches zero, it makes light culling optimizations hard to perform. In this case the range() is set to Constants::inf():

\[ F_{att} = \lim_{{\color{m-info} R} \to \infty} \frac{{\color{m-dim} \operatorname{clamp}(}1 \mathbin{\color{m-dim}-} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{{\color{m-success} K_c} + {\color{m-success} K_l} d + {\color{m-success} K_q} d^2} = \frac{1}{{\color{m-success} K_c} + {\color{m-success} K_l} d + {\color{m-success} K_q} d^2} \]

The range-based equation approaches zero when $ {\color{m-info} R} = d $ and provides a good tradeoff for performance while staying mostly physically-based. This is modelled after the glTF KHR_lights_punctual extension, which in turn is based on the UE4 implementation. In this case, attenuation() is set to {1.0f, 0.0f, 1.0f}, the constant factor is present in order to prevent the function from exploding to infinity when $ d \to \infty $ .

\[ F_{att} = \frac{\operatorname{clamp}(1 - (\frac{d}{\color{m-info} R})^4, 0, 1)^2}{{\color{m-success} K_c} + {\color{m-dim} K_l d} \mathbin{\color{m-dim} +} {\color{m-success} K_q} d^2} = \frac{\operatorname{clamp}(1 - (\frac{d}{\color{m-info} R})^4, 0, 1)^2}{1 + d^2} \]

If $ {\color{m-info} R} \to \infty $ as well, the equation reduces down to a simple inverse square:

\[ F_{att} = \lim_{{\color{m-info} R} \to \infty} \frac{{\color{m-dim} \operatorname{clamp}(} 1 \mathbin{\color{m-dim} -} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{{\color{m-success} K_c} + {\color{m-dim} K_l d} \mathbin{\color{m-dim} +} {\color{m-success} K_q} d^2} = \frac{1}{1 + d^2} \]

As a special case, a LightType::Directional light is defined by attenuation() set to {1.0f, 0.0f, 0.0f} and range() to Constants::inf() — thus without any attenuation:

\[ F_{att} = \lim_{{\color{m-info} R} \to \infty} \frac{{\color{m-dim} \operatorname{clamp}(} 1 \mathbin{\color{m-dim} -} {\color{m-dim} (\frac{d}{R})^4, 0, 1)^2}}{{\color{m-success} K_c} \mathbin{\color{m-dim} +} {\color{m-dim} K_l d + K_q d^2}} = 1 \]

Units

To follow physically-based principles in lighting calculation, intensity is assumed to be in in candela (lm/sr) for LightType::Point and LightType::Spot, and in lux (lm/m2) for LightType::Directional. Distance $ d $ is in meters.

Public types

using Type = LightType deprecated in Git master
Light type.

Constructors, destructors, conversion operators

LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, Float range, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master
Constructor.
LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, Float range, const void* importerState = nullptr) explicit noexcept new in Git master
Construct with implicit cone angles.
LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master
Construct attenuation-based light data.
LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, const void* importerState = nullptr) explicit noexcept new in Git master
Construct attenuation-based light data with implicit cone angles.
LightData(LightType type, const Color3& color, Float intensity, Float range, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master
Construct range-based light data.
LightData(LightType type, const Color3& color, Float intensity, Float range, const void* importerState = nullptr) explicit noexcept new in Git master
Construct range-based light data with implicit cone angles.
LightData(LightType type, const Color3& color, Float intensity, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master
Construct light data with implicit attenuation.
LightData(LightType type, const Color3& color, Float intensity, const void* importerState = nullptr) explicit noexcept
Construct light data with implicit attenuation and cone angles.
LightData(const LightData&) deleted
Copying is not allowed.
LightData(LightData&&) defaulted noexcept
Move constructor.

Public functions

auto operator=(const LightData&) -> LightData& deleted
Copying is not allowed.
auto operator=(LightData&&) -> LightData& defaulted noexcept
Move assignment.
auto type() const -> LightType
Light type.
auto color() const -> Color3
Light color.
auto intensity() const -> Float
Light intensity.
auto attenuation() const -> Vector3 new in Git master
Constant, linear and quadratic light attenuation.
auto range() const -> Float new in Git master
Light range.
auto innerConeAngle() const -> Rad new in Git master
Inner cone angle.
auto outerConeAngle() const -> Rad new in Git master
Outer cone angle.
auto importerState() const -> const void*
Importer-specific state.

Typedef documentation

typedef LightType Magnum::Trade::LightData::Type

Light type.

Function documentation

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, Float range, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master

Constructor.

Parameters
type Light type
color Light color
intensity Light intensity
attenuation Constant, linear and quadratic light attenuation factor. Expected to be {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light.
range Light range, after which the intensity is considered to be zero. Expected to be Constants::inf() for an LightType::Ambient and LightType::Directional light.
innerConeAngle Inner cone angle. Expected to be greater than or equal to 0.0_degf and less than or equal to outerConeAngle for a LightType::Spot light, 360.0_degf otherwise.
outerConeAngle Outer cone angle. Expected to be greater than or equal to innerConeAngle and less than or equal to 360.0_degf for a LightType::Spot light, 360.0_degf otherwise.
importerState Importer-specific state

This is a combined constructor including both attenuation and range parameters. Use LightData(LightType, const Color3&, Float, const Vector3&, Rad, Rad, const void*) for light data defined by just attenuation parameters and LightData(LightType, const Color3&, Float, Float, Rad, Rad, const void*) for light data defined by a range alone, and LightData(LightType, const Color3&, Float, Rad, Rad, const void*) for an implicit inverse square attenuation. See Attenuation calculation for more information.

For lights other than spot it may be more convenient to use LightData(LightType, const Color3&, Float, const Vector3&, Float, const void*) and friends instead.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, Float range, const void* importerState = nullptr) explicit noexcept new in Git master

Construct with implicit cone angles.

Parameters
type Light type
color Light color
intensity Light intensity
attenuation Constant, linear and quadratic light attenuation factor. Expected to be {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light.
range Light range, after which the intensity is considered to be zero. Expected to be Constants::inf() for an LightType::Ambient and LightType::Directional light.
importerState Importer-specific state

This is a combined constructor including both attenuation and range parameters. Use LightData(LightType, const Color3&, Float, const Vector3&, const void*) for light data defined by just attenuation parameters and LightData(LightType, const Color3&, Float, Float, const void*) for light data defined by a range alone, and LightData(LightType, const Color3&, Float, const void*) for an implicit inverse square attenuation. See Attenuation calculation for more information.

For a LightType::Spot light, innerConeAngle() is implicitly set to 0.0_degf and outerConeAngle() to 90.0_degf, and both are 360.0_degf otherwise. Use LightData(LightType, const Color3&, Float, const Vector3&, Float, Rad, Rad, const void*) in order to specify cone angles as well.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master

Construct attenuation-based light data.

Parameters
type Light type
color Light color
intensity Light intensity
attenuation Constant, linear and quadratic light attenuation factor. Expected to be {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light.
innerConeAngle Inner cone angle. Expected to be greater than or equal to 0.0_degf and less than or equal to outerConeAngle for a LightType::Spot light, 360.0_degf otherwise.
outerConeAngle Inner cone angle. Expected to be greater than or equal to innerConeAngle and less than or equal to 360.0_degf for a LightType::Spot light, 360.0_degf otherwise.
importerState Importer-specific state

The range() is implicitly set to Constants::inf(). See Attenuation calculation for more information.

For lights other than spot it may be more convenient to use LightData(LightType, const Color3&, Float, const Vector3&, const void*) instead.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, const Vector3& attenuation, const void* importerState = nullptr) explicit noexcept new in Git master

Construct attenuation-based light data with implicit cone angles.

Parameters
type Light type
color Light color
intensity Light intensity
attenuation Constant, linear and quadratic light attenuation factor. Expected to be {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light.
importerState Importer-specific state

The range() is implicitly set to Constants::inf(). See Attenuation calculation for more information.

For a LightType::Spot light, innerConeAngle() is implicitly set to 0.0_degf and outerConeAngle() to 90.0_degf, and both are 360.0_degf otherwise. Use LightData(LightType, const Color3&, Float, const Vector3&, Rad, Rad, const void*) in order to specify cone angles as well.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, Float range, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master

Construct range-based light data.

Parameters
type Light type
color Light color
intensity Light intensity
range Light range, after which the intensity is considered to be zero. Expected to be Constants::inf() for an LightType::Ambient and LightType::Directional light.
innerConeAngle Inner cone angle. Expected to be greater than or equal to 0.0_degf and less than or equal to outerConeAngle for a LightType::Spot light, 360.0_degf otherwise.
outerConeAngle Outer cone angle. Expected to be greater than or equal to innerConeAngle and less than or equal to 360.0_degf for a LightType::Spot light, 360.0_degf otherwise.
importerState Importer-specific state

The attenuation() is implicitly set to {1.0f, 0.0f, 1.0f} for a LightType::Point and LightType::Spot light and to {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light. See Attenuation calculation for more information.

For lights other than spot it may be more convenient to use LightData(LightType, const Color3&, Float, Float, const void*) instead.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, Float range, const void* importerState = nullptr) explicit noexcept new in Git master

Construct range-based light data with implicit cone angles.

Parameters
type Light type
color Light color
intensity Light intensity
range Light range, after which the intensity is considered to be zero. Expected to be Constants::inf() for an LightType::Ambient and LightType::Directional light.
importerState Importer-specific state

The attenuation() is implicitly set to {1.0f, 0.0f, 1.0f} for a LightType::Point and LightType::Spot light and to {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light. See Attenuation calculation for more information.

For a LightType::Spot light, innerConeAngle() is implicitly set to 0.0_degf and outerConeAngle() to 90.0_degf, and both are 360.0_degf otherwise. Use LightData(LightType, const Color3&, Float, Float, Rad, Rad, const void*) in order to specify cone angles as well.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, Rad innerConeAngle, Rad outerConeAngle, const void* importerState = nullptr) explicit noexcept new in Git master

Construct light data with implicit attenuation.

Parameters
type Light type
color Light color
intensity Light intensity
innerConeAngle Inner cone angle. Expected to be greater than or equal to 0.0_degf and less than or equal to outerConeAngle for a LightType::Spot light, 360.0_degf otherwise.
outerConeAngle Outer cone angle. Expected to be greater than or equal to innerConeAngle and less than or equal to 360.0_degf for a LightType::Spot light, 360.0_degf otherwise.
importerState Importer-specific state

The attenuation() is implicitly set to {1.0f, 0.0f, 1.0f} for a LightType::Point and LightType::Spot light and to {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light; range() is always Constants::inf(). See Attenuation calculation for more information.

For lights other than spot it may be more convenient to use LightData(LightType, const Color3&, Float, const void*) instead.

Magnum::Trade::LightData::LightData(LightType type, const Color3& color, Float intensity, const void* importerState = nullptr) explicit noexcept

Construct light data with implicit attenuation and cone angles.

Parameters
type Light type
color Light color
intensity Light intensity
importerState Importer-specific state

The attenuation() is implicitly set to {1.0f, 0.0f, 1.0f} for a LightType::Point and LightType::Spot light and to {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light; range() is always Constants::inf(). See Attenuation calculation for more information.

For a LightType::Spot light, innerConeAngle() is implicitly set to 0.0_degf and outerConeAngle() to 90.0_degf, and both are 360.0_degf otherwise. Use LightData(LightType, const Color3&, Float, Rad, Rad, const void*) in order to specify cone angles as well.

Float Magnum::Trade::LightData::intensity() const

Light intensity.

Defined in candela (lm/sr) for LightType::Point and LightType::Spot, and in lux (lm/m2) for LightType::Directional.

Vector3 Magnum::Trade::LightData::attenuation() const new in Git master

Constant, linear and quadratic light attenuation.

Values of $ \color{m-success} K_c $ , $ \color{m-success} K_l $ and $ \color{m-success} K_q $ in the attenuation equation. Always {1.0f, 0.0f, 0.0f} for an LightType::Ambient and LightType::Directional light, set to {1.0f, 0.0f, 1.0f} for range-based attenuation — and if range() is Constants::inf() as well, the attenuation equation is simply $ F_{att} = \frac{1}{1 + d^2} $ .

Float Magnum::Trade::LightData::range() const new in Git master

Light range.

Value of $ \color{m-info} R $ in the attenuation equation. If set to Constants::inf(), then:

  • if attenuation() is {1.0f, 0.0f, 1.0f}, the attenuation equation is $ F_{att} = \frac{1}{1 + d^2} $ ;
  • if attenuation() is {1.0f, 0.0f, 0.0f}, the attenuation equation is $ F_{att} = 1 $ .

The latter is always the case for a LightType::Directional light.

Rad Magnum::Trade::LightData::innerConeAngle() const new in Git master

Inner cone angle.

For a LightType::Spot light, it's always less than outerConeAngle(). For a LightType::Directional or LightType::Point light it's always 360.0_degf.

Rad Magnum::Trade::LightData::outerConeAngle() const new in Git master

Outer cone angle.

For a LightType::Spot light, it's always greater than outerConeAngle() and less than or equal to 90.0_degf. For a LightType::Directional or LightType::Point light it's always 360.0_degf.

const void* Magnum::Trade::LightData::importerState() const

Importer-specific state.

See AbstractImporter::importerState() for more information.