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), );
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)

58
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; }

43
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;

Loading…
Cancel
Save