Browse Source

Shaders: support multiple lights in Phong.

pull/284/head
Vladimír Vondruš 8 years ago
parent
commit
b615e1ae28
  1. 1
      doc/changelog.dox
  2. 53
      src/Magnum/Shaders/Phong.cpp
  3. 45
      src/Magnum/Shaders/Phong.frag
  4. 87
      src/Magnum/Shaders/Phong.h
  5. 10
      src/Magnum/Shaders/Phong.vert
  6. 79
      src/Magnum/Shaders/Test/PhongGLTest.cpp

1
doc/changelog.dox

@ -138,6 +138,7 @@ See also:
- New dedicated @ref Shaders::VertexColor::Color3 and - New dedicated @ref Shaders::VertexColor::Color3 and
@ref Shaders::VertexColor::Color4 attribute specifiers for more convenient @ref Shaders::VertexColor::Color4 attribute specifiers for more convenient
distinction between three- and four-component vertex color attribute. distinction between three- and four-component vertex color attribute.
- Support for multiple lights in @ref Shaders::Phong
- Classical alpha masking support in @ref Shaders::Flat and - Classical alpha masking support in @ref Shaders::Flat and
@ref Shaders::Phong @ref Shaders::Phong
- Debug output for the @ref Shaders::Flat::Flag / @ref Shaders::Flat::Flags, - Debug output for the @ref Shaders::Flat::Flag / @ref Shaders::Flat::Flags,

53
src/Magnum/Shaders/Phong.cpp

@ -25,7 +25,11 @@
#include "Phong.h" #include "Phong.h"
#ifdef MAGNUM_TARGET_GLES
#include <Corrade/Containers/Array.h>
#endif
#include <Corrade/Containers/EnumSet.hpp> #include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Utility/Format.h>
#include <Corrade/Utility/Resource.h> #include <Corrade/Utility/Resource.h>
#include "Magnum/GL/Context.h" #include "Magnum/GL/Context.h"
@ -45,7 +49,7 @@ namespace {
}; };
} }
Phong::Phong(const Flags flags): _flags(flags) { Phong::Phong(const Flags flags, const UnsignedInt lightCount): _flags{flags}, _lightCount{lightCount}, _lightColorsUniform{9 + Int(lightCount)} {
#ifdef MAGNUM_BUILD_STATIC #ifdef MAGNUM_BUILD_STATIC
/* Import resources on static build, if not already */ /* Import resources on static build, if not already */
if(!Utility::Resource::hasGroup("MagnumShaders")) if(!Utility::Resource::hasGroup("MagnumShaders"))
@ -62,13 +66,40 @@ Phong::Phong(const Flags flags): _flags(flags) {
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
#ifndef MAGNUM_TARGET_GLES
/* Initializer for the light color array -- we need a list of vec4(1.0)
joined by commas. For GLES we'll simply upload the values directly. */
constexpr const char lightInitializerPreamble[] = "#define LIGHT_COLOR_INITIALIZER ";
constexpr std::size_t lightInitializerPreambleSize =
Containers::arraySize(lightInitializerPreamble) - 1;
constexpr const char lightInitializerItem[] = "vec4(1.0), ";
constexpr std::size_t lightInitializerItemSize =
Containers::arraySize(lightInitializerItem) - 1;
std::string lightInitializer;
lightInitializer.reserve(Containers::arraySize(lightInitializerPreamble) - 1 + lightCount*lightInitializerItemSize);
lightInitializer.append(lightInitializerPreamble, lightInitializerPreambleSize);
for(std::size_t i = 0; i != lightCount; ++i)
lightInitializer.append(lightInitializerItem, lightInitializerItemSize);
/* Drop the last comma and add a newline at the end */
lightInitializer[lightInitializer.size() - 2] = '\n';
lightInitializer.resize(lightInitializer.size() - 1);
#endif
vert.addSource(flags ? "#define TEXTURED\n" : "") vert.addSource(flags ? "#define TEXTURED\n" : "")
.addSource(Utility::formatString("#define LIGHT_COUNT {}\n", lightCount))
.addSource(rs.get("generic.glsl")) .addSource(rs.get("generic.glsl"))
.addSource(rs.get("Phong.vert")); .addSource(rs.get("Phong.vert"));
frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "")
.addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "")
.addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "")
.addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "")
.addSource(Utility::formatString(
"#define LIGHT_COUNT {}\n"
"#define LIGHT_COLORS_LOCATION {}\n", lightCount, 9 + lightCount))
#ifndef MAGNUM_TARGET_GLES
.addSource(std::move(lightInitializer))
#endif
.addSource(rs.get("Phong.frag")); .addSource(rs.get("Phong.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag})); CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
@ -96,13 +127,13 @@ Phong::Phong(const Flags flags): _flags(flags) {
_transformationMatrixUniform = uniformLocation("transformationMatrix"); _transformationMatrixUniform = uniformLocation("transformationMatrix");
_projectionMatrixUniform = uniformLocation("projectionMatrix"); _projectionMatrixUniform = uniformLocation("projectionMatrix");
_normalMatrixUniform = uniformLocation("normalMatrix"); _normalMatrixUniform = uniformLocation("normalMatrix");
_lightPositionUniform = uniformLocation("lightPosition");
_ambientColorUniform = uniformLocation("ambientColor"); _ambientColorUniform = uniformLocation("ambientColor");
_diffuseColorUniform = uniformLocation("diffuseColor"); _diffuseColorUniform = uniformLocation("diffuseColor");
_specularColorUniform = uniformLocation("specularColor"); _specularColorUniform = uniformLocation("specularColor");
_lightColorUniform = uniformLocation("lightColor");
_shininessUniform = uniformLocation("shininess"); _shininessUniform = uniformLocation("shininess");
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
_lightPositionsUniform = uniformLocation("lightPositions");
_lightColorsUniform = uniformLocation("lightColors");
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -121,9 +152,9 @@ Phong::Phong(const Flags flags): _flags(flags) {
else setAmbientColor(Color4{0.0f}); else setAmbientColor(Color4{0.0f});
setDiffuseColor(Color4{1.0f}); setDiffuseColor(Color4{1.0f});
setSpecularColor(Color4{1.0f}); setSpecularColor(Color4{1.0f});
setLightColor(Color4{1.0f});
setShininess(80.0f); setShininess(80.0f);
if(flags & Flag::AlphaMask) setAlphaMask(0.5f); if(flags & Flag::AlphaMask) setAlphaMask(0.5f);
setLightColors(Containers::Array<Color4>{Containers::DirectInit, lightCount, Color4{1.0f}});
setTransformationMatrix({}); setTransformationMatrix({});
setProjectionMatrix({}); setProjectionMatrix({});
@ -174,6 +205,13 @@ Phong& Phong::setLightPositions(const Containers::ArrayView<const Vector3> posit
return *this; return *this;
} }
Phong& Phong::setLightPosition(UnsignedInt id, const Vector3& position) {
CORRADE_ASSERT(id < _lightCount,
"Shaders::Phong::setLightPosition(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this);
setUniform(_lightPositionsUniform + id, position);
return *this;
}
Phong& Phong::setLightColors(const Containers::ArrayView<const Color4> colors) { Phong& Phong::setLightColors(const Containers::ArrayView<const Color4> colors) {
CORRADE_ASSERT(_lightCount == colors.size(), CORRADE_ASSERT(_lightCount == colors.size(),
"Shaders::Phong::setLightColors(): expected" << _lightCount << "items but got" << colors.size(), *this); "Shaders::Phong::setLightColors(): expected" << _lightCount << "items but got" << colors.size(), *this);
@ -181,6 +219,13 @@ Phong& Phong::setLightColors(const Containers::ArrayView<const Color4> colors) {
return *this; return *this;
} }
Phong& Phong::setLightColor(UnsignedInt id, const Color4& color) {
CORRADE_ASSERT(id < _lightCount,
"Shaders::Phong::setLightColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this);
setUniform(_lightColorsUniform + id, color);
return *this;
}
Debug& operator<<(Debug& debug, const Phong::Flag value) { Debug& operator<<(Debug& debug, const Phong::Flag value) {
switch(value) { switch(value) {
/* LCOV_EXCL_START */ /* LCOV_EXCL_START */

45
src/Magnum/Shaders/Phong.frag

@ -88,34 +88,37 @@ uniform lowp vec4 specularColor
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 7) layout(location = 7)
#endif #endif
uniform lowp vec4 lightColor uniform mediump float shininess
#ifndef GL_ES #ifndef GL_ES
= vec4(1.0) = 80.0
#endif #endif
; ;
#ifdef ALPHA_MASK
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 8) layout(location = 8)
#endif #endif
uniform mediump float shininess uniform lowp float alphaMask
#ifndef GL_ES #ifndef GL_ES
= 80.0 = 0.5
#endif #endif
; ;
#endif
#ifdef ALPHA_MASK /* Needs to be last because it uses locations 9 + LIGHT_COUNT to
9 + 2*LIGHT_COUNT - 1. Location 9 is lightPositions. Also it can't be
specified as 9 + LIGHT_COUNT because that requires ARB_enhanced_layouts. */
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 9) layout(location = LIGHT_COLORS_LOCATION) /* I fear this will blow up some drivers */
#endif #endif
uniform lowp float alphaMask uniform lowp vec4 lightColors[LIGHT_COUNT]
#ifndef GL_ES #ifndef GL_ES
= 0.5 = vec4[](LIGHT_COLOR_INITIALIZER)
#endif #endif
; ;
#endif
in mediump vec3 transformedNormal; in mediump vec3 transformedNormal;
in highp vec3 lightDirection; in highp vec3 lightDirections[LIGHT_COUNT];
in highp vec3 cameraDirection; in highp vec3 cameraDirection;
#if defined(AMBIENT_TEXTURE) || defined(DIFFUSE_TEXTURE) || defined(SPECULAR_TEXTURE) #if defined(AMBIENT_TEXTURE) || defined(DIFFUSE_TEXTURE) || defined(SPECULAR_TEXTURE)
@ -147,17 +150,19 @@ void main() {
color = finalAmbientColor; color = finalAmbientColor;
mediump vec3 normalizedTransformedNormal = normalize(transformedNormal); mediump vec3 normalizedTransformedNormal = normalize(transformedNormal);
highp vec3 normalizedLightDirection = normalize(lightDirection);
/* Add diffuse color */
lowp float intensity = max(0.0, dot(normalizedTransformedNormal, normalizedLightDirection));
color += vec4(finalDiffuseColor.rgb*lightColor.rgb*intensity, lightColor.a*finalDiffuseColor.a);
/* Add specular color, if needed */ /* Add diffuse color for each light */
if(intensity > 0.001) { for(int i = 0; i < LIGHT_COUNT; ++i) {
highp vec3 reflection = reflect(-normalizedLightDirection, normalizedTransformedNormal); highp vec3 normalizedLightDirection = normalize(lightDirections[i]);
mediump float specularity = pow(max(0.0, dot(normalize(cameraDirection), reflection)), shininess); lowp float intensity = max(0.0, dot(normalizedTransformedNormal, normalizedLightDirection));
color += vec4(finalSpecularColor.rgb*specularity, finalSpecularColor.a); color += vec4(finalDiffuseColor.rgb*lightColors[i].rgb*intensity, lightColors[i].a*finalDiffuseColor.a);
/* Add specular color, if needed */
if(intensity > 0.001) {
highp vec3 reflection = reflect(-normalizedLightDirection, normalizedTransformedNormal);
mediump float specularity = pow(max(0.0, dot(normalize(cameraDirection), reflection)), shininess);
color += vec4(finalSpecularColor.rgb*specularity, finalSpecularColor.a);
}
} }
#ifdef ALPHA_MASK #ifdef ALPHA_MASK

87
src/Magnum/Shaders/Phong.h

@ -172,9 +172,10 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @param flags Flags
* @param lightCount Count of light sources
*/ */
explicit Phong(Flags flags = {}); explicit Phong(Flags flags = {}, UnsignedInt lightCount = 1);
/** /**
* @brief Construct without creating the underlying OpenGL object * @brief Construct without creating the underlying OpenGL object
@ -203,6 +204,9 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
/** @brief Flags */ /** @brief Flags */
Flags flags() const { return _flags; } Flags flags() const { return _flags; }
/** @brief Light count */
UnsignedInt lightCount() const { return _lightCount; }
/** /**
* @brief Set ambient color * @brief Set ambient color
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
@ -387,42 +391,95 @@ class MAGNUM_SHADERS_EXPORT Phong: public GL::AbstractShaderProgram {
return *this; return *this;
} }
/**
* @brief Set light positions
* @return Reference to self (for method chaining)
*
* Initial values are zero vectors --- that will in most cases cause
* the object to be rendered black (or in the ambient color), as the
* lights are is inside of it. Expects that the size of the @p lights
* array is the same as @ref lightCount().
* @see @ref setLightPosition(UnsignedInt, const Vector3&),
* @ref setLightPosition(const Vector3&)
*/
Phong& setLightPositions(Containers::ArrayView<const Vector3> lights);
/** @overload */
Phong& setLightPositions(std::initializer_list<Vector3> lights) {
return setLightPositions({lights.begin(), lights.size()});
}
/**
* @brief Set position for given light
* @return Reference to self (for method chaining)
*
* Unlike @ref setLightPosition() updates just a single light position.
* Expects that @p id is less than @ref lightCount().
* @see @ref setLightPosition(const Vector3&)
*/
Phong& setLightPosition(UnsignedInt id, const Vector3& position);
/** /**
* @brief Set light position * @brief Set light position
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Initial value is a zero vector --- that will in most cases cause the * Convenience alternative to @ref setLightPositions() when there is
* object to be rendered black (or in the ambient color), as the light * just one light.
* is inside of it. * @see @ref setLightPosition(UnsignedInt, const Vector3&)
*/ */
Phong& setLightPosition(const Vector3& light) { Phong& setLightPosition(const Vector3& position) {
setUniform(_lightPositionUniform, light); return setLightPositions({&position, 1});
return *this;
} }
/**
* @brief Set light colors
* @return Reference to self (for method chaining)
*
* Initial values are @cpp 0xffffffff_rgbaf @ce. Expects that the size
* of the @p colors array is the same as @ref lightCount().
*/
Phong& setLightColors(Containers::ArrayView<const Color4> colors);
/** @overload */
Phong& setLightColors(std::initializer_list<Color4> colors) {
return setLightColors({colors.begin(), colors.size()});
}
/**
* @brief Set position for given light
* @return Reference to self (for method chaining)
*
* Unlike @ref setLightColors() updates just a single light color.
* Expects that @p id is less than @ref lightCount().
* @see @ref setLightColor(const Color4&)
*/
Phong& setLightColor(UnsignedInt id, const Color4& color);
/** /**
* @brief Set light color * @brief Set light color
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Initial value is @cpp 0xffffffff_rgbaf @ce. * Convenience alternative to @ref setLightColors() when there is just
* one light.
* @see @ref setLightColor(UnsignedInt, const Color4&)
*/ */
Phong& setLightColor(const Color4& color) { Phong& setLightColor(const Color4& color) {
setUniform(_lightColorUniform, color); return setLightColors({&color, 1});
return *this;
} }
private: private:
Flags _flags; Flags _flags;
UnsignedInt _lightCount;
Int _transformationMatrixUniform{0}, Int _transformationMatrixUniform{0},
_projectionMatrixUniform{1}, _projectionMatrixUniform{1},
_normalMatrixUniform{2}, _normalMatrixUniform{2},
_lightPositionUniform{3},
_ambientColorUniform{4}, _ambientColorUniform{4},
_diffuseColorUniform{5}, _diffuseColorUniform{5},
_specularColorUniform{6}, _specularColorUniform{6},
_lightColorUniform{7}, _shininessUniform{7},
_shininessUniform{8}, _alphaMaskUniform{8},
_alphaMaskUniform{9}; _lightPositionsUniform{9},
_lightColorsUniform; /* 9 + lightCount, set in the constructor */
}; };
/** @debugoperatorclassenum{Phong,Phong::Flag} */ /** @debugoperatorclassenum{Phong,Phong::Flag} */

10
src/Magnum/Shaders/Phong.vert

@ -55,10 +55,11 @@ uniform mediump mat3 normalMatrix
#endif #endif
; ;
/* Needs to be last because it uses locations 9 to 9 + LIGHT_COUNT - 1 */
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 3) layout(location = 9)
#endif #endif
uniform highp vec3 lightPosition; /* defaults to zero */ uniform highp vec3 lightPositions[LIGHT_COUNT]; /* defaults to zero */
#ifdef EXPLICIT_ATTRIB_LOCATION #ifdef EXPLICIT_ATTRIB_LOCATION
layout(location = POSITION_ATTRIBUTE_LOCATION) layout(location = POSITION_ATTRIBUTE_LOCATION)
@ -80,7 +81,7 @@ out mediump vec2 interpolatedTextureCoords;
#endif #endif
out mediump vec3 transformedNormal; out mediump vec3 transformedNormal;
out highp vec3 lightDirection; out highp vec3 lightDirections[LIGHT_COUNT];
out highp vec3 cameraDirection; out highp vec3 cameraDirection;
void main() { void main() {
@ -92,7 +93,8 @@ void main() {
transformedNormal = normalMatrix*normal; transformedNormal = normalMatrix*normal;
/* Direction to the light */ /* Direction to the light */
lightDirection = normalize(lightPosition - transformedPosition); for(int i = 0; i < LIGHT_COUNT; ++i)
lightDirections[i] = normalize(lightPositions[i] - transformedPosition);
/* Direction to the camera */ /* Direction to the camera */
cameraDirection = -transformedPosition; cameraDirection = -transformedPosition;

79
src/Magnum/Shaders/Test/PhongGLTest.cpp

@ -46,22 +46,27 @@ struct PhongGLTest: GL::OpenGLTester {
void setAlphaMask(); void setAlphaMask();
void setAlphaMaskNotEnabled(); void setAlphaMaskNotEnabled();
void setWrongLightCount();
void setWrongLightId();
}; };
constexpr struct { constexpr struct {
const char* name; const char* name;
Phong::Flags flags; Phong::Flags flags;
UnsignedInt lightCount;
} ConstructData[]{ } ConstructData[]{
{"", {}}, {"", {}, 1},
{"ambient texture", Phong::Flag::AmbientTexture}, {"ambient texture", Phong::Flag::AmbientTexture, 1},
{"diffuse texture", Phong::Flag::DiffuseTexture}, {"diffuse texture", Phong::Flag::DiffuseTexture, 1},
{"specular texture", Phong::Flag::SpecularTexture}, {"specular texture", Phong::Flag::SpecularTexture, 1},
{"ambient + diffuse texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture}, {"ambient + diffuse texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture, 1},
{"ambient + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::SpecularTexture}, {"ambient + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::SpecularTexture, 1},
{"diffuse + specular texture", Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture}, {"diffuse + specular texture", Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 1},
{"ambient + diffuse + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture}, {"ambient + diffuse + specular texture", Phong::Flag::AmbientTexture|Phong::Flag::DiffuseTexture|Phong::Flag::SpecularTexture, 1},
{"alpha mask", Phong::Flag::AlphaMask}, {"alpha mask", Phong::Flag::AlphaMask, 1},
{"alpha mask + diffuse texture", Phong::Flag::AlphaMask|Phong::Flag::DiffuseTexture} {"alpha mask + diffuse texture", Phong::Flag::AlphaMask|Phong::Flag::DiffuseTexture, 1},
{"five lights", {}, 5}
}; };
PhongGLTest::PhongGLTest() { PhongGLTest::PhongGLTest() {
@ -73,15 +78,19 @@ PhongGLTest::PhongGLTest() {
&PhongGLTest::bindTexturesNotEnabled, &PhongGLTest::bindTexturesNotEnabled,
&PhongGLTest::setAlphaMask, &PhongGLTest::setAlphaMask,
&PhongGLTest::setAlphaMaskNotEnabled}); &PhongGLTest::setAlphaMaskNotEnabled,
&PhongGLTest::setWrongLightCount,
&PhongGLTest::setWrongLightId});
} }
void PhongGLTest::construct() { void PhongGLTest::construct() {
auto&& data = ConstructData[testCaseInstanceId()]; auto&& data = ConstructData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
Phong shader{data.flags}; Phong shader{data.flags, data.lightCount};
CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.lightCount(), data.lightCount);
{ {
#ifdef CORRADE_TARGET_APPLE #ifdef CORRADE_TARGET_APPLE
CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly."); CORRADE_EXPECT_FAIL("macOS drivers need insane amount of state to validate properly.");
@ -92,7 +101,7 @@ void PhongGLTest::construct() {
} }
void PhongGLTest::constructMove() { void PhongGLTest::constructMove() {
Phong a{Phong::Flag::AlphaMask}; Phong a{Phong::Flag::AlphaMask, 3};
const GLuint id = a.id(); const GLuint id = a.id();
CORRADE_VERIFY(id); CORRADE_VERIFY(id);
@ -101,12 +110,14 @@ void PhongGLTest::constructMove() {
Phong b{std::move(a)}; Phong b{std::move(a)};
CORRADE_COMPARE(b.id(), id); CORRADE_COMPARE(b.id(), id);
CORRADE_COMPARE(b.flags(), Phong::Flag::AlphaMask); CORRADE_COMPARE(b.flags(), Phong::Flag::AlphaMask);
CORRADE_COMPARE(b.lightCount(), 3);
CORRADE_VERIFY(!a.id()); CORRADE_VERIFY(!a.id());
Phong c{NoCreate}; Phong c{NoCreate};
c = std::move(b); c = std::move(b);
CORRADE_COMPARE(c.id(), id); CORRADE_COMPARE(c.id(), id);
CORRADE_COMPARE(c.flags(), Phong::Flag::AlphaMask); CORRADE_COMPARE(c.flags(), Phong::Flag::AlphaMask);
CORRADE_COMPARE(c.lightCount(), 3);
CORRADE_VERIFY(!b.id()); CORRADE_VERIFY(!b.id());
} }
@ -169,6 +180,48 @@ void PhongGLTest::setAlphaMaskNotEnabled() {
"Shaders::Phong::setAlphaMask(): the shader was not created with alpha mask enabled\n"); "Shaders::Phong::setAlphaMask(): the shader was not created with alpha mask enabled\n");
} }
void PhongGLTest::setWrongLightCount() {
std::ostringstream out;
Error redirectError{&out};
Phong shader{{}, 5};
/* This is okay */
shader.setLightColors({{}, {}, {}, {}, {}})
.setLightPositions({{}, {}, {}, {}, {}});
MAGNUM_VERIFY_NO_GL_ERROR();
/* This is not */
shader.setLightColor({})
.setLightPosition({});
CORRADE_COMPARE(out.str(),
"Shaders::Phong::setLightColors(): expected 5 items but got 1\n"
"Shaders::Phong::setLightPositions(): expected 5 items but got 1\n");
}
void PhongGLTest::setWrongLightId() {
std::ostringstream out;
Error redirectError{&out};
Phong shader{{}, 3};
/* This is okay */
shader.setLightColor(2, {})
.setLightPosition(2, {});
MAGNUM_VERIFY_NO_GL_ERROR();
/* This is not */
shader.setLightColor(3, {})
.setLightPosition(3, {});
CORRADE_COMPARE(out.str(),
"Shaders::Phong::setLightColor(): light ID 3 is out of bounds for 3 lights\n"
"Shaders::Phong::setLightPosition(): light ID 3 is out of bounds for 3 lights\n");
}
}}} }}}
CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongGLTest) CORRADE_TEST_MAIN(Magnum::Shaders::Test::PhongGLTest)

Loading…
Cancel
Save