diff --git a/src/Magnum/Trade/LightData.cpp b/src/Magnum/Trade/LightData.cpp index 298915c8c..ff37ec519 100644 --- a/src/Magnum/Trade/LightData.cpp +++ b/src/Magnum/Trade/LightData.cpp @@ -34,10 +34,10 @@ LightData::LightData(const Type type, const Color3& color, const Float intensity "Trade::LightData: spot light inner and outer cone angles have to be in range [0°, 360°] and inner not larger than outer but got" << Deg(_innerConeAngle) << "and" << Deg(_outerConeAngle), ); CORRADE_ASSERT(_type == Type::Spot || (Math::equal(Deg(_innerConeAngle),360.0_degf) && Math::equal(Deg(_outerConeAngle), 360.0_degf)), "Trade::LightData: cone angles have to be 360° for lights that aren't spot but got" << Deg(_innerConeAngle) << "and" << Deg(_outerConeAngle), ); - CORRADE_ASSERT(_type != Type::Directional || (_attenuation == Vector3{1.0f, 0.0f, 0.0f}), - "Trade::LightData: attenuation has to be (1, 0, 0) for a directional light but got" << _attenuation, ); - CORRADE_ASSERT(_type != Type::Directional || _range == Constants::inf(), - "Trade::LightData: range has to be infinity for a directional light but got" << _range, ); + CORRADE_ASSERT((_type != Type::Ambient && _type != Type::Directional) || (_attenuation == Vector3{1.0f, 0.0f, 0.0f}), + "Trade::LightData: attenuation has to be (1, 0, 0) for an ambient or directional light but got" << _attenuation, ); + CORRADE_ASSERT((_type != Type::Ambient && _type != Type::Directional) || _range == Constants::inf(), + "Trade::LightData: range has to be infinity for an ambient or directional light but got" << _range, ); } LightData::LightData(const Type type, const Color3& color, const Float intensity, const Vector3& attenuation, const Float range, const void* const importerState) noexcept: LightData{type, color, intensity, attenuation, range, @@ -50,11 +50,13 @@ LightData::LightData(const Type type, const Color3& color, const Float intensity LightData::LightData(const Type type, const Color3& color, const Float intensity, const Vector3& attenuation, const void* const importerState) noexcept: LightData{type, color, intensity, attenuation, Constants::inf(), importerState} {} LightData::LightData(const Type type, const Color3& color, const Float intensity, const Float range, const Rad innerConeAngle, const Rad outerConeAngle, const void* const importerState) noexcept: LightData{type, color, intensity, - type == Type::Directional ? Vector3{1.0f, 0.0f, 0.0f} : Vector3{0.0f, 0.0f, 1.0f}, + type == Type::Ambient || type == Type::Directional ? + Vector3{1.0f, 0.0f, 0.0f} : Vector3{0.0f, 0.0f, 1.0f}, range, innerConeAngle, outerConeAngle, importerState} {} LightData::LightData(const Type type, const Color3& color, const Float intensity, const Float range, const void* const importerState) noexcept: LightData{type, color, intensity, - type == Type::Directional ? Vector3{1.0f, 0.0f, 0.0f} : Vector3{0.0f, 0.0f, 1.0f}, + type == Type::Ambient || type == Type::Directional ? + Vector3{1.0f, 0.0f, 0.0f} : Vector3{0.0f, 0.0f, 1.0f}, range, importerState} {} LightData::LightData(const Type type, const Color3& color, const Float intensity, const Rad innerConeAngle, const Rad outerConeAngle, const void* const importerState) noexcept: LightData{type, color, intensity, Constants::inf(), innerConeAngle, outerConeAngle, importerState} {} @@ -68,6 +70,7 @@ Debug& operator<<(Debug& debug, const LightData::Type value) { switch(value) { /* LCOV_EXCL_START */ #define _c(value) case LightData::Type::value: return debug << "::" #value; + _c(Ambient) _c(Directional) _c(Point) _c(Spot) diff --git a/src/Magnum/Trade/LightData.h b/src/Magnum/Trade/LightData.h index 18f41c9c1..a4095953d 100644 --- a/src/Magnum/Trade/LightData.h +++ b/src/Magnum/Trade/LightData.h @@ -122,6 +122,16 @@ class MAGNUM_TRADE_EXPORT LightData { * @see @ref type() */ enum class Type: UnsignedByte { + /* Zero reserved for an invalid value */ + + /** + * Ambient light, without any position, direction or attenuation. + * Meant to be added to ambient color in Phong workflows, has no + * use in physically based workflows. + * @m_since_latest + */ + Ambient = 1, + /** * Light at a position that is infinitely far away, emitted in a * direction of negative Z axis. The rotation is inherited from @@ -166,10 +176,10 @@ class MAGNUM_TRADE_EXPORT LightData { * @param intensity Light intensity * @param attenuation Constant, linear and quadratic light * attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce - * for a @ref Type::Directional light. + * for an @ref Type::Ambient and @ref Type::Directional light. * @param range Light range, after which the intensity is * considered to be zero. Expected to be @ref Constants::inf() for - * a @ref Type::Directional light. + * an @ref Type::Ambient and @ref Type::Directional light. * @param innerConeAngle Inner cone angle. Expected to be greater * than or equal to @cpp 0.0_degf @ce and less than or equal to * @p outerConeAngle for a @ref Type::Spot light, @@ -203,10 +213,10 @@ class MAGNUM_TRADE_EXPORT LightData { * @param intensity Light intensity * @param attenuation Constant, linear and quadratic light * attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce - * for a @ref Type::Directional light. + * for an @ref Type::Ambient and @ref Type::Directional light. * @param range Light range, after which the intensity is * considered to be zero. Expected to be @ref Constants::inf() for - * a @ref Type::Directional light. + * an @ref Type::Ambient and @ref Type::Directional light. * @param importerState Importer-specific state * @m_since_latest * @@ -234,7 +244,7 @@ class MAGNUM_TRADE_EXPORT LightData { * @param intensity Light intensity * @param attenuation Constant, linear and quadratic light * attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce - * for a @ref Type::Directional light. + * for an @ref Type::Ambient and @ref Type::Directional light. * @param innerConeAngle Inner cone angle. Expected to be greater * than or equal to @cpp 0.0_degf @ce and less than or equal to * @p outerConeAngle for a @ref Type::Spot light, @@ -262,7 +272,7 @@ class MAGNUM_TRADE_EXPORT LightData { * @param intensity Light intensity * @param attenuation Constant, linear and quadratic light * attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce - * for a @ref Type::Directional light. + * for an @ref Type::Ambient and @ref Type::Directional light. * @param importerState Importer-specific state * @m_since_latest * @@ -284,7 +294,7 @@ class MAGNUM_TRADE_EXPORT LightData { * @param intensity Light intensity * @param range Light range, after which the intensity is * considered to be zero. Expected to be @ref Constants::inf() for - * a @ref Type::Directional light. + * an @ref Type::Ambient and @ref Type::Directional light. * @param innerConeAngle Inner cone angle. Expected to be greater * than or equal to @cpp 0.0_degf @ce and less than or equal to * @p outerConeAngle for a @ref Type::Spot light, @@ -298,8 +308,9 @@ class MAGNUM_TRADE_EXPORT LightData { * * The @ref attenuation() is implicitly set to @cpp {0.0f, 0.0f, 1.0f} @ce * for a @ref Type::Point and @ref Type::Spot light and to - * @cpp {1.0f, 0.0f, 0.0f} @ce for a @ref Type::Directional light. See - * @ref Trade-LightData-attenuation for more information. + * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and + * @ref Type::Directional light. See @ref Trade-LightData-attenuation + * for more information. * * For lights other than spot it may be more convenient to use * @ref LightData(Type, const Color3&, Float, Float, const void*) @@ -314,14 +325,15 @@ class MAGNUM_TRADE_EXPORT LightData { * @param intensity Light intensity * @param range Light range, after which the intensity is * considered to be zero. Expected to be @ref Constants::inf() for - * a @ref Type::Directional light. + * an @ref Type::Ambient and @ref Type::Directional light. * @param importerState Importer-specific state * @m_since_latest * * The @ref attenuation() is implicitly set to @cpp {0.0f, 0.0f, 1.0f} @ce * for a @ref Type::Point and @ref Type::Spot light and to - * @cpp {1.0f, 0.0f, 0.0f} @ce for a @ref Type::Directional light. See - * @ref Trade-LightData-attenuation for more information. + * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and + * @ref Type::Directional light. See @ref Trade-LightData-attenuation + * for more information. * * For a @ref Type::Spot light, @ref innerConeAngle() is implicitly set * to @cpp 0.0_degf @ce and @ref outerConeAngle() to @cpp 45.0_degf @ce, @@ -349,9 +361,10 @@ class MAGNUM_TRADE_EXPORT LightData { * * The @ref attenuation() is implicitly set to @cpp {0.0f, 0.0f, 1.0f} @ce * for a @ref Type::Point and @ref Type::Spot light and to - * @cpp {1.0f, 0.0f, 0.0f} @ce for a @ref Type::Directional light; - * @ref range() is always @ref Constants::inf(). See - * @ref Trade-LightData-attenuation for more information. + * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and + * @ref Type::Directional light; @ref range() is always + * @ref Constants::inf(). See @ref Trade-LightData-attenuation for more + * information. * * For lights other than spot it may be more convenient to use * @ref LightData(Type, const Color3&, Float, const void*) instead. @@ -367,9 +380,10 @@ class MAGNUM_TRADE_EXPORT LightData { * * The @ref attenuation() is implicitly set to @cpp {0.0f, 0.0f, 1.0f} @ce * for a @ref Type::Point and @ref Type::Spot light and to - * @cpp {1.0f, 0.0f, 0.0f} @ce for a @ref Type::Directional light; - * @ref range() is always @ref Constants::inf(). See - * @ref Trade-LightData-attenuation for more information. + * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and + * @ref Type::Directional light; @ref range() is always + * @ref Constants::inf(). See @ref Trade-LightData-attenuation for more + * information. * * For a @ref Type::Spot light, @ref innerConeAngle() is implicitly set * to @cpp 0.0_degf @ce and @ref outerConeAngle() to @cpp 45.0_degf @ce, @@ -413,10 +427,10 @@ class MAGNUM_TRADE_EXPORT LightData { * Values of @f$ \color{m-success} K_c @f$, * @f$ \color{m-success} K_l @f$ and @f$ \color{m-success} K_q @f$ in * the @ref Trade-LightData-attenuation "attenuation equation". Always - * @cpp {1.0f, 0.0f, 0.0f} @ce for a @ref Type::Directional - * light, set to @cpp {0.0f, 0.0f, 1.0f} @ce for range-based - * attenuation --- and if @ref range() is @ref Constants::inf() as - * well, the attenuation equation is simply + * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and + * @ref Type::Directional light, set to @cpp {0.0f, 0.0f, 1.0f} @ce for + * range-based attenuation --- and if @ref range() is + * @ref Constants::inf() as well, the attenuation equation is simply * @f$ F_{att} = \frac{1}{d^2} @f$. */ Vector3 attenuation() const { return _attenuation; } diff --git a/src/Magnum/Trade/Test/LightDataTest.cpp b/src/Magnum/Trade/Test/LightDataTest.cpp index f471f4c58..d3fdddde5 100644 --- a/src/Magnum/Trade/Test/LightDataTest.cpp +++ b/src/Magnum/Trade/Test/LightDataTest.cpp @@ -59,12 +59,18 @@ const struct { Rad outerConeAngle; const char* message; } ConstructInvalidData[] { + {"invalid ambient attenuation", LightData::Type::Ambient, + {0.0f, 0.0f, 1.0f}, Constants::inf(), 360.0_degf, 360.0_degf, + "attenuation has to be (1, 0, 0) for an ambient or directional light but got Vector(0, 0, 1)"}, {"invalid directional attenuation", LightData::Type::Directional, {0.0f, 0.0f, 1.0f}, Constants::inf(), 360.0_degf, 360.0_degf, - "attenuation has to be (1, 0, 0) for a directional light but got Vector(0, 0, 1)"}, + "attenuation has to be (1, 0, 0) for an ambient or directional light but got Vector(0, 0, 1)"}, + {"invalid ambient range", LightData::Type::Ambient, + {1.0f, 0.0f, 0.0f}, 2.0f, 360.0_degf, 360.0_degf, + "range has to be infinity for an ambient or directional light but got 2"}, {"invalid directional range", LightData::Type::Directional, {1.0f, 0.0f, 0.0f}, 2.0f, 360.0_degf, 360.0_degf, - "range has to be infinity for a directional light but got 2"}, + "range has to be infinity for an ambient or directional light but got 2"}, {"invalid point angles", LightData::Type::Point, {0.0f, 0.0f, 1.0f}, Constants::inf(), 15.0_degf, 90.0_degf, "cone angles have to be 360° for lights that aren't spot but got Deg(15) and Deg(90)"}, @@ -256,6 +262,23 @@ void LightDataTest::constructRange() { CORRADE_COMPARE(data.outerConeAngle(), 360.0_degf); CORRADE_COMPARE(data.importerState(), &a); + /* Implicit attenuation for an ambient + non-spot angles */ + } { + int a; + LightData data{LightData::Type::Ambient, + 0xccff33_rgbf, 0.8f, + Constants::inf(), + &a}; + + CORRADE_COMPARE(data.type(), LightData::Type::Ambient); + CORRADE_COMPARE(data.color(), 0xccff33_rgbf); + CORRADE_COMPARE(data.intensity(), 0.8f); + CORRADE_COMPARE(data.attenuation(), (Vector3{1.0f, 0.0f, 0.0f})); + CORRADE_COMPARE(data.range(), Constants::inf()); + CORRADE_COMPARE(data.innerConeAngle(), 360.0_degf); + CORRADE_COMPARE(data.outerConeAngle(), 360.0_degf); + CORRADE_COMPARE(data.importerState(), &a); + /* Implicit attenuation for a directional + non-spot angles */ } { int a; @@ -325,6 +348,22 @@ void LightDataTest::constructNone() { CORRADE_COMPARE(data.outerConeAngle(), 360.0_degf); CORRADE_COMPARE(data.importerState(), &a); + /* Implicit attenuation for an ambient + non-spot angles */ + } { + int a; + LightData data{LightData::Type::Ambient, + 0xccff33_rgbf, 0.8f, + &a}; + + CORRADE_COMPARE(data.type(), LightData::Type::Ambient); + CORRADE_COMPARE(data.color(), 0xccff33_rgbf); + CORRADE_COMPARE(data.intensity(), 0.8f); + CORRADE_COMPARE(data.attenuation(), (Vector3{1.0f, 0.0f, 0.0f})); + CORRADE_COMPARE(data.range(), Constants::inf()); + CORRADE_COMPARE(data.innerConeAngle(), 360.0_degf); + CORRADE_COMPARE(data.outerConeAngle(), 360.0_degf); + CORRADE_COMPARE(data.importerState(), &a); + /* Implicit attenuation for a directional + non-spot angles */ } { int a;