Browse Source

Shaders: ability to disable Phong specular contribution.

In cases when specular highlights are not desired, results in 30%
speedup (on Intel) and ~25% speedup on AMD, compared to setting the
specular color to transparent black.

Testing was easy thanks to already having a ground truth image for this
case.
pull/518/head
Vladimír Vondruš 5 years ago
parent
commit
cc74784d40
  1. 3
      doc/changelog.dox
  2. 10
      src/Magnum/Shaders/Phong.frag
  3. 8
      src/Magnum/Shaders/Phong.h
  4. 36
      src/Magnum/Shaders/PhongGL.cpp
  5. 32
      src/Magnum/Shaders/PhongGL.h
  6. 2
      src/Magnum/Shaders/Test/CMakeLists.txt
  7. 57
      src/Magnum/Shaders/Test/PhongGLTest.cpp
  8. 4
      src/Magnum/Shaders/Test/PhongGL_Test.cpp
  9. 0
      src/Magnum/Shaders/Test/PhongTestFiles/shininess-no-specular.tga
  10. 1
      src/Magnum/Shaders/Test/ShadersGLBenchmark.cpp

3
doc/changelog.dox

@ -161,6 +161,9 @@ See also:
@ref Trade::LightData @ref Trade::LightData
- Added @ref Shaders::PhongGL::setLightSpecularColors() for better control - Added @ref Shaders::PhongGL::setLightSpecularColors() for better control
over specular highlights over specular highlights
- Added @ref Shaders::PhongGL::Flag::NoSpecular as a significantly faster
alternative to setting specular color to @cpp 0x00000000_rgbaf @ce in case
specular highlights are not desired
@subsubsection changelog-latest-new-shadertools ShaderTools library @subsubsection changelog-latest-new-shadertools ShaderTools library

10
src/Magnum/Shaders/Phong.frag

@ -63,6 +63,7 @@ uniform lowp vec4 diffuseColor
#endif #endif
; ;
#ifndef NO_SPECULAR
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = 7) layout(location = 7)
#endif #endif
@ -81,6 +82,7 @@ uniform mediump float shininess
#endif #endif
; ;
#endif #endif
#endif
#ifdef NORMAL_TEXTURE #ifdef NORMAL_TEXTURE
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
@ -136,6 +138,7 @@ uniform lowp vec3 lightColors[LIGHT_COUNT]
#endif #endif
; ;
#ifndef NO_SPECULAR
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = LIGHT_SPECULAR_COLORS_LOCATION) layout(location = LIGHT_SPECULAR_COLORS_LOCATION)
#endif #endif
@ -144,6 +147,7 @@ uniform lowp vec3 lightSpecularColors[LIGHT_COUNT]
= vec3[](LIGHT_COLOR_INITIALIZER) = vec3[](LIGHT_COLOR_INITIALIZER)
#endif #endif
; ;
#endif
#ifdef EXPLICIT_UNIFORM_LOCATION #ifdef EXPLICIT_UNIFORM_LOCATION
layout(location = LIGHT_RANGES_LOCATION) layout(location = LIGHT_RANGES_LOCATION)
@ -386,12 +390,14 @@ void main() {
interpolatedVertexColor* interpolatedVertexColor*
#endif #endif
diffuseColor; diffuseColor;
#ifndef NO_SPECULAR
lowp const vec4 finalSpecularColor = lowp const vec4 finalSpecularColor =
#ifdef SPECULAR_TEXTURE #ifdef SPECULAR_TEXTURE
texture(specularTexture, interpolatedTextureCoordinates)* texture(specularTexture, interpolatedTextureCoordinates)*
#endif #endif
specularColor; specularColor;
#endif #endif
#endif
/* Ambient color */ /* Ambient color */
fragmentColor = finalAmbientColor; fragmentColor = finalAmbientColor;
@ -439,6 +445,7 @@ void main() {
i].light_color i].light_color
#endif #endif
; ;
#ifndef NO_SPECULAR
lowp const vec3 lightSpecularColor = lowp const vec3 lightSpecularColor =
#ifndef UNIFORM_BUFFERS #ifndef UNIFORM_BUFFERS
lightSpecularColors[i] lightSpecularColors[i]
@ -450,6 +457,7 @@ void main() {
i].light_specularColor i].light_specularColor
#endif #endif
; ;
#endif
lowp const float lightRange = lowp const float lightRange =
#ifndef UNIFORM_BUFFERS #ifndef UNIFORM_BUFFERS
lightRanges[i] lightRanges[i]
@ -490,6 +498,7 @@ void main() {
lowp float intensity = max(0.0, dot(normalizedTransformedNormal, normalizedLightDirection))*attenuation; lowp float intensity = max(0.0, dot(normalizedTransformedNormal, normalizedLightDirection))*attenuation;
fragmentColor.rgb += finalDiffuseColor.rgb*lightColor*intensity; fragmentColor.rgb += finalDiffuseColor.rgb*lightColor*intensity;
#ifndef NO_SPECULAR
/* Add specular color, if needed */ /* Add specular color, if needed */
if(intensity > 0.001) { if(intensity > 0.001) {
highp vec3 reflection = reflect(-normalizedLightDirection, normalizedTransformedNormal); highp vec3 reflection = reflect(-normalizedLightDirection, normalizedTransformedNormal);
@ -497,6 +506,7 @@ void main() {
mediump float specularity = clamp(pow(max(0.0, dot(cameraDirection, reflection)), shininess), 0.0, 1.0)*attenuation; mediump float specularity = clamp(pow(max(0.0, dot(cameraDirection, reflection)), shininess), 0.0, 1.0)*attenuation;
fragmentColor += vec4(finalSpecularColor.rgb*lightSpecularColor.rgb*specularity, finalSpecularColor.a); fragmentColor += vec4(finalSpecularColor.rgb*lightSpecularColor.rgb*specularity, finalSpecularColor.a);
} }
#endif
} }
fragmentColor.a += finalDiffuseColor.a; fragmentColor.a += finalDiffuseColor.a;

8
src/Magnum/Shaders/Phong.h

@ -326,8 +326,8 @@ struct PhongMaterialUniform {
* *
* Default value is @cpp 0xffffff00_rgbaf @ce. * Default value is @cpp 0xffffff00_rgbaf @ce.
* *
* Used only if the effective light count for given draw is not zero, * Used only if the effective light count for given draw is not zero and
* ignored otherwise. * @ref PhongGL::Flag::NoSpecular is not set, ignored otherwise.
* @see @ref PhongGL::setSpecularColor() * @see @ref PhongGL::setSpecularColor()
*/ */
Color4 specularColor; Color4 specularColor;
@ -351,8 +351,8 @@ struct PhongMaterialUniform {
* The larger value, the harder surface (smaller specular highlight). * The larger value, the harder surface (smaller specular highlight).
* Default value is @cpp 80.0f @ce. * Default value is @cpp 80.0f @ce.
* *
* Used only if the effective light count for given draw is not zero, * Used only if the effective light count for given draw is not zero and
* ignored otherwise. * @ref PhongGL::Flag::NoSpecular is not set, ignored otherwise.
* @see @ref PhongGL::setShininess() * @see @ref PhongGL::setShininess()
*/ */
Float shininess; Float shininess;

36
src/Magnum/Shaders/PhongGL.cpp

@ -111,6 +111,9 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
"Shaders::PhongGL: light culling requires uniform buffers to be enabled", ); "Shaders::PhongGL: light culling requires uniform buffers to be enabled", );
#endif #endif
CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)),
"Shaders::PhongGL: specular texture requires the shader to not have specular disabled", );
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(flags >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
@ -243,6 +246,7 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
.addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif #endif
.addSource(flags & Flag::NoSpecular ? "#define NO_SPECULAR\n" : "")
; ;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(flags >= Flag::UniformBuffers) {
@ -338,13 +342,16 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
if(lightCount) { if(lightCount) {
_normalMatrixUniform = uniformLocation("normalMatrix"); _normalMatrixUniform = uniformLocation("normalMatrix");
_diffuseColorUniform = uniformLocation("diffuseColor"); _diffuseColorUniform = uniformLocation("diffuseColor");
_specularColorUniform = uniformLocation("specularColor"); if(!(flags & Flag::NoSpecular)) {
_shininessUniform = uniformLocation("shininess"); _specularColorUniform = uniformLocation("specularColor");
_shininessUniform = uniformLocation("shininess");
}
if(flags & Flag::NormalTexture) if(flags & Flag::NormalTexture)
_normalTextureScaleUniform = uniformLocation("normalTextureScale"); _normalTextureScaleUniform = uniformLocation("normalTextureScale");
_lightPositionsUniform = uniformLocation("lightPositions"); _lightPositionsUniform = uniformLocation("lightPositions");
_lightColorsUniform = uniformLocation("lightColors"); _lightColorsUniform = uniformLocation("lightColors");
_lightSpecularColorsUniform = uniformLocation("lightSpecularColors"); if(!(flags & Flag::NoSpecular))
_lightSpecularColorsUniform = uniformLocation("lightSpecularColors");
_lightRangesUniform = uniformLocation("lightRanges"); _lightRangesUniform = uniformLocation("lightRanges");
} }
if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask"); if(flags & Flag::AlphaMask) _alphaMaskUniform = uniformLocation("alphaMask");
@ -393,14 +400,17 @@ PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount
setProjectionMatrix(Matrix4{Math::IdentityInit}); setProjectionMatrix(Matrix4{Math::IdentityInit});
if(lightCount) { if(lightCount) {
setDiffuseColor(Magnum::Color4{1.0f}); setDiffuseColor(Magnum::Color4{1.0f});
setSpecularColor(Magnum::Color4{1.0f, 0.0f}); if(!(flags & Flag::NoSpecular)) {
setShininess(80.0f); setSpecularColor(Magnum::Color4{1.0f, 0.0f});
setShininess(80.0f);
}
if(flags & Flag::NormalTexture) if(flags & Flag::NormalTexture)
setNormalTextureScale(1.0f); setNormalTextureScale(1.0f);
setLightPositions(Containers::Array<Vector4>{DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}}); setLightPositions(Containers::Array<Vector4>{DirectInit, lightCount, Vector4{0.0f, 0.0f, 1.0f, 0.0f}});
Containers::Array<Magnum::Color3> colors{DirectInit, lightCount, Magnum::Color3{1.0f}}; Containers::Array<Magnum::Color3> colors{DirectInit, lightCount, Magnum::Color3{1.0f}};
setLightColors(colors); setLightColors(colors);
setLightSpecularColors(colors); if(!(flags & Flag::NoSpecular))
setLightSpecularColors(colors);
setLightRanges(Containers::Array<Float>{DirectInit, lightCount, Constants::inf()}); setLightRanges(Containers::Array<Float>{DirectInit, lightCount, Constants::inf()});
/* Light position is zero by default */ /* Light position is zero by default */
setNormalMatrix(Matrix3x3{Math::IdentityInit}); setNormalMatrix(Matrix3x3{Math::IdentityInit});
@ -441,6 +451,8 @@ PhongGL& PhongGL::setSpecularColor(const Magnum::Color4& color) {
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
"Shaders::PhongGL::setSpecularColor(): the shader was created with uniform buffers enabled", *this); "Shaders::PhongGL::setSpecularColor(): the shader was created with uniform buffers enabled", *this);
#endif #endif
CORRADE_ASSERT(!(_flags >= Flag::NoSpecular),
"Shaders::PhongGL::setSpecularColor(): the shader was created with specular disabled", *this);
if(_lightCount) setUniform(_specularColorUniform, color); if(_lightCount) setUniform(_specularColorUniform, color);
return *this; return *this;
} }
@ -450,6 +462,8 @@ PhongGL& PhongGL::setShininess(Float shininess) {
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),
"Shaders::PhongGL::setShininess(): the shader was created with uniform buffers enabled", *this); "Shaders::PhongGL::setShininess(): the shader was created with uniform buffers enabled", *this);
#endif #endif
CORRADE_ASSERT(!(_flags >= Flag::NoSpecular),
"Shaders::PhongGL::setShininess(): the shader was created with specular disabled", *this);
if(_lightCount) setUniform(_shininessUniform, shininess); if(_lightCount) setUniform(_shininessUniform, shininess);
return *this; return *this;
} }
@ -651,6 +665,8 @@ PhongGL& PhongGL::setLightSpecularColors(const Containers::ArrayView<const Magnu
#endif #endif
CORRADE_ASSERT(_lightCount == colors.size(), CORRADE_ASSERT(_lightCount == colors.size(),
"Shaders::PhongGL::setLightSpecularColors(): expected" << _lightCount << "items but got" << colors.size(), *this); "Shaders::PhongGL::setLightSpecularColors(): expected" << _lightCount << "items but got" << colors.size(), *this);
CORRADE_ASSERT(!(_flags >= Flag::NoSpecular),
"Shaders::PhongGL::setLightSpecularColors(): the shader was created with specular disabled", *this);
if(_lightCount) setUniform(_lightSpecularColorsUniform, colors); if(_lightCount) setUniform(_lightSpecularColorsUniform, colors);
return *this; return *this;
} }
@ -666,6 +682,8 @@ PhongGL& PhongGL::setLightSpecularColor(const UnsignedInt id, const Magnum::Colo
#endif #endif
CORRADE_ASSERT(id < _lightCount, CORRADE_ASSERT(id < _lightCount,
"Shaders::PhongGL::setLightSpecularColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this); "Shaders::PhongGL::setLightSpecularColor(): light ID" << id << "is out of bounds for" << _lightCount << "lights", *this);
CORRADE_ASSERT(!(_flags >= Flag::NoSpecular),
"Shaders::PhongGL::setLightSpecularColor(): the shader was created with specular disabled", *this);
setUniform(_lightSpecularColorsUniform + id, color); setUniform(_lightSpecularColorsUniform + id, color);
return *this; return *this;
} }
@ -920,11 +938,12 @@ Debug& operator<<(Debug& debug, const PhongGL::Flag value) {
_c(TextureArrays) _c(TextureArrays)
_c(LightCulling) _c(LightCulling)
#endif #endif
_c(NoSpecular)
#undef _c #undef _c
/* LCOV_EXCL_STOP */ /* LCOV_EXCL_STOP */
} }
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")"; return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedInt(value)) << Debug::nospace << ")";
} }
Debug& operator<<(Debug& debug, const PhongGL::Flags value) { Debug& operator<<(Debug& debug, const PhongGL::Flags value) {
@ -947,8 +966,9 @@ Debug& operator<<(Debug& debug, const PhongGL::Flags value) {
PhongGL::Flag::MultiDraw, /* Superset of UniformBuffers */ PhongGL::Flag::MultiDraw, /* Superset of UniformBuffers */
PhongGL::Flag::UniformBuffers, PhongGL::Flag::UniformBuffers,
PhongGL::Flag::TextureArrays, PhongGL::Flag::TextureArrays,
PhongGL::Flag::LightCulling PhongGL::Flag::LightCulling,
#endif #endif
PhongGL::Flag::NoSpecular
}); });
} }

32
src/Magnum/Shaders/PhongGL.h

@ -484,7 +484,7 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* *
* @see @ref Flags, @ref flags() * @see @ref Flags, @ref flags()
*/ */
enum class Flag: UnsignedShort { enum class Flag: UnsignedInt {
/** /**
* Multiply ambient color with a texture. * Multiply ambient color with a texture.
* @see @ref setAmbientColor(), @ref bindAmbientTexture() * @see @ref setAmbientColor(), @ref bindAmbientTexture()
@ -705,8 +705,17 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* 1.0. * 1.0.
* @m_since_latest * @m_since_latest
*/ */
LightCulling = 1 << 15 LightCulling = 1 << 15,
#endif #endif
/**
* Disable specular contribution in light calculation. Can result
* in a significant performance improvement compared to calling
* @ref setSpecularColor() with @cpp 0x00000000_rgbaf @ce when
* specular highlights are not desired.
* @m_since_latest
*/
NoSpecular = 1 << 16
}; };
/** /**
@ -900,10 +909,13 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @brief Set specular color * @brief Set specular color
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Initial value is @cpp 0xffffff00_rgbaf @ce. If * Initial value is @cpp 0xffffff00_rgbaf @ce. Expects that the shader
* was not created with @ref Flag::NoSpecular. If
* @ref Flag::SpecularTexture is set, the color will be multiplied with * @ref Flag::SpecularTexture is set, the color will be multiplied with
* the texture. If you want to have a fully diffuse material, set * the texture. If you want to have a fully diffuse material, it's
* the specular color to @cpp 0x00000000_rgbaf @ce. If * recommended to disable the specular contribution altogether with
* @ref Flag::NoSpecular. If having a dedicated shader variant is not
* possible, set the specular color to @cpp 0x00000000_rgbaf @ce. If
* @ref lightCount() is zero, this function is a no-op, as specular * @ref lightCount() is zero, this function is a no-op, as specular
* color doesn't contribute to the output in that case. * color doesn't contribute to the output in that case.
* *
@ -1530,7 +1542,8 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* Expects that the shader was created with @ref Flag::SpecularTexture * Expects that the shader was created with @ref Flag::SpecularTexture
* enabled. If @ref Flag::TextureArrays is enabled as well, use * enabled and that @ref Flag::NoSpecular is not set. If
* @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 lightCount() is zero, this function is a no-op, as specular
* color doesn't contribute to the output in that case. * color doesn't contribute to the output in that case.
@ -1545,9 +1558,10 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @m_since_latest * @m_since_latest
* *
* Expects that the shader was created with both * Expects that the shader was created with both
* @ref Flag::SpecularTexture and @ref Flag::TextureArrays enabled. If * @ref Flag::SpecularTexture and @ref Flag::TextureArrays enabled and
* @ref Flag::UniformBuffers is not enabled, the layer is set via * that @ref Flag::NoSpecular is not set. If @ref Flag::UniformBuffers
* @ref setTextureLayer(); if @ref Flag::UniformBuffers is enabled, * is not enabled, the layer is set via @ref setTextureLayer(); if
* @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 lightCount() is zero, this function is a no-op, as specular

2
src/Magnum/Shaders/Test/CMakeLists.txt

@ -280,7 +280,7 @@ if(BUILD_GL_TESTS)
PhongTestFiles/instanced.tga PhongTestFiles/instanced.tga
PhongTestFiles/instanced-normal.tga PhongTestFiles/instanced-normal.tga
PhongTestFiles/low-light-angle.tga PhongTestFiles/low-light-angle.tga
PhongTestFiles/shininess-black-specular.tga PhongTestFiles/shininess-no-specular.tga
PhongTestFiles/shininess0-overflow.tga PhongTestFiles/shininess0-overflow.tga
PhongTestFiles/shininess0.tga PhongTestFiles/shininess0.tga
PhongTestFiles/shininess10.tga PhongTestFiles/shininess10.tga

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

@ -100,6 +100,7 @@ struct PhongGLTest: GL::OpenGLTester {
void bindTextureArraysInvalid(); void bindTextureArraysInvalid();
#endif #endif
void setAlphaMaskNotEnabled(); void setAlphaMaskNotEnabled();
void setSpecularDisabled();
void setTextureMatrixNotEnabled(); void setTextureMatrixNotEnabled();
void setNormalTextureScaleNotEnabled(); void setNormalTextureScaleNotEnabled();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -233,6 +234,7 @@ constexpr struct {
{"instanced object ID", PhongGL::Flag::InstancedObjectId, 1}, {"instanced object ID", PhongGL::Flag::InstancedObjectId, 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},
#endif #endif
{"no specular", PhongGL::Flag::NoSpecular, 1},
{"five lights", {}, 5}, {"five lights", {}, 5},
{"zero lights", {}, 0}, {"zero lights", {}, 0},
{"instanced transformation", PhongGL::Flag::InstancedTransformation, 3}, {"instanced transformation", PhongGL::Flag::InstancedTransformation, 3},
@ -265,6 +267,7 @@ constexpr struct {
{"normal texture + separate bitangents", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1, 1, 1}, {"normal texture + separate bitangents", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NormalTexture|PhongGL::Flag::Bitangent, 1, 1, 1},
{"alpha mask", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AlphaMask, 1, 1, 1}, {"alpha mask", PhongGL::Flag::UniformBuffers|PhongGL::Flag::AlphaMask, 1, 1, 1},
{"object ID", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectId, 1, 1, 1}, {"object ID", PhongGL::Flag::UniformBuffers|PhongGL::Flag::ObjectId, 1, 1, 1},
{"no specular", PhongGL::Flag::UniformBuffers|PhongGL::Flag::NoSpecular, 1, 1, 1},
{"multidraw with all the things", 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, 8, 16, 24} {"multidraw with all the things", 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, 8, 16, 24}
}; };
#endif #endif
@ -284,6 +287,9 @@ constexpr struct {
PhongGL::Flag::Bitangent|PhongGL::Flag::InstancedObjectId, PhongGL::Flag::Bitangent|PhongGL::Flag::InstancedObjectId,
"Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead"}, "Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead"},
#endif #endif
{"specular texture but no specular",
PhongGL::Flag::SpecularTexture|PhongGL::Flag::NoSpecular,
"specular texture requires the shader to not have specular disabled"}
}; };
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -472,14 +478,22 @@ const struct {
const struct { const struct {
const char* name; const char* name;
const char* expected; const char* expected;
PhongGL::Flags flags;
Float shininess; Float shininess;
Color4 specular; Color4 specular;
} RenderShininessData[] { } RenderShininessData[] {
{"80", "shininess80.tga", 80.0f, 0xffffff_rgbf}, {"80", "shininess80.tga",
{"10", "shininess10.tga", 10.0f, 0xffffff_rgbf}, {}, 80.0f, 0xffffff_rgbf},
{"0", "shininess0.tga", 0.0f, 0xffffff_rgbf}, {"10", "shininess10.tga",
{"0.001", "shininess0.tga", 0.001f, 0xffffff_rgbf}, {}, 10.0f, 0xffffff_rgbf},
{"black specular", "shininess-black-specular.tga", 80.0f, 0x000000_rgbf} {"0", "shininess0.tga",
{}, 0.0f, 0xffffff_rgbf},
{"0.001", "shininess0.tga",
{}, 0.001f, 0xffffff_rgbf},
{"black specular", "shininess-no-specular.tga",
{}, 80.0f, 0x000000_rgbf},
{"no specular", "shininess-no-specular.tga",
PhongGL::Flag::NoSpecular, 80.0f, 0xffffff_rgbf}
}; };
const struct { const struct {
@ -777,6 +791,7 @@ PhongGLTest::PhongGLTest() {
addTests({ addTests({
&PhongGLTest::setAlphaMaskNotEnabled, &PhongGLTest::setAlphaMaskNotEnabled,
&PhongGLTest::setSpecularDisabled,
&PhongGLTest::setTextureMatrixNotEnabled, &PhongGLTest::setTextureMatrixNotEnabled,
&PhongGLTest::setNormalTextureScaleNotEnabled, &PhongGLTest::setNormalTextureScaleNotEnabled,
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
@ -1306,6 +1321,27 @@ void PhongGLTest::setAlphaMaskNotEnabled() {
"Shaders::PhongGL::setAlphaMask(): the shader was not created with alpha mask enabled\n"); "Shaders::PhongGL::setAlphaMask(): the shader was not created with alpha mask enabled\n");
} }
void PhongGLTest::setSpecularDisabled() {
#ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
#endif
std::ostringstream out;
Error redirectError{&out};
GL::Texture2D texture;
PhongGL shader{PhongGL::Flag::NoSpecular};
shader.setSpecularColor({})
.setShininess({})
.setLightSpecularColors({{}})
.setLightSpecularColor(0, {});
CORRADE_COMPARE(out.str(),
"Shaders::PhongGL::setSpecularColor(): the shader was created with specular disabled\n"
"Shaders::PhongGL::setShininess(): the shader was created with specular disabled\n"
"Shaders::PhongGL::setLightSpecularColors(): the shader was created with specular disabled\n"
"Shaders::PhongGL::setLightSpecularColor(): the shader was created with specular disabled\n");
}
void PhongGLTest::setTextureMatrixNotEnabled() { void PhongGLTest::setTextureMatrixNotEnabled() {
#ifdef CORRADE_NO_ASSERT #ifdef CORRADE_NO_ASSERT
CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions"); CORRADE_SKIP("CORRADE_NO_ASSERT defined, can't test assertions");
@ -2427,13 +2463,14 @@ template<PhongGL::Flag flag> void PhongGLTest::renderShininess() {
GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32)); GL::Mesh sphere = MeshTools::compile(Primitives::uvSphereSolid(16, 32));
PhongGL shader{flag}; PhongGL shader{flag|data.flags};
if(flag == PhongGL::Flag{}) { if(flag == PhongGL::Flag{}) {
if(!(data.flags & PhongGL::Flag::NoSpecular)) shader
.setSpecularColor(data.specular)
.setShininess(data.shininess);
shader shader
.setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}}) .setLightPositions({{-3.0f, -3.0f, 2.0f, 0.0f}})
.setDiffuseColor(0xff3333_rgbf) .setDiffuseColor(0xff3333_rgbf)
.setSpecularColor(data.specular)
.setShininess(data.shininess)
.setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f))) .setTransformationMatrix(Matrix4::translation(Vector3::zAxis(-2.15f)))
.setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f)) .setProjectionMatrix(Matrix4::perspectiveProjection(60.0_degf, 1.0f, 0.1f, 10.0f))
.draw(sphere); .draw(sphere);
@ -2459,8 +2496,8 @@ template<PhongGL::Flag flag> void PhongGLTest::renderShininess() {
GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, { GL::Buffer materialUniform{GL::Buffer::TargetHint::Uniform, {
PhongMaterialUniform{} PhongMaterialUniform{}
.setDiffuseColor(0xff3333_rgbf) .setDiffuseColor(0xff3333_rgbf)
.setSpecularColor(data.specular) .setSpecularColor(data.specular) /* ignored if NoSpecular */
.setShininess(data.shininess) .setShininess(data.shininess) /* ignored if NoSpecular */
}}; }};
shader shader
.bindProjectionBuffer(projectionUniform) .bindProjectionBuffer(projectionUniform)

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

@ -72,8 +72,8 @@ void PhongGL_Test::constructCopy() {
void PhongGL_Test::debugFlag() { void PhongGL_Test::debugFlag() {
std::ostringstream out; std::ostringstream out;
Debug{&out} << PhongGL::Flag::AmbientTexture << PhongGL::Flag(0xf0); Debug{&out} << PhongGL::Flag::AmbientTexture << PhongGL::Flag(0xcafedead);
CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::AmbientTexture Shaders::PhongGL::Flag(0xf0)\n"); CORRADE_COMPARE(out.str(), "Shaders::PhongGL::Flag::AmbientTexture Shaders::PhongGL::Flag(0xcafedead)\n");
} }
void PhongGL_Test::debugFlags() { void PhongGL_Test::debugFlags() {

0
src/Magnum/Shaders/Test/PhongTestFiles/shininess-black-specular.tga → src/Magnum/Shaders/Test/PhongTestFiles/shininess-no-specular.tga

1
src/Magnum/Shaders/Test/ShadersGLBenchmark.cpp

@ -171,6 +171,7 @@ const struct {
{"", {}, 1, 1, 1, false}, {"", {}, 1, 1, 1, false},
{"zero lights", {}, 0, 1, 1, false}, {"zero lights", {}, 0, 1, 1, false},
{"five lights", {}, 5, 1, 1, false}, {"five lights", {}, 5, 1, 1, false},
{"no specular", PhongGL::Flag::NoSpecular, 1, 1, 1, false},
{"vertex color", PhongGL::Flag::VertexColor, 1, 1, 1, false}, {"vertex color", PhongGL::Flag::VertexColor, 1, 1, 1, false},
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
{"object ID", PhongGL::Flag::ObjectId, 1, 1, 1, false}, {"object ID", PhongGL::Flag::ObjectId, 1, 1, 1, false},

Loading…
Cancel
Save