Browse Source

Trade: add ambient light type as well.

At first I thought it could be done with a point light and a (1, 0, 0)
attenuation, but that still has a direction, so no.
pull/470/head
Vladimír Vondruš 6 years ago
parent
commit
d1949a4941
  1. 15
      src/Magnum/Trade/LightData.cpp
  2. 58
      src/Magnum/Trade/LightData.h
  3. 43
      src/Magnum/Trade/Test/LightDataTest.cpp

15
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), ); "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)), 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), ); "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}), 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 a directional light but got" << _attenuation, ); "Trade::LightData: attenuation has to be (1, 0, 0) for an ambient or directional light but got" << _attenuation, );
CORRADE_ASSERT(_type != Type::Directional || _range == Constants::inf(), CORRADE_ASSERT((_type != Type::Ambient && _type != Type::Directional) || _range == Constants::inf(),
"Trade::LightData: range has to be infinity for a directional light but got" << _range, ); "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, 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 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, 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} {} 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, 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} {} 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} {} 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) { switch(value) {
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */
#define _c(value) case LightData::Type::value: return debug << "::" #value; #define _c(value) case LightData::Type::value: return debug << "::" #value;
_c(Ambient)
_c(Directional) _c(Directional)
_c(Point) _c(Point)
_c(Spot) _c(Spot)

58
src/Magnum/Trade/LightData.h

@ -122,6 +122,16 @@ class MAGNUM_TRADE_EXPORT LightData {
* @see @ref type() * @see @ref type()
*/ */
enum class Type: UnsignedByte { 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 * Light at a position that is infinitely far away, emitted in a
* direction of negative Z axis. The rotation is inherited from * direction of negative Z axis. The rotation is inherited from
@ -166,10 +176,10 @@ class MAGNUM_TRADE_EXPORT LightData {
* @param intensity Light intensity * @param intensity Light intensity
* @param attenuation Constant, linear and quadratic light * @param attenuation Constant, linear and quadratic light
* attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce * 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 * @param range Light range, after which the intensity is
* considered to be zero. Expected to be @ref Constants::inf() for * 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 * @param innerConeAngle Inner cone angle. Expected to be greater
* than or equal to @cpp 0.0_degf @ce and less than or equal to * than or equal to @cpp 0.0_degf @ce and less than or equal to
* @p outerConeAngle for a @ref Type::Spot light, * @p outerConeAngle for a @ref Type::Spot light,
@ -203,10 +213,10 @@ class MAGNUM_TRADE_EXPORT LightData {
* @param intensity Light intensity * @param intensity Light intensity
* @param attenuation Constant, linear and quadratic light * @param attenuation Constant, linear and quadratic light
* attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce * 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 * @param range Light range, after which the intensity is
* considered to be zero. Expected to be @ref Constants::inf() for * 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 * @param importerState Importer-specific state
* @m_since_latest * @m_since_latest
* *
@ -234,7 +244,7 @@ class MAGNUM_TRADE_EXPORT LightData {
* @param intensity Light intensity * @param intensity Light intensity
* @param attenuation Constant, linear and quadratic light * @param attenuation Constant, linear and quadratic light
* attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce * 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 * @param innerConeAngle Inner cone angle. Expected to be greater
* than or equal to @cpp 0.0_degf @ce and less than or equal to * than or equal to @cpp 0.0_degf @ce and less than or equal to
* @p outerConeAngle for a @ref Type::Spot light, * @p outerConeAngle for a @ref Type::Spot light,
@ -262,7 +272,7 @@ class MAGNUM_TRADE_EXPORT LightData {
* @param intensity Light intensity * @param intensity Light intensity
* @param attenuation Constant, linear and quadratic light * @param attenuation Constant, linear and quadratic light
* attenuation factor. Expected to be @cpp {1.0f, 0.0f, 0.0f} @ce * 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 * @param importerState Importer-specific state
* @m_since_latest * @m_since_latest
* *
@ -284,7 +294,7 @@ class MAGNUM_TRADE_EXPORT LightData {
* @param intensity Light intensity * @param intensity Light intensity
* @param range Light range, after which the intensity is * @param range Light range, after which the intensity is
* considered to be zero. Expected to be @ref Constants::inf() for * 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 * @param innerConeAngle Inner cone angle. Expected to be greater
* than or equal to @cpp 0.0_degf @ce and less than or equal to * than or equal to @cpp 0.0_degf @ce and less than or equal to
* @p outerConeAngle for a @ref Type::Spot light, * @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 * 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 * 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 * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and
* @ref Trade-LightData-attenuation for more information. * @ref Type::Directional light. See @ref Trade-LightData-attenuation
* for more information.
* *
* For lights other than spot it may be more convenient to use * For lights other than spot it may be more convenient to use
* @ref LightData(Type, const Color3&, Float, Float, const void*) * @ref LightData(Type, const Color3&, Float, Float, const void*)
@ -314,14 +325,15 @@ class MAGNUM_TRADE_EXPORT LightData {
* @param intensity Light intensity * @param intensity Light intensity
* @param range Light range, after which the intensity is * @param range Light range, after which the intensity is
* considered to be zero. Expected to be @ref Constants::inf() for * 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 * @param importerState Importer-specific state
* @m_since_latest * @m_since_latest
* *
* The @ref attenuation() is implicitly set to @cpp {0.0f, 0.0f, 1.0f} @ce * 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 * 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 * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and
* @ref Trade-LightData-attenuation for more information. * @ref Type::Directional light. See @ref Trade-LightData-attenuation
* for more information.
* *
* For a @ref Type::Spot light, @ref innerConeAngle() is implicitly set * 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, * 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 * 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 * 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; * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and
* @ref range() is always @ref Constants::inf(). See * @ref Type::Directional light; @ref range() is always
* @ref Trade-LightData-attenuation for more information. * @ref Constants::inf(). See @ref Trade-LightData-attenuation for more
* information.
* *
* For lights other than spot it may be more convenient to use * For lights other than spot it may be more convenient to use
* @ref LightData(Type, const Color3&, Float, const void*) instead. * @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 * 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 * 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; * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and
* @ref range() is always @ref Constants::inf(). See * @ref Type::Directional light; @ref range() is always
* @ref Trade-LightData-attenuation for more information. * @ref Constants::inf(). See @ref Trade-LightData-attenuation for more
* information.
* *
* For a @ref Type::Spot light, @ref innerConeAngle() is implicitly set * 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, * 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$, * 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 * @f$ \color{m-success} K_l @f$ and @f$ \color{m-success} K_q @f$ in
* the @ref Trade-LightData-attenuation "attenuation equation". Always * the @ref Trade-LightData-attenuation "attenuation equation". Always
* @cpp {1.0f, 0.0f, 0.0f} @ce for a @ref Type::Directional * @cpp {1.0f, 0.0f, 0.0f} @ce for an @ref Type::Ambient and
* light, set to @cpp {0.0f, 0.0f, 1.0f} @ce for range-based * @ref Type::Directional light, set to @cpp {0.0f, 0.0f, 1.0f} @ce for
* attenuation --- and if @ref range() is @ref Constants::inf() as * range-based attenuation --- and if @ref range() is
* well, the attenuation equation is simply * @ref Constants::inf() as well, the attenuation equation is simply
* @f$ F_{att} = \frac{1}{d^2} @f$. * @f$ F_{att} = \frac{1}{d^2} @f$.
*/ */
Vector3 attenuation() const { return _attenuation; } Vector3 attenuation() const { return _attenuation; }

43
src/Magnum/Trade/Test/LightDataTest.cpp

@ -59,12 +59,18 @@ const struct {
Rad outerConeAngle; Rad outerConeAngle;
const char* message; const char* message;
} ConstructInvalidData[] { } 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, {"invalid directional attenuation", LightData::Type::Directional,
{0.0f, 0.0f, 1.0f}, Constants::inf(), 360.0_degf, 360.0_degf, {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, {"invalid directional range", LightData::Type::Directional,
{1.0f, 0.0f, 0.0f}, 2.0f, 360.0_degf, 360.0_degf, {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, {"invalid point angles", LightData::Type::Point,
{0.0f, 0.0f, 1.0f}, Constants::inf(), 15.0_degf, 90.0_degf, {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)"}, "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.outerConeAngle(), 360.0_degf);
CORRADE_COMPARE(data.importerState(), &a); 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 */ /* Implicit attenuation for a directional + non-spot angles */
} { } {
int a; int a;
@ -325,6 +348,22 @@ void LightDataTest::constructNone() {
CORRADE_COMPARE(data.outerConeAngle(), 360.0_degf); CORRADE_COMPARE(data.outerConeAngle(), 360.0_degf);
CORRADE_COMPARE(data.importerState(), &a); 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 */ /* Implicit attenuation for a directional + non-spot angles */
} { } {
int a; int a;

Loading…
Cancel
Save