Browse Source

Shaders: decouple light array size and per-draw light count.

So it's possible to have light culling enabled on, say, 64 lights, but
with only at most 3 applied each draw, allowing the shader compiler to
unroll the loop if it makes sense. This also better prepares for SSBO
support where the total light count would be unbounded and thus the
value ignored, and thus the value can be 0.
pull/617/head
Vladimír Vondruš 3 years ago
parent
commit
fdd9d798b3
  1. 18
      src/Magnum/Shaders/Phong.frag
  2. 53
      src/Magnum/Shaders/PhongGL.cpp
  3. 141
      src/Magnum/Shaders/PhongGL.h
  4. 278
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  5. 34
      src/Magnum/Shaders/Test/PhongGL_Test.cpp

18
src/Magnum/Shaders/Phong.frag

@ -53,7 +53,7 @@ uniform lowp vec4 ambientColor
#endif #endif
; ;
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 6) layout(location = 6)
#endif #endif
@ -252,7 +252,7 @@ uniform lowp
ambientTexture; ambientTexture;
#endif #endif
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
#ifdef DIFFUSE_TEXTURE #ifdef DIFFUSE_TEXTURE
#ifdef EXPLICIT_BINDING #ifdef EXPLICIT_BINDING
layout(binding = 1) layout(binding = 1)
@ -308,7 +308,7 @@ uniform lowp
/* Inputs */ /* Inputs */
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
in mediump vec3 transformedNormal; in mediump vec3 transformedNormal;
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
#ifndef BITANGENT #ifndef BITANGENT
@ -370,7 +370,7 @@ void main() {
#define materialId 0u #define materialId 0u
#endif #endif
lowp const vec4 ambientColor = materials[materialId].ambientColor; lowp const vec4 ambientColor = materials[materialId].ambientColor;
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
lowp const vec4 diffuseColor = materials[materialId].diffuseColor; lowp const vec4 diffuseColor = materials[materialId].diffuseColor;
lowp const vec4 specularColor = materials[materialId].specularColor; lowp const vec4 specularColor = materials[materialId].specularColor;
mediump const float shininess = materials[materialId].material_shininess; mediump const float shininess = materials[materialId].material_shininess;
@ -381,7 +381,7 @@ void main() {
#ifdef ALPHA_MASK #ifdef ALPHA_MASK
lowp const float alphaMask = materials[materialId].material_alphaMask; lowp const float alphaMask = materials[materialId].material_alphaMask;
#endif #endif
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
mediump const uint lightOffset = draws[drawId].draw_lightOffsetLightCount & 0xffffu; mediump const uint lightOffset = draws[drawId].draw_lightOffsetLightCount & 0xffffu;
#ifdef LIGHT_CULLING #ifdef LIGHT_CULLING
mediump const uint lightCount = draws[drawId].draw_lightOffsetLightCount >> 16 & 0xffffu; mediump const uint lightCount = draws[drawId].draw_lightOffsetLightCount >> 16 & 0xffffu;
@ -397,7 +397,7 @@ void main() {
interpolatedVertexColor* interpolatedVertexColor*
#endif #endif
ambientColor; ambientColor;
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
lowp const vec4 finalDiffuseColor = lowp const vec4 finalDiffuseColor =
#ifdef DIFFUSE_TEXTURE #ifdef DIFFUSE_TEXTURE
texture(diffuseTexture, interpolatedTextureCoordinates)* texture(diffuseTexture, interpolatedTextureCoordinates)*
@ -418,7 +418,7 @@ void main() {
/* Ambient color */ /* Ambient color */
fragmentColor = finalAmbientColor; fragmentColor = finalAmbientColor;
#if LIGHT_COUNT #if PER_DRAW_LIGHT_COUNT
/* Normal */ /* Normal */
mediump vec3 normalizedTransformedNormal = normalize(transformedNormal); mediump vec3 normalizedTransformedNormal = normalize(transformedNormal);
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
@ -445,9 +445,9 @@ void main() {
/* Add diffuse color for each light */ /* Add diffuse color for each light */
#ifndef LIGHT_CULLING #ifndef LIGHT_CULLING
for(int i = 0; i < LIGHT_COUNT; ++i) for(int i = 0; i < PER_DRAW_LIGHT_COUNT; ++i)
#else #else
for(uint i = 0u, actualLightCount = min(uint(LIGHT_COUNT), lightCount); i < actualLightCount; ++i) for(uint i = 0u, actualLightCount = min(uint(PER_DRAW_LIGHT_COUNT), lightCount); i < actualLightCount; ++i)
#endif #endif
{ {
lowp const vec3 lightColor = lowp const vec3 lightColor =

53
src/Magnum/Shaders/PhongGL.cpp

@ -170,6 +170,7 @@ PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
PhongGL out{NoInit}; PhongGL out{NoInit};
out._flags = configuration.flags(); out._flags = configuration.flags();
out._lightCount = configuration.lightCount(); out._lightCount = configuration.lightCount();
out._perDrawLightCount = configuration.perDrawLightCount();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._jointCount = configuration.jointCount(); out._jointCount = configuration.jointCount();
out._perVertexJointCount = configuration.perVertexJointCount(); out._perVertexJointCount = configuration.perVertexJointCount();
@ -215,7 +216,7 @@ PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n"_s : ""_s) .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n"_s : ""_s)
#endif #endif
.addSource(configuration.lightCount() ? "#define HAS_LIGHTS\n"_s : ""_s) .addSource(configuration.perDrawLightCount() ? "#define HAS_LIGHTS\n"_s : ""_s)
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n"_s : ""_s) .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n"_s : ""_s)
#endif #endif
@ -286,10 +287,12 @@ PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n" "#define MATERIAL_COUNT {}\n"
"#define LIGHT_COUNT {}\n", "#define LIGHT_COUNT {}\n"
"#define PER_DRAW_LIGHT_COUNT {}\n",
configuration.drawCount(), configuration.drawCount(),
configuration.materialCount(), configuration.materialCount(),
configuration.lightCount())); configuration.lightCount(),
configuration.perDrawLightCount()));
frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n"_s : ""_s) frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n"_s : ""_s)
.addSource(configuration.flags() >= Flag::LightCulling ? "#define LIGHT_CULLING\n"_s : ""_s); .addSource(configuration.flags() >= Flag::LightCulling ? "#define LIGHT_CULLING\n"_s : ""_s);
} else } else
@ -297,10 +300,12 @@ PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
{ {
frag.addSource(Utility::format( frag.addSource(Utility::format(
"#define LIGHT_COUNT {}\n" "#define LIGHT_COUNT {}\n"
"#define PER_DRAW_LIGHT_COUNT {}\n"
"#define LIGHT_COLORS_LOCATION {}\n" "#define LIGHT_COLORS_LOCATION {}\n"
"#define LIGHT_SPECULAR_COLORS_LOCATION {}\n" "#define LIGHT_SPECULAR_COLORS_LOCATION {}\n"
"#define LIGHT_RANGES_LOCATION {}\n", "#define LIGHT_RANGES_LOCATION {}\n",
configuration.lightCount(), configuration.lightCount(),
configuration.perDrawLightCount(),
out._lightColorsUniform, out._lightColorsUniform,
out._lightSpecularColorsUniform, out._lightSpecularColorsUniform,
out._lightRangesUniform)); out._lightRangesUniform));
@ -323,9 +328,9 @@ PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
#endif #endif
{ {
out.bindAttributeLocation(Position::Location, "position"_s); out.bindAttributeLocation(Position::Location, "position"_s);
if(configuration.lightCount()) if(configuration.perDrawLightCount())
out.bindAttributeLocation(Normal::Location, "normal"_s); out.bindAttributeLocation(Normal::Location, "normal"_s);
if((configuration.flags() & Flag::NormalTexture) && configuration.lightCount()) { if((configuration.flags() & Flag::NormalTexture) && configuration.perDrawLightCount()) {
out.bindAttributeLocation(Tangent::Location, "tangent"_s); out.bindAttributeLocation(Tangent::Location, "tangent"_s);
if(configuration.flags() & Flag::Bitangent) if(configuration.flags() & Flag::Bitangent)
out.bindAttributeLocation(Bitangent::Location, "bitangent"_s); out.bindAttributeLocation(Bitangent::Location, "bitangent"_s);
@ -348,7 +353,7 @@ PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
#endif #endif
if(configuration.flags() & Flag::InstancedTransformation) { if(configuration.flags() & Flag::InstancedTransformation) {
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"_s); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"_s);
if(configuration.lightCount()) if(configuration.perDrawLightCount())
out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"_s); out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"_s);
} }
if(configuration.flags() >= Flag::InstancedTextureOffset) if(configuration.flags() >= Flag::InstancedTextureOffset)
@ -431,7 +436,7 @@ PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast<PhongGL&&>(std::move
#endif #endif
_projectionMatrixUniform = uniformLocation("projectionMatrix"_s); _projectionMatrixUniform = uniformLocation("projectionMatrix"_s);
_ambientColorUniform = uniformLocation("ambientColor"_s); _ambientColorUniform = uniformLocation("ambientColor"_s);
if(_lightCount) { if(_perDrawLightCount) {
_normalMatrixUniform = uniformLocation("normalMatrix"_s); _normalMatrixUniform = uniformLocation("normalMatrix"_s);
_diffuseColorUniform = uniformLocation("diffuseColor"_s); _diffuseColorUniform = uniformLocation("diffuseColor"_s);
if(!(_flags & Flag::NoSpecular)) { if(!(_flags & Flag::NoSpecular)) {
@ -464,7 +469,7 @@ PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast<PhongGL&&>(std::move
#endif #endif
{ {
if(_flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"_s), AmbientTextureUnit); if(_flags & Flag::AmbientTexture) setUniform(uniformLocation("ambientTexture"_s), AmbientTextureUnit);
if(_lightCount) { if(_perDrawLightCount) {
if(_flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"_s), DiffuseTextureUnit); if(_flags & Flag::DiffuseTexture) setUniform(uniformLocation("diffuseTexture"_s), DiffuseTextureUnit);
if(_flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"_s), SpecularTextureUnit); if(_flags & Flag::SpecularTexture) setUniform(uniformLocation("specularTexture"_s), SpecularTextureUnit);
if(_flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"_s), NormalTextureUnit); if(_flags & Flag::NormalTexture) setUniform(uniformLocation("normalTexture"_s), NormalTextureUnit);
@ -580,7 +585,7 @@ PhongGL& PhongGL::setDiffuseColor(const Magnum::Color4& color) {
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
"Shaders::PhongGL::setDiffuseColor(): the shader was created with uniform buffers enabled", *this); "Shaders::PhongGL::setDiffuseColor(): the shader was created with uniform buffers enabled", *this);
#endif #endif
if(_lightCount) setUniform(_diffuseColorUniform, color); if(_perDrawLightCount) setUniform(_diffuseColorUniform, color);
return *this; return *this;
} }
@ -591,7 +596,7 @@ PhongGL& PhongGL::setSpecularColor(const Magnum::Color4& color) {
#endif #endif
CORRADE_ASSERT(!(_flags >= Flag::NoSpecular), CORRADE_ASSERT(!(_flags >= Flag::NoSpecular),
"Shaders::PhongGL::setSpecularColor(): the shader was created with specular disabled", *this); "Shaders::PhongGL::setSpecularColor(): the shader was created with specular disabled", *this);
if(_lightCount) setUniform(_specularColorUniform, color); if(_perDrawLightCount) setUniform(_specularColorUniform, color);
return *this; return *this;
} }
@ -602,7 +607,7 @@ PhongGL& PhongGL::setShininess(Float shininess) {
#endif #endif
CORRADE_ASSERT(!(_flags >= Flag::NoSpecular), CORRADE_ASSERT(!(_flags >= Flag::NoSpecular),
"Shaders::PhongGL::setShininess(): the shader was created with specular disabled", *this); "Shaders::PhongGL::setShininess(): the shader was created with specular disabled", *this);
if(_lightCount) setUniform(_shininessUniform, shininess); if(_perDrawLightCount) setUniform(_shininessUniform, shininess);
return *this; return *this;
} }
@ -613,7 +618,7 @@ PhongGL& PhongGL::setNormalTextureScale(const Float scale) {
#endif #endif
CORRADE_ASSERT(_flags & Flag::NormalTexture, CORRADE_ASSERT(_flags & Flag::NormalTexture,
"Shaders::PhongGL::setNormalTextureScale(): the shader was not created with normal texture enabled", *this); "Shaders::PhongGL::setNormalTextureScale(): the shader was not created with normal texture enabled", *this);
if(_lightCount) setUniform(_normalTextureScaleUniform, scale); if(_perDrawLightCount) setUniform(_normalTextureScaleUniform, scale);
return *this; return *this;
} }
@ -653,7 +658,7 @@ PhongGL& PhongGL::setNormalMatrix(const Matrix3x3& matrix) {
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
"Shaders::PhongGL::setNormalMatrix(): the shader was created with uniform buffers enabled", *this); "Shaders::PhongGL::setNormalMatrix(): the shader was created with uniform buffers enabled", *this);
#endif #endif
if(_lightCount) setUniform(_normalMatrixUniform, matrix); if(_perDrawLightCount) setUniform(_normalMatrixUniform, matrix);
return *this; return *this;
} }
@ -1025,7 +1030,7 @@ PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(!(_flags & Flag::TextureArrays), CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindDiffuseTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this); "Shaders::PhongGL::bindDiffuseTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif #endif
if(_lightCount) texture.bind(DiffuseTextureUnit); if(_perDrawLightCount) texture.bind(DiffuseTextureUnit);
return *this; return *this;
} }
@ -1035,7 +1040,7 @@ PhongGL& PhongGL::bindDiffuseTexture(GL::Texture2DArray& texture) {
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this); "Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with diffuse texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays, CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this); "Shaders::PhongGL::bindDiffuseTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
if(_lightCount) texture.bind(DiffuseTextureUnit); if(_perDrawLightCount) texture.bind(DiffuseTextureUnit);
return *this; return *this;
} }
#endif #endif
@ -1047,7 +1052,7 @@ PhongGL& PhongGL::bindSpecularTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(!(_flags & Flag::TextureArrays), CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindSpecularTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this); "Shaders::PhongGL::bindSpecularTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif #endif
if(_lightCount) texture.bind(SpecularTextureUnit); if(_perDrawLightCount) texture.bind(SpecularTextureUnit);
return *this; return *this;
} }
@ -1057,7 +1062,7 @@ PhongGL& PhongGL::bindSpecularTexture(GL::Texture2DArray& texture) {
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this); "Shaders::PhongGL::bindSpecularTexture(): the shader was not created with specular texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays, CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindSpecularTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this); "Shaders::PhongGL::bindSpecularTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
if(_lightCount) texture.bind(SpecularTextureUnit); if(_perDrawLightCount) texture.bind(SpecularTextureUnit);
return *this; return *this;
} }
#endif #endif
@ -1069,7 +1074,7 @@ PhongGL& PhongGL::bindNormalTexture(GL::Texture2D& texture) {
CORRADE_ASSERT(!(_flags & Flag::TextureArrays), CORRADE_ASSERT(!(_flags & Flag::TextureArrays),
"Shaders::PhongGL::bindNormalTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this); "Shaders::PhongGL::bindNormalTexture(): the shader was created with texture arrays enabled, use a Texture2DArray instead", *this);
#endif #endif
if(_lightCount) texture.bind(NormalTextureUnit); if(_perDrawLightCount) texture.bind(NormalTextureUnit);
return *this; return *this;
} }
@ -1079,7 +1084,7 @@ PhongGL& PhongGL::bindNormalTexture(GL::Texture2DArray& texture) {
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this); "Shaders::PhongGL::bindNormalTexture(): the shader was not created with normal texture enabled", *this);
CORRADE_ASSERT(_flags & Flag::TextureArrays, CORRADE_ASSERT(_flags & Flag::TextureArrays,
"Shaders::PhongGL::bindNormalTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this); "Shaders::PhongGL::bindNormalTexture(): the shader was not created with texture arrays enabled, use a Texture2D instead", *this);
if(_lightCount) texture.bind(NormalTextureUnit); if(_perDrawLightCount) texture.bind(NormalTextureUnit);
return *this; return *this;
} }
#endif #endif
@ -1117,6 +1122,16 @@ PhongGL& PhongGL::bindTextures(GL::Texture2D* ambient, GL::Texture2D* diffuse, G
return *this; return *this;
} }
PhongGL::Configuration& PhongGL::Configuration::setLightCount(const UnsignedInt count, const UnsignedInt perDrawCount) {
CORRADE_ASSERT(!count == !perDrawCount,
"Shaders::PhongGL::Configuration::setLightCount(): count has to be non-zero iff per-draw count is non-zero", *this);
CORRADE_ASSERT(perDrawCount <= count,
"Shaders::PhongGL::Configuration::setLightCount(): per-draw light count expected to be not larger than total count of" << count << Debug::nospace << ", got" << perDrawCount, *this);
_lightCount = count;
_perDrawLightCount = perDrawCount;
return *this;
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
PhongGL::Configuration& PhongGL::Configuration::setJointCount(UnsignedInt count, UnsignedInt perVertexCount, UnsignedInt secondaryPerVertexCount) { PhongGL::Configuration& PhongGL::Configuration::setJointCount(UnsignedInt count, UnsignedInt perVertexCount, UnsignedInt secondaryPerVertexCount) {
CORRADE_ASSERT(perVertexCount <= 4, CORRADE_ASSERT(perVertexCount <= 4,

141
src/Magnum/Shaders/PhongGL.h

@ -365,8 +365,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @brief Normal direction * @brief Normal direction
* *
* @ref shaders-generic "Generic attribute", * @ref shaders-generic "Generic attribute",
* @relativeref{Magnum,Vector3}. Used only if @ref lightCount() isn't * @relativeref{Magnum,Vector3}. Used only if @ref perDrawLightCount()
* @cpp 0 @ce. * isn't @cpp 0 @ce.
*/ */
typedef GenericGL3D::Normal Normal; typedef GenericGL3D::Normal Normal;
@ -380,7 +380,7 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @ref Flag::Bitangent is not enabled, it's the same as if * @ref Flag::Bitangent is not enabled, it's the same as if
* @ref Tangent4 was specified with the fourth component always being * @ref Tangent4 was specified with the fourth component always being
* @cpp 1.0f @ce. Used only if @ref Flag::NormalTexture is set and * @cpp 1.0f @ce. Used only if @ref Flag::NormalTexture is set and
* @ref lightCount() isn't @cpp 0 @ce. * @ref perDrawLightCount() isn't @cpp 0 @ce.
* @see @ref Shaders-PhongGL-normal-mapping * @see @ref Shaders-PhongGL-normal-mapping
*/ */
typedef GenericGL3D::Tangent Tangent; typedef GenericGL3D::Tangent Tangent;
@ -394,7 +394,7 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* attribute. If @ref Flag::Bitangent is set, the fourth component is * attribute. If @ref Flag::Bitangent is set, the fourth component is
* ignored and bitangents are taken from the @ref Bitangent attribute * ignored and bitangents are taken from the @ref Bitangent attribute
* instead. Used only if @ref Flag::NormalTexture is set and * instead. Used only if @ref Flag::NormalTexture is set and
* @ref lightCount() isn't @cpp 0 @ce. * @ref perDrawLightCount() isn't @cpp 0 @ce.
* @see @ref Shaders-PhongGL-normal-mapping * @see @ref Shaders-PhongGL-normal-mapping
*/ */
typedef GenericGL3D::Tangent4 Tangent4; typedef GenericGL3D::Tangent4 Tangent4;
@ -406,7 +406,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @ref shaders-generic "Generic attribute", * @ref shaders-generic "Generic attribute",
* @relativeref{Magnum,Vector3}. Use either this or the @ref Tangent4 * @relativeref{Magnum,Vector3}. Use either this or the @ref Tangent4
* attribute. Used only if both @ref Flag::NormalTexture and * attribute. Used only if both @ref Flag::NormalTexture and
* @ref Flag::Bitangent are set and @ref lightCount() isn't @cpp 0 @ce. * @ref Flag::Bitangent are set and @ref perDrawLightCount() isn't
* @cpp 0 @ce.
* @see @ref Shaders-PhongGL-normal-mapping * @see @ref Shaders-PhongGL-normal-mapping
*/ */
typedef GenericGL3D::Bitangent Bitangent; typedef GenericGL3D::Bitangent Bitangent;
@ -851,8 +852,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* Enable light culling in uniform buffer workflows using the * Enable light culling in uniform buffer workflows using the
* @ref PhongDrawUniform::lightOffset and * @ref PhongDrawUniform::lightOffset and
* @ref PhongDrawUniform::lightCount fields. If not enabled, all * @ref PhongDrawUniform::lightCount fields. If not enabled, all
* @ref lightCount() lights are used for every draw. Expects that * @ref perDrawLightCount() lights are used for every draw. Expects
* @ref Flag::UniformBuffers is enabled as well. * that @ref Flag::UniformBuffers is enabled as well.
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES * @requires_gles30 Uniform buffers are not available in OpenGL ES
* 2.0. * 2.0.
@ -1032,10 +1033,24 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* If @ref Flag::UniformBuffers is set, this is the statically defined * If @ref Flag::UniformBuffers is set, this is the statically defined
* size of the @ref PhongLightUniform uniform buffer bound with * size of the @ref PhongLightUniform uniform buffer bound with
* @ref bindLightBuffer(). * @ref bindLightBuffer().
* @see @ref Configuration::setLightCount() * @see @ref perDrawLightCount(), @ref Configuration::setLightCount()
*/ */
UnsignedInt lightCount() const { return _lightCount; } UnsignedInt lightCount() const { return _lightCount; }
/**
* @brief Per-draw light count
* @m_since_latest
*
* Number of lights out of @ref lightCount() applied per draw. If
* @ref Flag::LightCulling is enabled, this is only an upper bound on
* the light count applied per draw, with the actual count supplied via
* @ref PhongDrawUniform::lightCount. If @cpp 0 @ce, no lighting
* calculations are performed and only the ambient contribution to the
* color is used.
* @see @ref Configuration::setLightCount()
*/
UnsignedInt perDrawLightCount() const { return _perDrawLightCount; }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Joint count * @brief Joint count
@ -1164,10 +1179,10 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* *
* Initial value is @cpp 0xffffffff_rgbaf @ce. If * Initial value is @cpp 0xffffffff_rgbaf @ce. If
* @ref Flag::DiffuseTexture is set, the color will be multiplied with * @ref Flag::DiffuseTexture is set, the color will be multiplied with
* the texture. If @ref lightCount() is zero, this function is a no-op, * the texture. If @ref perDrawLightCount() is zero, this function is a
* as diffuse color doesn't contribute to the output in that case. * no-op, as diffuse color doesn't contribute to the output in that
* If @ref Flag::VertexColor is set, the color is multiplied with a * case. If @ref Flag::VertexColor is set, the color is multiplied with
* color coming from the @ref Color3 / @ref Color4 attribute. * a color coming from the @ref Color3 / @ref Color4 attribute.
* *
* Expects that @ref Flag::UniformBuffers is not set, in that case fill * Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref PhongMaterialUniform::diffuseColor and call * @ref PhongMaterialUniform::diffuseColor and call
@ -1187,8 +1202,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* altogether. * altogether.
* *
* Expects that the shader was created with @ref Flag::NormalTexture * Expects that the shader was created with @ref Flag::NormalTexture
* enabled. If @ref lightCount() is zero, this function is a no-op, as * enabled. If @ref perDrawLightCount() is zero, this function is a
* normals don't contribute to the output in that case. * no-op, as normals don't contribute to the output in that case.
* *
* Expects that @ref Flag::UniformBuffers is not set, in that case fill * Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref PhongMaterialUniform::normalTextureScale and call * @ref PhongMaterialUniform::normalTextureScale and call
@ -1209,8 +1224,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* recommended to disable the specular contribution altogether with * recommended to disable the specular contribution altogether with
* @ref Flag::NoSpecular. If having a dedicated shader variant is not * @ref Flag::NoSpecular. If having a dedicated shader variant is not
* possible, set the specular color to @cpp 0x00000000_rgbaf @ce. If * possible, set the specular color to @cpp 0x00000000_rgbaf @ce. If
* @ref lightCount() is zero, this function is a no-op, as specular * @ref perDrawLightCount() is zero, this function is a no-op, as
* color doesn't contribute to the output in that case. * specular color doesn't contribute to the output in that case.
* *
* Expects that @ref Flag::UniformBuffers is not set, in that case fill * Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref PhongMaterialUniform::specularColor and call * @ref PhongMaterialUniform::specularColor and call
@ -1224,9 +1239,9 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* The larger value, the harder surface (smaller specular highlight). * The larger value, the harder surface (smaller specular highlight).
* Initial value is @cpp 80.0f @ce. If @ref lightCount() is zero, this * Initial value is @cpp 80.0f @ce. If @ref perDrawLightCount() is
* function is a no-op, as specular color doesn't contribute to the * zero, this function is a no-op, as specular color doesn't contribute
* output in that case. * to the output in that case.
* *
* Expects that @ref Flag::UniformBuffers is not set, in that case fill * Expects that @ref Flag::UniformBuffers is not set, in that case fill
* @ref PhongMaterialUniform::shininess and call * @ref PhongMaterialUniform::shininess and call
@ -1301,9 +1316,9 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* The matrix doesn't need to be normalized, as renormalization is done * The matrix doesn't need to be normalized, as renormalization is done
* per-fragment anyway. You need to set also * per-fragment anyway. You need to set also
* @ref setTransformationMatrix() with a corresponding value. Initial * @ref setTransformationMatrix() with a corresponding value. Initial
* value is an identity matrix. If @ref lightCount() is zero, this * value is an identity matrix. If @ref perDrawLightCount() is zero,
* function is a no-op, as normals don't contribute to the output in * this function is a no-op, as normals don't contribute to the output
* that case. If @ref Flag::InstancedTransformation is set, the * in that case. If @ref Flag::InstancedTransformation is set, the
* per-instance normal matrix coming from the @ref NormalMatrix * per-instance normal matrix coming from the @ref NormalMatrix
* attribute is applied first, before this one. * attribute is applied first, before this one.
* *
@ -1895,8 +1910,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* Expects that the shader was created with @ref Flag::DiffuseTexture * Expects that the shader was created with @ref Flag::DiffuseTexture
* enabled. If @ref Flag::TextureArrays is enabled as well, use * enabled. If @ref Flag::TextureArrays is enabled as well, use
* @ref bindDiffuseTexture(GL::Texture2DArray&) instead. If * @ref bindDiffuseTexture(GL::Texture2DArray&) instead. If
* @ref lightCount() is zero, this function is a no-op, as diffuse * @ref perDrawLightCount() is zero, this function is a no-op, as
* color doesn't contribute to the output in that case. * diffuse color doesn't contribute to the output in that case.
* @see @ref bindTextures(), @ref setDiffuseColor() * @see @ref bindTextures(), @ref setDiffuseColor()
*/ */
PhongGL& bindDiffuseTexture(GL::Texture2D& texture); PhongGL& bindDiffuseTexture(GL::Texture2D& texture);
@ -1913,8 +1928,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* set via @ref setTextureLayer(); if @ref Flag::UniformBuffers is * set via @ref setTextureLayer(); if @ref Flag::UniformBuffers is
* enabled, @ref Flag::TextureTransformation has to be enabled as well * enabled, @ref Flag::TextureTransformation has to be enabled as well
* and the layer is set via @ref TextureTransformationUniform::layer. * and the layer is set via @ref TextureTransformationUniform::layer.
* If @ref lightCount() is zero, this function is a no-op, as diffuse * If @ref perDrawLightCount() is zero, this function is a no-op, as
* color doesn't contribute to the output in that case. * diffuse color doesn't contribute to the output in that case.
* @see @ref setDiffuseColor() * @see @ref setDiffuseColor()
* @requires_gl30 Extension @gl_extension{EXT,texture_array} * @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0. * @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
@ -1931,8 +1946,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* enabled and that @ref Flag::NoSpecular is not set. If * enabled and that @ref Flag::NoSpecular is not set. If
* @ref Flag::TextureArrays is enabled as well, use * @ref Flag::TextureArrays is enabled as well, use
* @ref bindSpecularTexture(GL::Texture2DArray&) instead. If * @ref bindSpecularTexture(GL::Texture2DArray&) instead. If
* @ref lightCount() is zero, this function is a no-op, as specular * @ref perDrawLightCount() is zero, this function is a no-op, as
* color doesn't contribute to the output in that case. * specular color doesn't contribute to the output in that case.
* @see @ref bindTextures(), @ref setSpecularColor() * @see @ref bindTextures(), @ref setSpecularColor()
*/ */
PhongGL& bindSpecularTexture(GL::Texture2D& texture); PhongGL& bindSpecularTexture(GL::Texture2D& texture);
@ -1950,8 +1965,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @ref Flag::UniformBuffers is enabled, * @ref Flag::UniformBuffers is enabled,
* @ref Flag::TextureTransformation has to be enabled as well and the * @ref Flag::TextureTransformation has to be enabled as well and the
* layer is set via @ref TextureTransformationUniform::layer. If * layer is set via @ref TextureTransformationUniform::layer. If
* @ref lightCount() is zero, this function is a no-op, as specular * @ref perDrawLightCount() is zero, this function is a no-op, as
* color doesn't contribute to the output in that case. * specular color doesn't contribute to the output in that case.
* @see @ref setSpecularColor() * @see @ref setSpecularColor()
* @requires_gl30 Extension @gl_extension{EXT,texture_array} * @requires_gl30 Extension @gl_extension{EXT,texture_array}
* @requires_gles30 Texture arrays are not available in OpenGL ES 2.0. * @requires_gles30 Texture arrays are not available in OpenGL ES 2.0.
@ -1969,8 +1984,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* enabled and the @ref Tangent attribute was supplied. If * enabled and the @ref Tangent attribute was supplied. If
* @ref Flag::TextureArrays is enabled as well, use * @ref Flag::TextureArrays is enabled as well, use
* @ref bindNormalTexture(GL::Texture2DArray&) instead. If * @ref bindNormalTexture(GL::Texture2DArray&) instead. If
* @ref lightCount() is zero, this function is a no-op, as normals * @ref perDrawLightCount() is zero, this function is a no-op, as
* don't contribute to the output in that case. * normals don't contribute to the output in that case.
* @see @ref Shaders-PhongGL-normal-mapping, * @see @ref Shaders-PhongGL-normal-mapping,
* @ref bindTextures(), @ref setNormalTextureScale() * @ref bindTextures(), @ref setNormalTextureScale()
*/ */
@ -1984,9 +1999,9 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* *
* Expects that the shader was created with both * Expects that the shader was created with both
* @ref Flag::NormalTexture and @ref Flag::TextureArrays enabled and * @ref Flag::NormalTexture and @ref Flag::TextureArrays enabled and
* the @ref Tangent attribute was supplied. If @ref lightCount() is * the @ref Tangent attribute was supplied. If @ref perDrawLightCount()
* zero, this function is a no-op, as normals don't contribute to the * is zero, this function is a no-op, as normals don't contribute to
* output in that case. * the output in that case.
* @see @ref Shaders-PhongGL-normal-mapping, * @see @ref Shaders-PhongGL-normal-mapping,
* @ref setNormalTextureScale() * @ref setNormalTextureScale()
*/ */
@ -2070,7 +2085,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
explicit PhongGL(NoInitT) {} explicit PhongGL(NoInitT) {}
Flags _flags; Flags _flags;
UnsignedInt _lightCount{}; UnsignedInt _lightCount{},
_perDrawLightCount{};
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
UnsignedInt _jointCount{}, UnsignedInt _jointCount{},
_perVertexJointCount{}, _perVertexJointCount{},
@ -2136,33 +2152,50 @@ class MAGNUM_SHADERS_EXPORT PhongGL::Configuration {
/** @brief Light count */ /** @brief Light count */
UnsignedInt lightCount() const { return _lightCount; } UnsignedInt lightCount() const { return _lightCount; }
/** @brief Per-draw light count */
UnsignedInt perDrawLightCount() const { return _perDrawLightCount; }
/** /**
* @brief Set light count * @brief Set light count
* *
* If @ref Flag::UniformBuffers isn't set, describes how many lights * If @ref Flag::UniformBuffers isn't set, @p count corresponds to the
* get applied to each draw, and corresponds to the range / array size * range / array size accepted by @ref setLightPosition() /
* accepted by @ref setLightPosition() / @ref setLightPositions(), * @ref setLightPositions(), @ref setLightColor() /
* @ref setLightColor() / @ref setLightColors(), * @ref setLightColors(), @ref setLightSpecularColor() /
* @ref setLightSpecularColor() / @ref setLightSpecularColors() and * @ref setLightSpecularColors() and @ref setLightRange() /
* @ref setLightRange() / @ref setLightRanges(). If * @ref setLightRanges().
* @ref Flag::UniformBuffers is set, describes size of a *
* If @ref Flag::UniformBuffers is set, @p count describes size of a
* @ref PhongLightUniform buffer bound with @ref bindLightBuffer(). * @ref PhongLightUniform buffer bound with @ref bindLightBuffer().
* Uniform buffers have a statically defined size and * Uniform buffers have a statically defined size and
* @cpp count*sizeof(PhongLightUniform) @ce has to be within * @cpp count*sizeof(PhongLightUniform) @ce has to be within
* @ref GL::AbstractShaderProgram::maxUniformBlockSize(). * @ref GL::AbstractShaderProgram::maxUniformBlockSize(). The per-draw
* * lights are then specified via @ref PhongDrawUniform::lightOffset and
* The per-draw lights are then specified via
* @ref PhongDrawUniform::lightOffset and
* @ref PhongDrawUniform::lightCount. * @ref PhongDrawUniform::lightCount.
* *
* Can be set to @cpp 0 @ce, in which case only the ambient * The @p perDrawCount parameter describes how many lights out of
* contribution to the color is used. Default value is @cpp 1 @ce. * @p count get applied to each draw. Useful mainly in combination with
* @ref Flag::LightCulling, without it can be used for conveniently
* reducing the light count without having to reduce sizes of the light
* arrays as well. It's expected to not be larger than @p count. If set
* to @cpp 0 @ce, no lighting calculations are performed and only the
* ambient contribution to the color is used. If @p perDrawCount is
* @cpp 0 @ce, @p count is expected to be zero as well.
*
* Default value is @cpp 1 @ce for both.
* @see @ref setFlags(), @ref setMaterialCount(), @ref setDrawCount(), * @see @ref setFlags(), @ref setMaterialCount(), @ref setDrawCount(),
* @ref PhongGL::lightCount() * @ref PhongGL::lightCount(), @ref PhongGL::perDrawLightCount()
*/
Configuration& setLightCount(UnsignedInt count, UnsignedInt perDrawCount);
/**
* @brief Set light count
*
* Same as calling @ref setLightCount(UnsignedInt, UnsignedInt) with
* both parameters set to @p count.
*/ */
Configuration& setLightCount(UnsignedInt count) { Configuration& setLightCount(UnsignedInt count) {
_lightCount = count; return setLightCount(count, count);
return *this;
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -2302,7 +2335,9 @@ class MAGNUM_SHADERS_EXPORT PhongGL::Configuration {
Flags _flags; Flags _flags;
UnsignedInt _lightCount = 1; UnsignedInt _lightCount = 1;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
UnsignedInt _jointCount = 0, UnsignedInt
_perDrawLightCount = 1,
_jointCount = 0,
_perVertexJointCount = 0, _perVertexJointCount = 0,
_secondaryPerVertexJointCount = 0, _secondaryPerVertexJointCount = 0,
_materialCount = 1, _materialCount = 1,

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

@ -230,54 +230,55 @@ struct PhongGLTest: GL::OpenGLTester {
constexpr struct { constexpr struct {
const char* name; const char* name;
PhongGL::Flags flags; PhongGL::Flags flags;
UnsignedInt lightCount; UnsignedInt lightCount, perDrawLightCount;
} ConstructData[]{ } ConstructData[]{
{"", {}, 1}, {"", {}, 1, 1},
{"ambient texture", PhongGL::Flag::AmbientTexture, 1}, {"ambient texture", PhongGL::Flag::AmbientTexture, 1, 1},
{"diffuse texture", PhongGL::Flag::DiffuseTexture, 1}, {"diffuse texture", PhongGL::Flag::DiffuseTexture, 1, 1},
{"diffuse texture + texture transform", PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureTransformation, 1}, {"diffuse texture + texture transform", PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureTransformation, 1, 1},
{"specular texture", PhongGL::Flag::SpecularTexture, 1}, {"specular texture", PhongGL::Flag::SpecularTexture, 1, 1},
{"normal texture", PhongGL::Flag::NormalTexture, 1}, {"normal texture", PhongGL::Flag::NormalTexture, 1, 1},
{"normal texture + separate bitangents", PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1}, {"normal texture + separate bitangents", PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1, 1},
{"separate bitangents alone", PhongGL::Flag::Bitangent, 1}, {"separate bitangents alone", PhongGL::Flag::Bitangent, 1, 1},
{"ambient + diffuse texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 1}, {"ambient + diffuse texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture, 1, 1},
{"ambient + specular texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture, 1}, {"ambient + specular texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture, 1, 1},
{"diffuse + specular texture", PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1}, {"diffuse + specular texture", PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1, 1},
{"ambient + diffuse + specular texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1}, {"ambient + diffuse + specular texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, 1, 1},
{"ambient + diffuse + specular + normal texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture, 1}, {"ambient + diffuse + specular + normal texture", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture, 1, 1},
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
{"ambient + diffuse + specular + normal texture arrays", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays, 1}, {"ambient + diffuse + specular + normal texture arrays", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays, 1, 1},
{"ambient + diffuse + specular + normal texture arrays + texture transformation", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, 1}, {"ambient + diffuse + specular + normal texture arrays + texture transformation", PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, 1, 1},
#endif #endif
{"alpha mask", PhongGL::Flag::AlphaMask, 1}, {"alpha mask", PhongGL::Flag::AlphaMask, 1, 1},
{"alpha mask + diffuse texture", PhongGL::Flag::AlphaMask|PhongGL::Flag::DiffuseTexture, 1}, {"alpha mask + diffuse texture", PhongGL::Flag::AlphaMask|PhongGL::Flag::DiffuseTexture, 1, 1},
{"vertex colors", PhongGL::Flag::VertexColor, 1}, {"vertex colors", PhongGL::Flag::VertexColor, 1, 1},
{"vertex colors + diffuse texture", PhongGL::Flag::VertexColor|PhongGL::Flag::DiffuseTexture, 1}, {"vertex colors + diffuse texture", PhongGL::Flag::VertexColor|PhongGL::Flag::DiffuseTexture, 1, 1},
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
{"object ID", PhongGL::Flag::ObjectId, 1}, {"object ID", PhongGL::Flag::ObjectId, 1, 1},
/* This is fine, InstancedObjectId isn't (check in ConstructInvalidData) */ /* This is fine, InstancedObjectId isn't (check in ConstructInvalidData) */
{"object ID + separate bitangent", PhongGL::Flag::ObjectId|PhongGL::Flag::Bitangent, 1}, {"object ID + separate bitangent", PhongGL::Flag::ObjectId|PhongGL::Flag::Bitangent, 1, 1},
{"instanced object ID", PhongGL::Flag::InstancedObjectId, 1}, {"instanced object ID", PhongGL::Flag::InstancedObjectId, 1, 1},
{"object ID + alpha mask + specular texture", PhongGL::Flag::ObjectId|PhongGL::Flag::AlphaMask|PhongGL::Flag::SpecularTexture, 1}, {"object ID + alpha mask + specular texture", PhongGL::Flag::ObjectId|PhongGL::Flag::AlphaMask|PhongGL::Flag::SpecularTexture, 1, 1},
{"object ID texture", PhongGL::Flag::ObjectIdTexture, 1}, {"object ID texture", PhongGL::Flag::ObjectIdTexture, 1, 1},
{"object ID texture array", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays, 1}, {"object ID texture array", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays, 1, 1},
{"object ID texture + instanced texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset, 1}, {"object ID texture + instanced texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset, 1, 1},
{"object ID texture array + instanced texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::InstancedTextureOffset, 1}, {"object ID texture array + instanced texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::InstancedTextureOffset, 1, 1},
{"instanced object ID texture array + texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, 1}, {"instanced object ID texture array + texture transformation", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, 1, 1},
{"object ID texture + diffuse texture", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::DiffuseTexture, 1}, {"object ID texture + diffuse texture", PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::DiffuseTexture, 1, 1},
{"object ID texture, zero lights", PhongGL::Flag::ObjectIdTexture, 0}, {"object ID texture, zero lights", PhongGL::Flag::ObjectIdTexture, 0, 0},
#endif #endif
{"no specular", PhongGL::Flag::NoSpecular, 1}, {"no specular", PhongGL::Flag::NoSpecular, 1, 1},
{"five lights", {}, 5}, {"five lights", {}, 5, 5},
{"zero lights", {}, 0}, {"fifteen lights, five used", {}, 15, 5},
{"instanced transformation", PhongGL::Flag::InstancedTransformation, 3}, {"zero lights", {}, 0, 0},
{"instanced transformation, zero lights", PhongGL::Flag::InstancedTransformation, 0}, {"instanced transformation", PhongGL::Flag::InstancedTransformation, 3, 3},
{"instanced specular texture offset", PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3}, {"instanced transformation, zero lights", PhongGL::Flag::InstancedTransformation, 0, 0},
{"instanced normal texture offset", PhongGL::Flag::NormalTexture|PhongGL::Flag::InstancedTextureOffset, 3}, {"instanced specular texture offset", PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset, 3, 3},
{"instanced normal texture offset", PhongGL::Flag::NormalTexture|PhongGL::Flag::InstancedTextureOffset, 3, 3},
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/* InstancedObjectId|Bitangent is disallowed (checked in /* InstancedObjectId|Bitangent is disallowed (checked in
ConstructInvalidData), but this should work */ ConstructInvalidData), but this should work */
{"object ID + normal texture with bitangent from tangent", PhongGL::Flag::InstancedObjectId|PhongGL::Flag::NormalTexture, 1} {"object ID + normal texture with bitangent from tangent", PhongGL::Flag::InstancedObjectId|PhongGL::Flag::NormalTexture, 1, 1}
#endif #endif
}; };
@ -311,57 +312,57 @@ const struct {
constexpr struct { constexpr struct {
const char* name; const char* name;
PhongGL::Flags flags; PhongGL::Flags flags;
UnsignedInt lightCount, materialCount, drawCount; UnsignedInt lightCount, perDrawLightCount, materialCount, drawCount;
UnsignedInt jointCount, perVertexJointCount, secondaryPerVertexJointCount; UnsignedInt jointCount, perVertexJointCount, secondaryPerVertexJointCount;
} ConstructUniformBuffersData[]{ } ConstructUniformBuffersData[]{
{"classic fallback", {}, {"classic fallback", {},
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"", PhongGL::Flag::UniformBuffers, {"", PhongGL::Flag::UniformBuffers,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
/* SwiftShader has 256 uniform vectors at most, per-3D-draw is 4+4, /* SwiftShader has 256 uniform vectors at most, per-3D-draw is 4+4,
per-material 4, per-light 4 plus 4 for projection */ per-material 4, per-light 4 plus 4 for projection */
{"multiple lights, materials, draws", PhongGL::Flag::UniformBuffers, {"multiple lights, materials, draws", PhongGL::Flag::UniformBuffers,
8, 8, 24, 0, 0, 0}, 8, 8, 8, 24, 0, 0, 0},
{"multiple lights, materials, draws + light culling", PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling, {"multiple lights, materials, draws + light culling", PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling,
8, 8, 24, 0, 0, 0}, 8, 4, 8, 24, 0, 0, 0},
{"zero lights", PhongGL::Flag::UniformBuffers, {"zero lights", PhongGL::Flag::UniformBuffers,
0, 16, 24, 0, 0, 0}, 0, 0, 16, 24, 0, 0, 0},
{"ambient + diffuse + specular texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture, {"ambient + diffuse + specular texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"ambient + diffuse + specular texture + texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::TextureTransformation, {"ambient + diffuse + specular texture + texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::TextureTransformation,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"ambient + diffuse + specular texture array + texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, {"ambient + diffuse + specular texture array + texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AmbientTexture|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"normal texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture, {"normal texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"normal texture + separate bitangents", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, {"normal texture + separate bitangents", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"alpha mask", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AlphaMask, {"alpha mask", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AlphaMask,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"object ID", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectId, {"object ID", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectId,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"object ID texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture, {"object ID texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"object ID texture array", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, {"object ID texture array", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"object ID texture + instanced texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset, {"object ID texture + instanced texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedTextureOffset,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"object ID texture array + instanced texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::InstancedTextureOffset, {"object ID texture array + instanced texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::InstancedTextureOffset,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"instanced object ID texture array + texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation, {"instanced object ID texture array + texture transformation", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::TextureArrays|PhongGL::Flag::TextureTransformation,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"object ID texture + diffuse texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::DiffuseTexture, {"object ID texture + diffuse texture", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::DiffuseTexture,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"no specular", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NoSpecular, {"no specular", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NoSpecular,
1, 1, 1, 0, 0, 0}, 1, 1, 1, 1, 0, 0, 0},
{"skinning", PhongGL::Flag::UniformBuffers, {"skinning", PhongGL::Flag::UniformBuffers,
1, 1, 1, 32, 3, 2}, 1, 1, 1, 1, 32, 3, 2},
{"skinning, dynamic per-vertex sets", PhongGL::Flag::UniformBuffers|PhongGL::Flag::DynamicPerVertexJointCount, {"skinning, dynamic per-vertex sets", PhongGL::Flag::UniformBuffers|PhongGL::Flag::DynamicPerVertexJointCount,
1, 1, 1, 32, 3, 4}, 1, 1, 1, 1, 32, 3, 4},
{"multidraw with all the things except secondary per-vertex sets", PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::AlphaMask|PhongGL::Flag::ObjectId|PhongGL::Flag::InstancedTextureOffset|PhongGL::Flag::InstancedTransformation|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::LightCulling|PhongGL::Flag::DynamicPerVertexJointCount, {"multidraw with all the things except secondary per-vertex sets", PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::AlphaMask|PhongGL::Flag::ObjectId|PhongGL::Flag::InstancedTextureOffset|PhongGL::Flag::InstancedTransformation|PhongGL::Flag::InstancedObjectId|PhongGL::Flag::LightCulling|PhongGL::Flag::DynamicPerVertexJointCount,
8, 16, 24, 16, 4, 0}, 8, 4, 16, 24, 16, 4, 0},
{"multidraw with all the things except instancing", PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::AlphaMask|PhongGL::Flag::ObjectId|PhongGL::Flag::LightCulling|PhongGL::Flag::DynamicPerVertexJointCount, {"multidraw with all the things except instancing", PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::AmbientTexture|PhongGL::Flag::SpecularTexture|PhongGL::Flag::NormalTexture|PhongGL::Flag::TextureArrays|PhongGL::Flag::AlphaMask|PhongGL::Flag::ObjectId|PhongGL::Flag::LightCulling|PhongGL::Flag::DynamicPerVertexJointCount,
8, 16, 24, 16, 3, 4}, 8, 4, 16, 24, 16, 3, 4},
}; };
#endif #endif
@ -489,13 +490,15 @@ using namespace Math::Literals;
const struct { const struct {
const char* name; const char* name;
UnsignedInt lightCount, perDrawLightCount;
Deg rotation; Deg rotation;
Color3 lightColor1, lightColor2; Color3 lightColor1, lightColor2;
Float lightPosition1, lightPosition2; Float lightPosition1, lightPosition2;
} RenderColoredData[]{ } RenderColoredData[]{
{"", {}, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f}, {"", 2, 2, {}, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f},
{"flip lights", {}, 0x669933_rgbf, 0x993366_rgbf, 3.0f, -3.0f}, {"per-draw light count less than total", 4, 2, {}, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f},
{"rotated", 45.0_degf, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f} {"flip lights", 2, 2, {}, 0x669933_rgbf, 0x993366_rgbf, 3.0f, -3.0f},
{"rotated", 2, 2, 45.0_degf, 0x993366_rgbf, 0x669933_rgbf, -3.0f, 3.0f}
}; };
constexpr struct { constexpr struct {
@ -795,6 +798,16 @@ const struct {
1.0f, 0.0f, {}} 1.0f, 0.0f, {}}
}; };
#ifndef MAGNUM_TARGET_GLES2
const struct {
const char* name;
UnsignedInt count, perDrawCount;
} RenderLightCullingData[]{
{"same count and per-draw count", 64, 64},
{"per-draw count lower", 64, 2}
};
#endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
const struct { const struct {
const char* name; const char* name;
@ -976,118 +989,130 @@ constexpr struct {
const char* expected; const char* expected;
UnsignedInt expectedId[3]; UnsignedInt expectedId[3];
PhongGL::Flags flags; PhongGL::Flags flags;
UnsignedInt lightCount, materialCount, drawCount; UnsignedInt lightCount, perDrawLightCount, materialCount, drawCount;
UnsignedInt uniformIncrement; UnsignedInt uniformIncrement;
Float maxThreshold, meanThreshold; Float maxThreshold, meanThreshold;
} RenderMultiData[] { } RenderMultiData[] {
{"bind with offset, colored", {"bind with offset, colored",
"multidraw.tga", {}, "multidraw.tga", {},
{}, {},
2, 1, 1, 16, 2, 2, 1, 1, 16,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"bind with offset, colored + object ID", {"bind with offset, colored + object ID",
"multidraw.tga", {1211, 5627, 36363}, "multidraw.tga", {1211, 5627, 36363},
PhongGL::Flag::ObjectId, PhongGL::Flag::ObjectId,
2, 1, 1, 16, 2, 2, 1, 1, 16,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"bind with offset, colored + textured object ID", {"bind with offset, colored + textured object ID",
"multidraw.tga", {3211, 8627, 40363}, "multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture, PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture,
2, 1, 1, 16, 2, 2, 1, 1, 16,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"bind with offset, colored + textured array object ID", {"bind with offset, colored + textured array object ID",
"multidraw.tga", {3211, 8627, 40363}, "multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays, PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
2, 1, 1, 16, 2, 2, 1, 1, 16,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"bind with offset, textured", {"bind with offset, textured",
"multidraw-textured.tga", {}, "multidraw-textured.tga", {},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture, PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture,
2, 1, 1, 16, 2, 2, 1, 1, 16,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
4.67f, 0.02f}, 4.67f, 0.02f},
{"bind with offset, texture array", {"bind with offset, texture array",
"multidraw-textured.tga", {}, "multidraw-textured.tga", {},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureArrays, PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureArrays,
2, 1, 1, 16, 2, 2, 1, 1, 16,
/* Some difference at the UV edge (texture is wrapping in the 2D case /* Some difference at the UV edge (texture is wrapping in the 2D case
while the 2D array has a black area around) */ while the 2D array has a black area around) */
50.34f, 0.131f}, 50.34f, 0.131f},
{"draw offset, colored", {"draw offset, colored",
"multidraw.tga", {}, "multidraw.tga", {},
{}, {},
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"draw offset, colore, less per-draw lights",
"multidraw.tga", {},
{},
4, 2, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"draw offset, colored + object ID", {"draw offset, colored + object ID",
"multidraw.tga", {1211, 5627, 36363}, "multidraw.tga", {1211, 5627, 36363},
PhongGL::Flag::ObjectId, PhongGL::Flag::ObjectId,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"draw offset, colored + textured object ID", {"draw offset, colored + textured object ID",
"multidraw.tga", {3211, 8627, 40363}, "multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture, PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"draw offset, colored + textured array object ID", {"draw offset, colored + textured array object ID",
"multidraw.tga", {3211, 8627, 40363}, "multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays, PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"draw offset, textured", {"draw offset, textured",
"multidraw-textured.tga", {}, "multidraw-textured.tga", {},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture, PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
4.67f, 0.02f}, 4.67f, 0.02f},
{"draw offset, texture array", {"draw offset, texture array",
"multidraw-textured.tga", {}, "multidraw-textured.tga", {},
PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureArrays, PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureArrays,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Some difference at the UV edge (texture is wrapping in the 2D case /* Some difference at the UV edge (texture is wrapping in the 2D case
while the 2D array has a black area around) */ while the 2D array has a black area around) */
50.34f, 0.131f}, 50.34f, 0.131f},
{"multidraw, colored", {"multidraw, colored",
"multidraw.tga", {}, "multidraw.tga", {},
PhongGL::Flag::MultiDraw, PhongGL::Flag::MultiDraw,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */
3.34f, 0.01f},
{"multidraw, colored, less per-draw lights",
"multidraw.tga", {},
PhongGL::Flag::MultiDraw,
4, 2, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"multidraw, colored + object ID", {"multidraw, colored + object ID",
"multidraw.tga", {1211, 5627, 36363}, "multidraw.tga", {1211, 5627, 36363},
PhongGL::Flag::MultiDraw|PhongGL::Flag::ObjectId, PhongGL::Flag::MultiDraw|PhongGL::Flag::ObjectId,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"multidraw, colored + textured object ID", {"multidraw, colored + textured object ID",
"multidraw.tga", {3211, 8627, 40363}, "multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture, PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"multidraw, colored + textured array object ID", {"multidraw, colored + textured array object ID",
"multidraw.tga", {3211, 8627, 40363}, "multidraw.tga", {3211, 8627, 40363},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays, PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::ObjectIdTexture|PhongGL::Flag::TextureArrays,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
3.34f, 0.01f}, 3.34f, 0.01f},
{"multidraw, textured", {"multidraw, textured",
"multidraw-textured.tga", {}, "multidraw-textured.tga", {},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture, PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Minor differences on ARM Mali */ /* Minor differences on ARM Mali */
4.67f, 0.02f}, 4.67f, 0.02f},
{"multidraw, texture array", {"multidraw, texture array",
"multidraw-textured.tga", {}, "multidraw-textured.tga", {},
PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureArrays, PhongGL::Flag::MultiDraw|PhongGL::Flag::TextureTransformation|PhongGL::Flag::DiffuseTexture|PhongGL::Flag::TextureArrays,
4, 2, 3, 1, 4, 4, 2, 3, 1,
/* Some difference at the UV edge (texture is wrapping in the 2D case /* Some difference at the UV edge (texture is wrapping in the 2D case
while the 2D array has a black area around) */ while the 2D array has a black area around) */
50.34f, 0.131f}, 50.34f, 0.131f},
@ -1292,16 +1317,18 @@ PhongGLTest::PhongGLTest() {
&PhongGLTest::renderSetup, &PhongGLTest::renderSetup,
&PhongGLTest::renderTeardown); &PhongGLTest::renderTeardown);
addTests({ addTests({&PhongGLTest::renderLightsSetOneByOne,
&PhongGLTest::renderLightsSetOneByOne, &PhongGLTest::renderLowLightAngle},
&PhongGLTest::renderLowLightAngle,
#ifndef MAGNUM_TARGET_GLES2
&PhongGLTest::renderLightCulling
#endif
},
&PhongGLTest::renderSetup, &PhongGLTest::renderSetup,
&PhongGLTest::renderTeardown); &PhongGLTest::renderTeardown);
#ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&PhongGLTest::renderLightCulling},
Containers::arraySize(RenderLightCullingData),
&PhongGLTest::renderSetup,
&PhongGLTest::renderTeardown);
#endif
/* MSVC needs explicit type due to default template args */ /* MSVC needs explicit type due to default template args */
addTests<PhongGLTest>({ addTests<PhongGLTest>({
&PhongGLTest::renderZeroLights, &PhongGLTest::renderZeroLights,
@ -1391,9 +1418,10 @@ void PhongGLTest::construct() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(data.flags) .setFlags(data.flags)
.setLightCount(data.lightCount)}; .setLightCount(data.lightCount, data.perDrawLightCount)};
CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.lightCount(), data.lightCount); CORRADE_COMPARE(shader.lightCount(), data.lightCount);
CORRADE_COMPARE(shader.perDrawLightCount(), data.perDrawLightCount);
CORRADE_VERIFY(shader.id()); CORRADE_VERIFY(shader.id());
{ {
#if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES) #if defined(CORRADE_TARGET_APPLE) && !defined(MAGNUM_TARGET_GLES)
@ -1438,12 +1466,13 @@ void PhongGLTest::constructSkinning() {
void PhongGLTest::constructAsync() { void PhongGLTest::constructAsync() {
PhongGL::CompileState state = PhongGL::compile(PhongGL::Configuration{} PhongGL::CompileState state = PhongGL::compile(PhongGL::Configuration{}
.setFlags(PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset) .setFlags(PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset)
.setLightCount(3) .setLightCount(3, 2)
/* Skinning properties tested in constructUniformBuffersAsync(), as /* Skinning properties tested in constructUniformBuffersAsync(), as
there we don't need to bother with ES2 */ there we don't need to bother with ES2 */
); );
CORRADE_COMPARE(state.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset); CORRADE_COMPARE(state.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset);
CORRADE_COMPARE(state.lightCount(), 3); CORRADE_COMPARE(state.lightCount(), 3);
CORRADE_COMPARE(state.perDrawLightCount(), 2);
while(!state.isLinkFinished()) while(!state.isLinkFinished())
Utility::System::sleep(100); Utility::System::sleep(100);
@ -1451,6 +1480,7 @@ void PhongGLTest::constructAsync() {
PhongGL shader{std::move(state)}; PhongGL shader{std::move(state)};
CORRADE_COMPARE(shader.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset); CORRADE_COMPARE(shader.flags(), PhongGL::Flag::SpecularTexture|PhongGL::Flag::InstancedTextureOffset);
CORRADE_COMPARE(shader.lightCount(), 3); CORRADE_COMPARE(shader.lightCount(), 3);
CORRADE_COMPARE(shader.perDrawLightCount(), 2);
CORRADE_VERIFY(shader.isLinkFinished()); CORRADE_VERIFY(shader.isLinkFinished());
CORRADE_VERIFY(shader.id()); CORRADE_VERIFY(shader.id());
{ {
@ -1492,12 +1522,13 @@ void PhongGLTest::constructUniformBuffers() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(data.flags) .setFlags(data.flags)
.setLightCount(data.lightCount) .setLightCount(data.lightCount, data.perDrawLightCount)
.setMaterialCount(data.materialCount) .setMaterialCount(data.materialCount)
.setDrawCount(data.drawCount) .setDrawCount(data.drawCount)
.setJointCount(data.jointCount, data.perVertexJointCount, data.secondaryPerVertexJointCount)}; .setJointCount(data.jointCount, data.perVertexJointCount, data.secondaryPerVertexJointCount)};
CORRADE_COMPARE(shader.flags(), data.flags); CORRADE_COMPARE(shader.flags(), data.flags);
CORRADE_COMPARE(shader.lightCount(), data.lightCount); CORRADE_COMPARE(shader.lightCount(), data.lightCount);
CORRADE_COMPARE(shader.perDrawLightCount(), data.perDrawLightCount);
CORRADE_COMPARE(shader.materialCount(), data.materialCount); CORRADE_COMPARE(shader.materialCount(), data.materialCount);
CORRADE_COMPARE(shader.drawCount(), data.drawCount); CORRADE_COMPARE(shader.drawCount(), data.drawCount);
CORRADE_COMPARE(shader.jointCount(), data.jointCount); CORRADE_COMPARE(shader.jointCount(), data.jointCount);
@ -1526,12 +1557,13 @@ void PhongGLTest::constructUniformBuffersAsync() {
.setFlags(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling) .setFlags(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling)
/* SwiftShader has 256 uniform vectors at most, per-3D-draw is 4+4, /* SwiftShader has 256 uniform vectors at most, per-3D-draw is 4+4,
per-material 4, per-light 4, per joint 4 plus 4 for projection */ per-material 4, per-light 4, per joint 4 plus 4 for projection */
.setLightCount(2) .setLightCount(2, 1)
.setMaterialCount(5) .setMaterialCount(5)
.setDrawCount(24) .setDrawCount(24)
.setJointCount(7, 3, 4)); .setJointCount(7, 3, 4));
CORRADE_COMPARE(state.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling); CORRADE_COMPARE(state.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling);
CORRADE_COMPARE(state.lightCount(), 2); CORRADE_COMPARE(state.lightCount(), 2);
CORRADE_COMPARE(state.perDrawLightCount(), 1);
CORRADE_COMPARE(state.materialCount(), 5); CORRADE_COMPARE(state.materialCount(), 5);
CORRADE_COMPARE(state.drawCount(), 24); CORRADE_COMPARE(state.drawCount(), 24);
CORRADE_COMPARE(state.jointCount(), 7); CORRADE_COMPARE(state.jointCount(), 7);
@ -1544,6 +1576,7 @@ void PhongGLTest::constructUniformBuffersAsync() {
PhongGL shader{std::move(state)}; PhongGL shader{std::move(state)};
CORRADE_COMPARE(shader.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling); CORRADE_COMPARE(shader.flags(), PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling);
CORRADE_COMPARE(shader.lightCount(), 2); CORRADE_COMPARE(shader.lightCount(), 2);
CORRADE_COMPARE(shader.perDrawLightCount(), 1);
CORRADE_COMPARE(shader.materialCount(), 5); CORRADE_COMPARE(shader.materialCount(), 5);
CORRADE_COMPARE(shader.drawCount(), 24); CORRADE_COMPARE(shader.drawCount(), 24);
CORRADE_COMPARE(shader.jointCount(), 7); CORRADE_COMPARE(shader.jointCount(), 7);
@ -1564,7 +1597,7 @@ void PhongGLTest::constructUniformBuffersAsync() {
void PhongGLTest::constructMove() { void PhongGLTest::constructMove() {
PhongGL a{PhongGL::Configuration{} PhongGL a{PhongGL::Configuration{}
.setFlags(PhongGL::Flag::AlphaMask) .setFlags(PhongGL::Flag::AlphaMask)
.setLightCount(3) .setLightCount(3, 2)
/* Skinning properties tested in constructMoveUniformBuffers(), as /* Skinning properties tested in constructMoveUniformBuffers(), as
there we don't need to bother with ES2 */ there we don't need to bother with ES2 */
}; };
@ -1577,6 +1610,7 @@ void PhongGLTest::constructMove() {
CORRADE_COMPARE(b.id(), id); CORRADE_COMPARE(b.id(), id);
CORRADE_COMPARE(b.flags(), PhongGL::Flag::AlphaMask); CORRADE_COMPARE(b.flags(), PhongGL::Flag::AlphaMask);
CORRADE_COMPARE(b.lightCount(), 3); CORRADE_COMPARE(b.lightCount(), 3);
CORRADE_COMPARE(b.perDrawLightCount(), 2);
CORRADE_VERIFY(!a.id()); CORRADE_VERIFY(!a.id());
PhongGL c{NoCreate}; PhongGL c{NoCreate};
@ -1584,6 +1618,7 @@ void PhongGLTest::constructMove() {
CORRADE_COMPARE(c.id(), id); CORRADE_COMPARE(c.id(), id);
CORRADE_COMPARE(c.flags(), PhongGL::Flag::AlphaMask); CORRADE_COMPARE(c.flags(), PhongGL::Flag::AlphaMask);
CORRADE_COMPARE(c.lightCount(), 3); CORRADE_COMPARE(c.lightCount(), 3);
CORRADE_COMPARE(c.perDrawLightCount(), 2);
CORRADE_VERIFY(!b.id()); CORRADE_VERIFY(!b.id());
} }
@ -1598,7 +1633,7 @@ void PhongGLTest::constructMoveUniformBuffers() {
PhongGL a{PhongGL::Configuration{} PhongGL a{PhongGL::Configuration{}
.setFlags(PhongGL::Flag::UniformBuffers) .setFlags(PhongGL::Flag::UniformBuffers)
.setLightCount(3) .setLightCount(5, 3)
.setMaterialCount(2) .setMaterialCount(2)
.setDrawCount(5) .setDrawCount(5)
.setJointCount(16, 4, 3)}; .setJointCount(16, 4, 3)};
@ -1610,7 +1645,8 @@ void PhongGLTest::constructMoveUniformBuffers() {
PhongGL b{std::move(a)}; PhongGL b{std::move(a)};
CORRADE_COMPARE(b.id(), id); CORRADE_COMPARE(b.id(), id);
CORRADE_COMPARE(b.flags(), PhongGL::Flag::UniformBuffers); CORRADE_COMPARE(b.flags(), PhongGL::Flag::UniformBuffers);
CORRADE_COMPARE(b.lightCount(), 3); CORRADE_COMPARE(b.lightCount(), 5);
CORRADE_COMPARE(b.perDrawLightCount(), 3);
CORRADE_COMPARE(b.materialCount(), 2); CORRADE_COMPARE(b.materialCount(), 2);
CORRADE_COMPARE(b.drawCount(), 5); CORRADE_COMPARE(b.drawCount(), 5);
CORRADE_COMPARE(b.jointCount(), 16); CORRADE_COMPARE(b.jointCount(), 16);
@ -1622,7 +1658,8 @@ void PhongGLTest::constructMoveUniformBuffers() {
c = std::move(b); c = std::move(b);
CORRADE_COMPARE(c.id(), id); CORRADE_COMPARE(c.id(), id);
CORRADE_COMPARE(c.flags(), PhongGL::Flag::UniformBuffers); CORRADE_COMPARE(c.flags(), PhongGL::Flag::UniformBuffers);
CORRADE_COMPARE(c.lightCount(), 3); CORRADE_COMPARE(c.lightCount(), 5);
CORRADE_COMPARE(c.perDrawLightCount(), 3);
CORRADE_COMPARE(c.materialCount(), 2); CORRADE_COMPARE(c.materialCount(), 2);
CORRADE_COMPARE(c.drawCount(), 5); CORRADE_COMPARE(c.drawCount(), 5);
CORRADE_COMPARE(c.jointCount(), 16); CORRADE_COMPARE(c.jointCount(), 16);
@ -2185,13 +2222,27 @@ template<PhongGL::Flag flag> void PhongGLTest::renderColored() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(flag) .setFlags(flag)
.setLightCount(2)}; .setLightCount(data.lightCount, data.perDrawLightCount)};
if(flag == PhongGL::Flag{}) { if(flag == PhongGL::Flag{}) {
Color3 lightColors[]{
data.lightColor1,
data.lightColor2,
{},
{}
};
Vector4 lightPositions[]{
{data.lightPosition1, -3.0f, 2.0f, 0.0f},
{data.lightPosition2, -3.0f, 2.0f, 0.0f},
{},
{}
};
shader shader
.setLightColors({data.lightColor1, data.lightColor2}) .setLightColors(Containers::arrayView(lightColors)
.setLightPositions({{data.lightPosition1, -3.0f, 2.0f, 0.0f}, .prefix(data.lightCount))
{data.lightPosition2, -3.0f, 2.0f, 0.0f}}) .setLightPositions(Containers::arrayView(lightPositions)
.prefix(data.lightCount))
.setAmbientColor(0x330033_rgbf) .setAmbientColor(0x330033_rgbf)
.setDiffuseColor(0xccffcc_rgbf) .setDiffuseColor(0xccffcc_rgbf)
.setSpecularColor(0x6666ff_rgbf) .setSpecularColor(0x6666ff_rgbf)
@ -2229,7 +2280,9 @@ template<PhongGL::Flag flag> void PhongGLTest::renderColored() {
.setColor(data.lightColor1), .setColor(data.lightColor1),
PhongLightUniform{} PhongLightUniform{}
.setPosition({data.lightPosition2, -3.0f, 2.0f, 0.0f}) .setPosition({data.lightPosition2, -3.0f, 2.0f, 0.0f})
.setColor(data.lightColor2) .setColor(data.lightColor2),
PhongLightUniform{},
PhongLightUniform{}
}}; }};
shader shader
.bindProjectionBuffer(projectionUniform) .bindProjectionBuffer(projectionUniform)
@ -2315,6 +2368,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderSinglePixelTextured() {
#endif #endif
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(flags) .setFlags(flags)
/* Different count and per-draw count tested in renderColored() */
.setLightCount(2)}; .setLightCount(2)};
const Color4ub ambientData[]{ 0x330033_rgb }; const Color4ub ambientData[]{ 0x330033_rgb };
@ -2503,6 +2557,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderTextured() {
#endif #endif
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(flags) .setFlags(flags)
/* Different count and per-draw count tested in renderColored() */
.setLightCount(2)}; .setLightCount(2)};
Containers::Pointer<Trade::AbstractImporter> importer = _manager.loadAndInstantiate("AnyImageImporter"); Containers::Pointer<Trade::AbstractImporter> importer = _manager.loadAndInstantiate("AnyImageImporter");
@ -2750,6 +2805,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderTexturedNormal() {
#endif #endif
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(flags) .setFlags(flags)
/* Different count and per-draw count tested in renderColored() */
.setLightCount(2)}; .setLightCount(2)};
GL::Texture2D normal{NoCreate}; GL::Texture2D normal{NoCreate};
@ -2953,6 +3009,7 @@ template<class T, PhongGL::Flag flag> void PhongGLTest::renderVertexColor() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(PhongGL::Flag::DiffuseTexture|PhongGL::Flag::VertexColor|flag) .setFlags(PhongGL::Flag::DiffuseTexture|PhongGL::Flag::VertexColor|flag)
/* Different count and per-draw count tested in renderColored() */
.setLightCount(2)}; .setLightCount(2)};
shader.bindDiffuseTexture(diffuse); shader.bindDiffuseTexture(diffuse);
@ -3240,6 +3297,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderAlpha() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(data.flags|flag) .setFlags(data.flags|flag)
/* Different count and per-draw count tested in renderColored() */
.setLightCount(2)}; .setLightCount(2)};
shader.bindTextures(&ambient, &diffuse, nullptr, nullptr); shader.bindTextures(&ambient, &diffuse, nullptr, nullptr);
@ -3371,6 +3429,7 @@ template<PhongGL::Flag flag> void PhongGLTest::renderObjectId() {
} }
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(PhongGL::Flag::ObjectId|flags) .setFlags(PhongGL::Flag::ObjectId|flags)
/* Different count and per-draw count tested in renderColored() */
.setLightCount(2)}; .setLightCount(2)};
GL::Texture2D texture{NoCreate}; GL::Texture2D texture{NoCreate};
@ -3535,6 +3594,8 @@ template<PhongGL::Flag flag> void PhongGLTest::renderLights() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(flag) .setFlags(flag)
/* Different count and per-draw count tested in renderColored(), here
it's testing mainly the calculation */
.setLightCount(1)}; .setLightCount(1)};
if(flag == PhongGL::Flag{}) { if(flag == PhongGL::Flag{}) {
shader shader
@ -3724,6 +3785,9 @@ void PhongGLTest::renderLowLightAngle() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void PhongGLTest::renderLightCulling() { void PhongGLTest::renderLightCulling() {
auto&& data = RenderLightCullingData[testCaseInstanceId()];
setTestCaseDescription(data.name);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>()) if(!GL::Context::current().isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>())
CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported."); CORRADE_SKIP(GL::Extensions::ARB::uniform_buffer_object::string() << "is not supported.");
@ -3765,7 +3829,7 @@ void PhongGLTest::renderLightCulling() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling) .setFlags(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling)
.setLightCount(64)}; .setLightCount(data.count, data.perDrawCount)};
shader shader
.bindProjectionBuffer(projectionUniform) .bindProjectionBuffer(projectionUniform)
.bindTransformationBuffer(transformationUniform) .bindTransformationBuffer(transformationUniform)
@ -4714,7 +4778,7 @@ void PhongGLTest::renderMulti() {
PhongGL shader{PhongGL::Configuration{} PhongGL shader{PhongGL::Configuration{}
.setFlags(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling|data.flags) .setFlags(PhongGL::Flag::UniformBuffers|PhongGL::Flag::LightCulling|data.flags)
.setLightCount(data.lightCount) .setLightCount(data.lightCount, data.perDrawLightCount)
.setMaterialCount(data.materialCount) .setMaterialCount(data.materialCount)
.setDrawCount(data.drawCount)}; .setDrawCount(data.drawCount)};

34
src/Magnum/Shaders/Test/PhongGL_Test.cpp

@ -37,6 +37,7 @@ namespace Magnum { namespace Shaders { namespace Test { namespace {
struct PhongGL_Test: TestSuite::Tester { struct PhongGL_Test: TestSuite::Tester {
explicit PhongGL_Test(); explicit PhongGL_Test();
void configurationSetLightCountInvalid();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void configurationSetJointCountInvalid(); void configurationSetJointCountInvalid();
#endif #endif
@ -49,6 +50,22 @@ struct PhongGL_Test: TestSuite::Tester {
void debugFlagsSupersets(); void debugFlagsSupersets();
}; };
const struct {
const char* name;
UnsignedInt count, perDrawCount;
const char* message;
} ConfigurationSetLightCountInvalidData[] {
{"per-draw count larger than count",
10, 11,
"per-draw light count expected to be not larger than total count of 10, got 11"},
{"count but no per-draw count",
10, 0,
"count has to be non-zero iff per-draw count is non-zero"},
{"per-draw count but no count",
0, 2,
"count has to be non-zero iff per-draw count is non-zero"},
};
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
const struct { const struct {
const char* name; const char* name;
@ -74,6 +91,9 @@ const struct {
#endif #endif
PhongGL_Test::PhongGL_Test() { PhongGL_Test::PhongGL_Test() {
addInstancedTests({&PhongGL_Test::configurationSetLightCountInvalid},
Containers::arraySize(ConfigurationSetLightCountInvalidData));
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
addInstancedTests({&PhongGL_Test::configurationSetJointCountInvalid}, addInstancedTests({&PhongGL_Test::configurationSetJointCountInvalid},
Containers::arraySize(ConfigurationSetJointCountInvalidData)); Containers::arraySize(ConfigurationSetJointCountInvalidData));
@ -87,6 +107,20 @@ PhongGL_Test::PhongGL_Test() {
&PhongGL_Test::debugFlagsSupersets}); &PhongGL_Test::debugFlagsSupersets});
} }
void PhongGL_Test::configurationSetLightCountInvalid() {
auto&& data = ConfigurationSetLightCountInvalidData[testCaseInstanceId()];
setTestCaseDescription(data.name);
CORRADE_SKIP_IF_NO_ASSERT();
PhongGL::Configuration configuration;
std::ostringstream out;
Error redirectError{&out};
configuration.setLightCount(data.count, data.perDrawCount);
CORRADE_COMPARE(out.str(), Utility::formatString("Shaders::PhongGL::Configuration::setLightCount(): {}\n", data.message));
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void PhongGL_Test::configurationSetJointCountInvalid() { void PhongGL_Test::configurationSetJointCountInvalid() {
auto&& data = ConfigurationSetJointCountInvalidData[testCaseInstanceId()]; auto&& data = ConfigurationSetJointCountInvalidData[testCaseInstanceId()];

Loading…
Cancel
Save