From c5abcf51406ad675873bebcc01b903e8e47eab28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 13 Nov 2022 17:22:52 +0100 Subject: [PATCH] Shaders: take constructor arguments via a Configuration instance. Because it was no longer bearable with three UnsignedInt arguments in a row, especially when some of them are only available on a subset of platforms. And it would get even worse with introduction of planned features such as multiview or skinning. Backwards compatibility is in place, as always. To ensure nothing breaks, this commit still has all tests and snippets using the old API. --- doc/changelog.dox | 4 + src/Magnum/Shaders/DistanceFieldVectorGL.cpp | 77 ++-- src/Magnum/Shaders/DistanceFieldVectorGL.h | 181 ++++++--- src/Magnum/Shaders/FlatGL.cpp | 127 +++--- src/Magnum/Shaders/FlatGL.h | 178 ++++++--- src/Magnum/Shaders/MeshVisualizerGL.cpp | 206 +++++----- src/Magnum/Shaders/MeshVisualizerGL.h | 384 ++++++++++++------- src/Magnum/Shaders/PhongGL.cpp | 200 +++++----- src/Magnum/Shaders/PhongGL.h | 209 +++++++--- src/Magnum/Shaders/VectorGL.cpp | 74 ++-- src/Magnum/Shaders/VectorGL.h | 178 ++++++--- src/Magnum/Shaders/VertexColorGL.cpp | 58 ++- src/Magnum/Shaders/VertexColorGL.h | 147 ++++--- 13 files changed, 1342 insertions(+), 681 deletions(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index d6353e94e..1b41e7223 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -911,6 +911,10 @@ See also: and correspondingly renamed typedefs to make room for Vulkan shaders and functionality shared between OpenGL and Vulkan implementation such as uniform buffer layout definitions +- @ref Shaders class constructors taking flags and other parameters directly + are deprecated in favor of constructors taking a configuration instance + such as @ref Shaders::FlatGL::FlatGL(const Configuration&) for better + extensibility - @ref Shaders::PhongGL::setLightPositions() and @ref Shaders::PhongGL::setLightPosition() taking three-component vectors are deprecated in favor of variants taking four-component vectors, where the diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp index 94519c22b..56e05c21c 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.cpp +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.cpp @@ -64,24 +64,20 @@ namespace { #endif } -template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Flags flags +template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Configuration& configuration) { #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -) { - #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(), "Shaders::DistanceFieldVectorGL: material count can't be zero", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::DistanceFieldVectorGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); #endif #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::MultiDraw) { + if(configuration.flags() >= Flag::MultiDraw) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); #elif !defined(MAGNUM_TARGET_WEBGL) @@ -110,28 +106,28 @@ template typename DistanceFieldVectorGL::Com GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); - vert.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") + vert.addSource(configuration.flags() & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n"); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { vert.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n", - drawCount)); - vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount())); + vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif vert.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Vector.vert")); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { frag.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define MATERIAL_COUNT {}\n" "#define DRAW_COUNT {}\n", - materialCount, - drawCount)); - frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.materialCount(), + configuration.drawCount())); + frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif frag.addSource(rs.getString("generic.glsl")) @@ -141,10 +137,10 @@ template typename DistanceFieldVectorGL::Com frag.submitCompile(); DistanceFieldVectorGL out{NoInit}; - out._flags = flags; + out._flags = configuration.flags(); #ifndef MAGNUM_TARGET_GLES2 - out._materialCount = materialCount; - out._drawCount = drawCount; + out._materialCount = configuration.materialCount(); + out._drawCount = configuration.drawCount(); #endif out.attachShaders({vert, frag}); @@ -164,6 +160,26 @@ template typename DistanceFieldVectorGL::Com return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } +template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile() { + return compile(Configuration{}); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Flags flags) { + return compile(Configuration{} + .setFlags(flags)); +} + +#ifndef MAGNUM_TARGET_GLES2 +template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount)); +} +#endif +#endif + template DistanceFieldVectorGL::DistanceFieldVectorGL(CompileState&& state): DistanceFieldVectorGL{static_cast(std::move(state))} { #ifdef CORRADE_GRACEFUL_ASSERT /* When graceful assertions fire from within compile(), we get a NoCreate'd @@ -234,19 +250,24 @@ template DistanceFieldVectorGL::DistanceFiel static_cast(version); } -template DistanceFieldVectorGL::DistanceFieldVectorGL(NoInitT) {} +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Configuration& configuration): DistanceFieldVectorGL{compile(configuration)} {} -template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(flags)} {} +template DistanceFieldVectorGL::DistanceFieldVectorGL(): DistanceFieldVectorGL{Configuration{}} {} -#ifndef MAGNUM_TARGET_GLES2 -template typename DistanceFieldVectorGL::CompileState DistanceFieldVectorGL::compile(const Flags flags) { - return compile(flags, 1, 1); -} +#ifdef MAGNUM_BUILD_DEPRECATED +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(Configuration{} + .setFlags(flags))} {} -template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): - DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +template DistanceFieldVectorGL::DistanceFieldVectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): DistanceFieldVectorGL{compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount))} {} +#endif #endif +template DistanceFieldVectorGL::DistanceFieldVectorGL(NoInitT) {} + template DistanceFieldVectorGL& DistanceFieldVectorGL::setTransformationProjectionMatrix(const MatrixTypeFor& matrix) { #ifndef MAGNUM_TARGET_GLES2 CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h index a959dd92d..79306bec5 100644 --- a/src/Magnum/Shaders/DistanceFieldVectorGL.h +++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h @@ -122,6 +122,7 @@ example. */ template class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL: public GL::AbstractShaderProgram { public: + class Configuration; class CompileState; /** @@ -225,80 +226,71 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref DistanceFieldVectorGL(Flags) can perform an - * asynchronous compilation and linking. See @ref shaders-async for - * more information. - * @see @ref DistanceFieldVectorGL(CompileState&&), - * @ref compile(Flags, UnsignedInt, UnsignedInt) + * Compared to @ref DistanceFieldVectorGL(const Configuration&) can + * perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref DistanceFieldVectorGL(CompileState&&) + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + static CompileState compile(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + static CompileState compile(const Configuration& configuration); + static CompileState compile(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. */ - static CompileState compile(Flags flags = {}); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref DistanceFieldVectorGL(Flags, UnsignedInt, UnsignedInt) - * can perform an asynchronous compilation and linking. See - * @ref shaders-async for more information. - * @see @ref DistanceFieldVectorGL(CompileState&&), @ref compile(Flags) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref DistanceFieldVectorGL(Flags, UnsignedInt, UnsignedInt) with - * @p materialCount and @p drawCount set to @cpp 1 @ce. - * @see @ref compile(Flags) + * @m_since_latest + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit DistanceFieldVectorGL(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + explicit DistanceFieldVectorGL(const Configuration& configuration); + explicit DistanceFieldVectorGL(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref DistanceFieldVectorGL(const Configuration&) + * instead. */ - explicit DistanceFieldVectorGL(Flags flags = {}); + explicit CORRADE_DEPRECATED("use DistanceFieldVectorGL(const Configuration& instead") DistanceFieldVectorGL(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param materialCount Size of a @ref DistanceFieldVectorMaterialUniform - * buffer bound with @ref bindMaterialBuffer() - * @param drawCount Size of a @ref TransformationProjectionUniform2D - * / @ref TransformationProjectionUniform3D / - * @ref DistanceFieldVectorDrawUniform / - * @ref TextureTransformationUniform buffer bound with - * @ref bindTransformationProjectionBuffer(), @ref bindDrawBuffer() - * and @ref bindTextureTransformationBuffer() - * @m_since_latest - * - * If @p flags contains @ref Flag::UniformBuffers, @p materialCount and - * @p drawCount describe the uniform buffer sizes as these are required - * to have a statically defined size. The draw offset is then set via - * @ref setDrawOffset() and the per-draw materials are specified via - * @ref DistanceFieldVectorDrawUniform::materialId. - * - * If @p flags don't contain @ref Flag::UniformBuffers, - * @p materialCount and @p drawCount is ignored and the constructor - * behaves the same as @ref DistanceFieldVectorGL(Flags). - * @see @ref compile(Flags, UnsignedInt, UnsignedInt) + * @m_deprecated_since_latest Use @ref DistanceFieldVectorGL(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions? make a - whole Configuration class? */ - explicit DistanceFieldVectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use DistanceFieldVectorGL(const Configuration& instead") DistanceFieldVectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** @@ -637,6 +629,91 @@ template class MAGNUM_SHADERS_EXPORT DistanceFieldVector #endif }; +/** +@brief Configuration +@m_since_latest + +@see @ref DistanceFieldVectorGL(const Configuration&), + @ref compile(const Configuration&) +*/ +template class DistanceFieldVectorGL::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * No flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Material count */ + UnsignedInt materialCount() const { return _materialCount; } + + /** + * @brief Set material count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref DistanceFieldVectorMaterialUniform buffer bound with + * @ref bindMaterialBuffer(); as uniform buffers are required to have a + * statically defined size. The per-draw materials are then specified + * via @ref DistanceFieldVectorDrawUniform::materialId. Default value + * is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setDrawCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setMaterialCount(UnsignedInt materialCount) { + _materialCount = materialCount; + return *this; + } + + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref TransformationProjectionUniform2D / + * @ref TransformationProjectionUniform3D / + * @ref DistanceFieldVectorDrawUniform / + * @ref TextureTransformationUniform buffer bound with + * @ref bindTransformationProjectionBuffer(), @ref bindDrawBuffer() and + * @ref bindTextureTransformationBuffer(); as uniform buffers are + * required to have a statically defined size. The draw offset is then + * set via @ref setDrawOffset(). Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setMaterialCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount = 1; + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest diff --git a/src/Magnum/Shaders/FlatGL.cpp b/src/Magnum/Shaders/FlatGL.cpp index 21483822e..d97b98f24 100644 --- a/src/Magnum/Shaders/FlatGL.cpp +++ b/src/Magnum/Shaders/FlatGL.cpp @@ -69,16 +69,12 @@ namespace { #endif } -template typename FlatGL::CompileState FlatGL::compile(const Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -) { +template typename FlatGL::CompileState FlatGL::compile(const Configuration& configuration) { #ifndef CORRADE_NO_ASSERT { - const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || flags & Flag::Textured + const bool textureTransformationNotEnabledOrTextured = !(configuration.flags() & Flag::TextureTransformation) || configuration.flags() & Flag::Textured #ifndef MAGNUM_TARGET_GLES2 - || flags >= Flag::ObjectIdTexture + || configuration.flags() >= Flag::ObjectIdTexture #endif ; CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, @@ -87,25 +83,25 @@ template typename FlatGL::CompileState FlatG #endif #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(), "Shaders::FlatGL: material count can't be zero", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::FlatGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags & Flag::TextureArrays) || flags & Flag::Textured || flags >= Flag::ObjectIdTexture, + CORRADE_ASSERT(!(configuration.flags() & Flag::TextureArrays) || configuration.flags() & Flag::Textured || configuration.flags() >= Flag::ObjectIdTexture, "Shaders::FlatGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), + CORRADE_ASSERT(!(configuration.flags() & Flag::UniformBuffers) || !(configuration.flags() & Flag::TextureArrays) || configuration.flags() >= (Flag::TextureArrays|Flag::TextureTransformation), "Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); #endif #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::MultiDraw) { + if(configuration.flags() >= Flag::MultiDraw) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); #elif !defined(MAGNUM_TARGET_WEBGL) @@ -116,7 +112,7 @@ template typename FlatGL::CompileState FlatG } #endif #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::TextureArrays) + if(configuration.flags() >= Flag::TextureArrays) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array); #endif @@ -138,54 +134,54 @@ template typename FlatGL::CompileState FlatG GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); - vert.addSource((flags & Flag::Textured + vert.addSource((configuration.flags() & Flag::Textured #ifndef MAGNUM_TARGET_GLES2 - || flags >= Flag::ObjectIdTexture + || configuration.flags() >= Flag::ObjectIdTexture #endif ) ? "#define TEXTURED\n" : "") - .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") - .addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") + .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") + .addSource(configuration.flags() & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") #endif .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") #endif - .addSource(flags & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") - .addSource(flags >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : ""); + .addSource(configuration.flags() & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") + .addSource(configuration.flags() >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : ""); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { vert.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n", - drawCount)); - vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount())); + vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif vert.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Flat.vert")); - frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") + frag.addSource(configuration.flags() & Flag::Textured ? "#define TEXTURED\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") #endif - .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") - .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") + .addSource(configuration.flags() & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") + .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") - .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") - .addSource(flags >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") + .addSource(configuration.flags() & Flag::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(configuration.flags() >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") #endif ; #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { frag.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - drawCount, - materialCount)); - frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount(), + configuration.materialCount())); + frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif frag.addSource(rs.getString("generic.glsl")) @@ -195,10 +191,10 @@ template typename FlatGL::CompileState FlatG frag.submitCompile(); FlatGL out{NoInit}; - out._flags = flags; + out._flags = configuration.flags(); #ifndef MAGNUM_TARGET_GLES2 - out._materialCount = materialCount; - out._drawCount = drawCount; + out._materialCount = configuration.materialCount(); + out._drawCount = configuration.drawCount(); #endif out.attachShaders({vert, frag}); @@ -211,25 +207,25 @@ template typename FlatGL::CompileState FlatG #endif { out.bindAttributeLocation(Position::Location, "position"); - if(flags & Flag::Textured + if(configuration.flags() & Flag::Textured #ifndef MAGNUM_TARGET_GLES2 - || flags >= Flag::ObjectIdTexture + || configuration.flags() >= Flag::ObjectIdTexture #endif ) out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); - if(flags & Flag::VertexColor) + if(configuration.flags() & Flag::VertexColor) out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ #ifndef MAGNUM_TARGET_GLES2 - if(flags & Flag::ObjectId) { + if(configuration.flags() & Flag::ObjectId) { out.bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId"); } - if(flags >= Flag::InstancedObjectId) + if(configuration.flags() >= Flag::InstancedObjectId) out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif - if(flags & Flag::InstancedTransformation) + if(configuration.flags() & Flag::InstancedTransformation) out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); - if(flags >= Flag::InstancedTextureOffset) + if(configuration.flags() >= Flag::InstancedTextureOffset) out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); } #endif @@ -239,6 +235,26 @@ template typename FlatGL::CompileState FlatG return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } +template typename FlatGL::CompileState FlatGL::compile() { + return compile(Configuration{}); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +template typename FlatGL::CompileState FlatGL::compile(const Flags flags) { + return compile(Configuration{} + .setFlags(flags)); +} + +#ifndef MAGNUM_TARGET_GLES2 +template typename FlatGL::CompileState FlatGL::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount)); +} +#endif +#endif + template FlatGL::FlatGL(CompileState&& state): FlatGL{static_cast(std::move(state))} { #ifdef CORRADE_GRACEFUL_ASSERT /* When graceful assertions fire from within compile(), we get a NoCreate'd @@ -315,15 +331,20 @@ template FlatGL::FlatGL(CompileState&& state static_cast(context); } -template FlatGL::FlatGL(Flags flags): FlatGL{compile(flags)} {} +template FlatGL::FlatGL(const Configuration& configuration): FlatGL{compile(configuration)} {} -#ifndef MAGNUM_TARGET_GLES2 -template typename FlatGL::CompileState FlatGL::compile(Flags flags) { - return compile(flags, 1, 1); -} +template FlatGL::FlatGL(): FlatGL{Configuration{}} {} + +#ifdef MAGNUM_BUILD_DEPRECATED +template FlatGL::FlatGL(const Flags flags): FlatGL{compile(Configuration{} + .setFlags(flags))} {} -template FlatGL::FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): - FlatGL{compile(flags, materialCount, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +template FlatGL::FlatGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): FlatGL{compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount))} {} +#endif #endif template FlatGL::FlatGL(NoInitT) {} diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h index 8746f4393..0ecb483de 100644 --- a/src/Magnum/Shaders/FlatGL.h +++ b/src/Magnum/Shaders/FlatGL.h @@ -203,6 +203,7 @@ all shaders, see @ref shaders-usage-multidraw for an example. */ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram { public: + class Configuration; class CompileState; /** @@ -548,79 +549,71 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref FlatGL(Flags) can perform an asynchronous - * compilation and linking. See @ref shaders-async for more - * information. - * @see @ref FlatGL(CompileState&&), - * @ref compile(Flags, UnsignedInt, UnsignedInt) + * Compared to @ref FlatGL(const Configuration&) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref FlatGL(CompileState&&) */ - static CompileState compile(Flags flags = {}); + #ifdef DOXYGEN_GENERATING_OUTPUT + static CompileState compile(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + static CompileState compile(const Configuration& configuration); + static CompileState compile(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. + */ + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref FlatGL(Flags, UnsignedInt, UnsignedInt) can perform - * an asynchronous compilation and linking. See @ref shaders-async for - * more information. - * @see @ref FlatGL(CompileState&&), @ref compile(Flags) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref FlatGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount - * and @p drawCount set to @cpp 1 @ce. - * @see @ref compile(Flags) + * @m_since_latest + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit FlatGL(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + explicit FlatGL(const Configuration& configuration); + explicit FlatGL(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref FlatGL(const Configuration&) + * instead. */ - explicit FlatGL(Flags flags = {}); + explicit CORRADE_DEPRECATED("use FlatGL(const Configuration& instead") FlatGL(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param materialCount Size of a @ref FlatMaterialUniform buffer - * bound with @ref bindMaterialBuffer() - * @param drawCount Size of a @ref TransformationProjectionUniform2D - * / @ref TransformationProjectionUniform3D / @ref FlatDrawUniform - * / @ref TextureTransformationUniform buffer bound with - * @ref bindTransformationProjectionBuffer(), @ref bindDrawBuffer() - * and @ref bindTextureTransformationBuffer() - * @m_since_latest - * - * If @p flags contains @ref Flag::UniformBuffers, @p materialCount and - * @p drawCount describe the uniform buffer sizes as these are required - * to have a statically defined size. The draw offset is then set via - * @ref setDrawOffset() and the per-draw materials specified via - * @ref FlatDrawUniform::materialId. - * - * If @p flags don't contain @ref Flag::UniformBuffers, - * @p materialCount and @p drawCount is ignored and the constructor - * behaves the same as @ref FlatGL(Flags). - * @see @ref compile(Flags, UnsignedInt, UnsignedInt) + * @m_deprecated_since_latest Use @ref FlatGL(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions? make a - whole Configuration class? */ - explicit FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use FlatGL(const Configuration& instead") FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** @@ -1048,6 +1041,89 @@ template class MAGNUM_SHADERS_EXPORT FlatGL: public GL:: #endif }; +/** +@brief Configuration +@m_since_latest + +@see @ref FlatGL(const Configuration&), @ref compile(const Configuration&) +*/ +template class FlatGL::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * No flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Material count */ + UnsignedInt materialCount() const { return _materialCount; } + + /** + * @brief Set material count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref FlatMaterialUniform buffer bound with + * @ref bindMaterialBuffer(); as uniform buffers are required to have a + * statically defined size. The per-draw materials are then specified + * via @ref FlatDrawUniform::materialId. Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setDrawCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setMaterialCount(UnsignedInt materialCount) { + _materialCount = materialCount; + return *this; + } + + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref TransformationProjectionUniform2D / + * @ref TransformationProjectionUniform3D / + * @ref FlatDrawUniform / @ref TextureTransformationUniform buffer + * bound with @ref bindTransformationProjectionBuffer(), + * @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer(); as + * uniform buffers are required to have a statically defined size. The + * draw offset is then set via @ref setDrawOffset(). Default value is + * @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setMaterialCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount = 1; + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest diff --git a/src/Magnum/Shaders/MeshVisualizerGL.cpp b/src/Magnum/Shaders/MeshVisualizerGL.cpp index ddbbde5ad..2cd242ba7 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.cpp +++ b/src/Magnum/Shaders/MeshVisualizerGL.cpp @@ -376,19 +376,15 @@ MeshVisualizerGLBase& MeshVisualizerGLBase::bindObjectIdTexture(GL::Texture2DArr } -MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -) { - const FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)); +MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Configuration& configuration) { + const FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(configuration.flags())); assertExtensions(baseFlags); #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), + CORRADE_ASSERT(configuration.flags() & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), "Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", CompileState{NoCreate}); #else - CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), + CORRADE_ASSERT(configuration.flags() & (Flag::Wireframe & ~Flag::NoGeometryShader), "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate}); #endif @@ -396,9 +392,9 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags constructor when testing for asserts -- GLSL compilation would fail otherwise */ #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(), "Shaders::MeshVisualizerGL2D: material count can't be zero", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::MeshVisualizerGL2D: draw count can't be zero", CompileState{NoCreate}); #endif @@ -411,7 +407,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags GL::Shader frag{NoCreate}; const GL::Version version = setupShaders(vert, frag, rs, baseFlags #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount + , configuration.materialCount(), configuration.drawCount() #endif ); Containers::Optional geom; @@ -420,7 +416,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when nothing actually needs it, as that makes checks much simpler in the shader code */ - .addSource((flags & Flag::NoGeometryShader) || !(flags & Flag::Wireframe) ? + .addSource((configuration.flags() & Flag::NoGeometryShader) || !(configuration.flags() & Flag::Wireframe) ? "#define NO_GEOMETRY_SHADER\n" : "") .addSource(rs.getString("generic.glsl")) .addSource(rs.getString("MeshVisualizer.vert")); @@ -428,10 +424,10 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when nothing actually needs it, as that makes checks much simpler in the shader code */ - .addSource((flags & Flag::NoGeometryShader) || !(flags & Flag::Wireframe) ? + .addSource((configuration.flags() & Flag::NoGeometryShader) || !(configuration.flags() & Flag::Wireframe) ? "#define NO_GEOMETRY_SHADER\n" : ""); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) frag.addSource("#define TWO_DIMENSIONS\n"); #endif frag.addSource(rs.getString("generic.glsl")) @@ -439,7 +435,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(flags & Flag::Wireframe && !(flags & Flag::NoGeometryShader)) { + if(configuration.flags() & Flag::Wireframe && !(configuration.flags() & Flag::NoGeometryShader)) { geom = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry); (*geom) .addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n") @@ -453,15 +449,15 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID\n") : ""); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { geom->addSource(Utility::formatString( "#define TWO_DIMENSIONS\n" "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - drawCount, - materialCount)); - geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount(), + configuration.materialCount())); + geom->addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif geom->addSource(rs.getString("MeshVisualizer.geom")); @@ -477,8 +473,8 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags MeshVisualizerGL2D out{NoInit}; out._flags = baseFlags; #ifndef MAGNUM_TARGET_GLES2 - out._materialCount = materialCount; - out._drawCount = drawCount; + out._materialCount = configuration.materialCount(); + out._drawCount = configuration.drawCount(); #endif out.attachShaders({vert, frag}); @@ -492,15 +488,15 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags { out.bindAttributeLocation(Position::Location, "position"); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::ObjectIdTexture) + if(configuration.flags() >= Flag::ObjectIdTexture) out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); - if(flags >= Flag::InstancedObjectId) + if(configuration.flags() >= Flag::InstancedObjectId) out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif - if(flags & Flag::InstancedTransformation) + if(configuration.flags() & Flag::InstancedTransformation) out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::InstancedTextureOffset) + if(configuration.flags() >= Flag::InstancedTextureOffset) out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); #endif #if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) @@ -519,14 +515,20 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags return CompileState{std::move(out), std::move(vert), std::move(frag), geom ? &*geom : nullptr, version}; } -MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{compile(flags)} {} - -#ifndef MAGNUM_TARGET_GLES2 +#ifdef MAGNUM_BUILD_DEPRECATED MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags) { - return compile(flags, 1, 1); + return compile(Configuration{} + .setFlags(flags)); } -MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): MeshVisualizerGL2D{compile(flags, materialCount, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount)); +} +#endif #endif MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D{static_cast(std::move(state))} { @@ -643,6 +645,20 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D static_cast(version); } +MeshVisualizerGL2D::MeshVisualizerGL2D(const Configuration& configuration): MeshVisualizerGL2D{compile(configuration)} {} + +#ifdef MAGNUM_BUILD_DEPRECATED +MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{Configuration{} + .setFlags(flags)} {} + +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): MeshVisualizerGL2D{compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount))} {} +#endif +#endif + MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) { /* Not asserting here, since the relation to wireframe is a bit vague. Also it's an ugly hack that should be removed, ideally. */ @@ -703,31 +719,27 @@ MeshVisualizerGL2D& MeshVisualizerGL2D::bindDrawBuffer(GL::Buffer& buffer, const } #endif -MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags - #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -) { - FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags)); +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Configuration& configuration) { + FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(configuration.flags())); assertExtensions(baseFlags); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), + CORRADE_ASSERT(configuration.flags() & ((Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags & Flag::NoGeometryShader && flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)), + CORRADE_ASSERT(!(configuration.flags() & Flag::NoGeometryShader && configuration.flags() & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)), "Shaders::MeshVisualizerGL3D: geometry shader has to be enabled when rendering TBN direction", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags & Flag::BitangentDirection && flags & Flag::BitangentFromTangentDirection), + CORRADE_ASSERT(!(configuration.flags() & Flag::BitangentDirection && configuration.flags() & Flag::BitangentFromTangentDirection), "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", CompileState{NoCreate}); #elif !defined(MAGNUM_TARGET_GLES2) - CORRADE_ASSERT(flags & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), + CORRADE_ASSERT(configuration.flags() & ((Flag::Wireframe|Flag::ObjectId|Flag::VertexId|Flag::PrimitiveIdFromVertexId) & ~Flag::NoGeometryShader), "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate}); #else - CORRADE_ASSERT(flags & (Flag::Wireframe & ~Flag::NoGeometryShader), + CORRADE_ASSERT(configuration.flags() & (Flag::Wireframe & ~Flag::NoGeometryShader), "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate}); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::BitangentDirection), + CORRADE_ASSERT(!(configuration.flags() >= Flag::InstancedObjectId) || !(configuration.flags() & Flag::BitangentDirection), "Shaders::MeshVisualizerGL3D: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate}); #endif @@ -735,9 +747,9 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags constructor when testing for asserts -- GLSL compilation would fail otherwise */ #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(), "Shaders::MeshVisualizerGL3D: material count can't be zero", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::MeshVisualizerGL3D: draw count can't be zero", CompileState{NoCreate}); #endif @@ -750,32 +762,32 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags GL::Shader frag{NoCreate}; const GL::Version version = setupShaders(vert, frag, rs, baseFlags #ifndef MAGNUM_TARGET_GLES2 - , materialCount, drawCount + , configuration.materialCount(), configuration.drawCount() #endif ); Containers::Optional geom; /* Expands the check done for wireframe in MeshVisualizerBase with TBN */ #ifndef MAGNUM_TARGET_GLES - CORRADE_INTERNAL_ASSERT(!(flags & (Flag::NormalDirection|Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) || version >= GL::Version::GL320); + CORRADE_INTERNAL_ASSERT(!(configuration.flags() & (Flag::NormalDirection|Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) || version >= GL::Version::GL320); #elif !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - CORRADE_INTERNAL_ASSERT(!(flags & (Flag::NormalDirection|Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) || version >= GL::Version::GLES310); + CORRADE_INTERNAL_ASSERT(!(configuration.flags() & (Flag::NormalDirection|Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) || version >= GL::Version::GLES310); #endif vert.addSource("#define THREE_DIMENSIONS\n") /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when nothing actually needs it, as that makes checks much simpler in the vertex shader code */ - .addSource((flags & Flag::NoGeometryShader) || !(flags & (Flag::Wireframe + .addSource((configuration.flags() & Flag::NoGeometryShader) || !(configuration.flags() & (Flag::Wireframe #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) |Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection|Flag::NormalDirection #endif )) ? "#define NO_GEOMETRY_SHADER\n" : "") #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - .addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") - .addSource(flags & Flag::BitangentFromTangentDirection ? "#define BITANGENT_FROM_TANGENT_DIRECTION\n" : "") - .addSource(flags & Flag::BitangentDirection ? "#define BITANGENT_DIRECTION\n" : "") - .addSource(flags & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : "") + .addSource(configuration.flags() & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") + .addSource(configuration.flags() & Flag::BitangentFromTangentDirection ? "#define BITANGENT_FROM_TANGENT_DIRECTION\n" : "") + .addSource(configuration.flags() & Flag::BitangentDirection ? "#define BITANGENT_DIRECTION\n" : "") + .addSource(configuration.flags() & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : "") #endif ; vert.addSource(rs.getString("generic.glsl")) @@ -784,35 +796,35 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when nothing actually needs it, as that makes checks much simpler in the vertex shader code */ - .addSource((flags & Flag::NoGeometryShader) || !(flags & (Flag::Wireframe + .addSource((configuration.flags() & Flag::NoGeometryShader) || !(configuration.flags() & (Flag::Wireframe #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) |Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection|Flag::NormalDirection #endif )) ? "#define NO_GEOMETRY_SHADER\n" : "") #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - .addSource(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) ? "#define TBN_DIRECTION\n" : "") + .addSource(configuration.flags() & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) ? "#define TBN_DIRECTION\n" : "") #endif ; #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) frag.addSource("#define THREE_DIMENSIONS\n"); #endif frag.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("MeshVisualizer.frag")); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(flags & (Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) && !(flags & Flag::NoGeometryShader)) { + if(configuration.flags() & (Flag::Wireframe|Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection) && !(configuration.flags() & Flag::NoGeometryShader)) { Int maxVertices = 0; - if(flags & Flag::Wireframe) maxVertices += 3; - if(flags & Flag::TangentDirection) maxVertices += 3*6; - if(flags & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) + if(configuration.flags() & Flag::Wireframe) maxVertices += 3; + if(configuration.flags() & Flag::TangentDirection) maxVertices += 3*6; + if(configuration.flags() & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) maxVertices += 3*6; - if(flags & Flag::NormalDirection) maxVertices += 3*6; + if(configuration.flags() & Flag::NormalDirection) maxVertices += 3*6; geom = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry); (*geom) .addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices)) - .addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") + .addSource(configuration.flags() & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "") .addSource(baseFlags >= FlagBase::ObjectIdTexture ? "#define TEXTURED\n" : "") .addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") @@ -822,19 +834,19 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags (baseFlags >= FlagBase::PrimitiveIdFromVertexId ? "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID\n") : "") - .addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") - .addSource(flags & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection) ? "#define BITANGENT_DIRECTION\n" : "") - .addSource(flags & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : ""); + .addSource(configuration.flags() & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") + .addSource(configuration.flags() & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection) ? "#define BITANGENT_DIRECTION\n" : "") + .addSource(configuration.flags() & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : ""); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { geom->addSource(Utility::formatString( "#define THREE_DIMENSIONS\n" "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - drawCount, - materialCount)); - geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount(), + configuration.materialCount())); + geom->addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif geom->addSource(rs.getString("MeshVisualizer.geom")); @@ -850,8 +862,8 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags MeshVisualizerGL3D out{NoInit}; out._flags = baseFlags; #ifndef MAGNUM_TARGET_GLES2 - out._materialCount = materialCount; - out._drawCount = drawCount; + out._materialCount = configuration.materialCount(); + out._drawCount = configuration.drawCount(); #endif out.attachShaders({vert, frag}); @@ -865,30 +877,30 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags { out.bindAttributeLocation(Position::Location, "position"); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::ObjectIdTexture) + if(configuration.flags() >= Flag::ObjectIdTexture) out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); - if(flags >= Flag::InstancedObjectId) + if(configuration.flags() >= Flag::InstancedObjectId) out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif - if(flags & Flag::InstancedTransformation) { + if(configuration.flags() & Flag::InstancedTransformation) { out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(flags & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)) + if(configuration.flags() & (Flag::TangentDirection|Flag::BitangentFromTangentDirection|Flag::BitangentDirection|Flag::NormalDirection)) out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); #endif } #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::InstancedTextureOffset) + if(configuration.flags() >= Flag::InstancedTextureOffset) out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); #endif #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) - if(flags & Flag::TangentDirection || - flags & Flag::BitangentFromTangentDirection) + if(configuration.flags() & Flag::TangentDirection || + configuration.flags() & Flag::BitangentFromTangentDirection) out.bindAttributeLocation(Tangent4::Location, "tangent"); - if(flags & Flag::BitangentDirection) + if(configuration.flags() & Flag::BitangentDirection) out.bindAttributeLocation(Bitangent::Location, "bitangent"); - if(flags & Flag::NormalDirection || - flags & Flag::BitangentFromTangentDirection) + if(configuration.flags() & Flag::NormalDirection || + configuration.flags() & Flag::BitangentFromTangentDirection) out.bindAttributeLocation(Normal::Location, "normal"); #endif @@ -908,6 +920,22 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags return CompileState{std::move(out), std::move(vert), std::move(frag), geom ? &*geom : nullptr, version}; } +#ifdef MAGNUM_BUILD_DEPRECATED +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Flags flags) { + return compile(Configuration{} + .setFlags(flags)); +} + +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount)); +} +#endif +#endif + MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D{static_cast(std::move(state))} { #ifdef CORRADE_GRACEFUL_ASSERT /* When graceful assertions fire from within compile(), we get a NoCreate'd @@ -1055,14 +1083,20 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D static_cast(version); } -MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): MeshVisualizerGL3D{compile(flags)} {} +MeshVisualizerGL3D::MeshVisualizerGL3D(const Configuration& configuration): MeshVisualizerGL3D{compile(configuration)} {} -#ifndef MAGNUM_TARGET_GLES2 -MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Flags flags) { - return compile(flags, 1, 1); -} +#ifdef MAGNUM_BUILD_DEPRECATED +MeshVisualizerGL3D::MeshVisualizerGL3D(): MeshVisualizerGL3D{Configuration{}} {} + +MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): MeshVisualizerGL3D{Configuration{} + .setFlags(flags)} {} -MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): MeshVisualizerGL3D{compile(flags, materialCount, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): MeshVisualizerGL3D{compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount))} {} +#endif #endif MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h index ff253a6f3..d44faca1e 100644 --- a/src/Magnum/Shaders/MeshVisualizerGL.h +++ b/src/Magnum/Shaders/MeshVisualizerGL.h @@ -180,6 +180,7 @@ texture offset (or offset and layer). */ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisualizerGLBase { public: + class Configuration; class CompileState; /** @@ -443,82 +444,61 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref MeshVisualizerGL2D(Flags) can perform an - * asynchronous compilation and linking. See @ref shaders-async for - * more information. - * @see @ref MeshVisualizerGL2D(CompileState&&), - * @ref compile(Flags, UnsignedInt, UnsignedInt) + * Compared to @ref MeshVisualizerGL2D(const Configuration&) can + * perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref MeshVisualizerGL2D(CompileState&&) */ - /* No default value, consistently with MeshVisualizerGL2D(Flags) */ - static CompileState compile(Flags flags); + /* No default value, consistently with MeshVisualizerGL2D(Configuration) */ + static CompileState compile(const Configuration& configuration); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. + */ + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref MeshVisualizerGL2D(Flags, UnsignedInt, UnsignedInt) - * can perform an asynchronous compilation and linking. See - * @ref shaders-async for more information. - * @see @ref MeshVisualizerGL2D(CompileState&&), @ref compile(Flags) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * - * At least @ref Flag::Wireframe is expected to be enabled. - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref MeshVisualizerGL2D(Flags, UnsignedInt, UnsignedInt) with - * @p materialCount and @p drawCount set to @cpp 1 @ce. - * @see @ref compile(Flags) + * @m_since_latest */ - explicit MeshVisualizerGL2D(Flags flags); + /* No default value, as at least one Flag has to be set */ + explicit MeshVisualizerGL2D(const Configuration& configuration); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref MeshVisualizerGL2D(const Configuration&) + * instead. + */ + explicit CORRADE_DEPRECATED("use MeshVisualizerGL2D(const Configuration& instead") MeshVisualizerGL2D(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param materialCount Size of a @ref MeshVisualizerMaterialUniform - * buffer bound with @ref bindMaterialBuffer() - * @param drawCount Size of a @ref TransformationProjectionUniform2D - * / @ref MeshVisualizerMaterialUniform buffer bound with - * @ref bindTransformationProjectionBuffer() and - * @ref bindDrawBuffer() - * @m_since_latest - * - * At least @ref Flag::Wireframe is expected to be enabled. - * - * If @p flags contains @ref Flag::UniformBuffers, @p materialCount and - * @p drawCount describe the uniform buffer sizes as these are required - * to have a statically defined size. The draw offset is then set via - * @ref setDrawOffset() and the per-draw materials are specified via - * @ref MeshVisualizerDrawUniform2D::materialId. - * - * If @p flags don't contain @ref Flag::UniformBuffers, - * @p materialCount and @p drawCount is ignored and the constructor - * behaves the same as @ref MeshVisualizerGL2D(Flags). - * @see @ref compile(Flags, UnsignedInt, UnsignedInt) + * @m_deprecated_since_latest Use @ref MeshVisualizerGL2D(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions */ - explicit MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use MeshVisualizerGL2D(const Configuration& instead") MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** @@ -878,6 +858,93 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua Int _transformationProjectionMatrixUniform{9}; }; +/** +@brief Configuration +@m_since_latest + +@see @ref MeshVisualizerGL2D(const Configuration&), + @ref compile(const Configuration&) +*/ +class MeshVisualizerGL2D::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * At least one of @ref Flag::Wireframe, @ref Flag::ObjectId, + * @ref Flag::VertexId, @ref Flag::PrimitiveId or + * @ref Flag::PrimitiveIdFromVertexId is expected to be enabled. No + * flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Material count */ + UnsignedInt materialCount() const { return _materialCount; } + + /** + * @brief Set material count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref MeshVisualizerMaterialUniform buffer bound with + * @ref bindMaterialBuffer(); as uniform buffers are required to have a + * statically defined size. The per-draw materials are then specified + * via @ref MeshVisualizerDrawUniform2D::materialId. Default value is + * @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setDrawCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setMaterialCount(UnsignedInt materialCount) { + _materialCount = materialCount; + return *this; + } + + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref TransformationProjectionUniform2D / + * @ref MeshVisualizerDrawUniform2D / @ref TextureTransformationUniform + * buffer bound with @ref bindTransformationProjectionBuffer(), + * @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer(); as + * uniform buffers are required to have a statically defined size. The + * draw offset is then set via @ref setDrawOffset(). Default value is + * @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setMaterialCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount = 1; + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest @@ -1136,6 +1203,7 @@ similar for all shaders, see @ref shaders-usage-multidraw for an example. */ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisualizerGLBase { public: + class Configuration; class CompileState; /** @@ -1656,100 +1724,81 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref MeshVisualizerGL3D(Flags) can perform an - * asynchronous compilation and linking. See @ref shaders-async for - * more information. - * @see @ref MeshVisualizerGL3D(CompileState&&), - * @ref compile(Flags, UnsignedInt, UnsignedInt) + * Compared to @ref MeshVisualizerGL3D(const Configuration&) can + * perform an asynchronous compilation and linking. See + * @ref shaders-async for more information. + * @see @ref MeshVisualizerGL3D(CompileState&&) + */ + /* No default value, consistently with MeshVisualizerGL3D(Configuration) */ + static CompileState compile(const Configuration& configuration); + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. */ - /* No default value, consistently with MeshVisualizerGL3D(Flags) */ - static CompileState compile(Flags flags); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref MeshVisualizerGL3D(Flags, UnsignedInt, UnsignedInt) - * can perform an asynchronous compilation and linking. See - * @ref shaders-async for more information. - * @see @ref MeshVisualizerGL3D(CompileState&&), @ref compile(Flags) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * - * At least @ref Flag::Wireframe or one of @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection, @ref Flag::NormalDirection is - * expected to be enabled. - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref MeshVisualizerGL3D(Flags, UnsignedInt, UnsignedInt) with - * @p materialCount and @p drawCount set to @cpp 1 @ce. - * @see @ref compile(Flags) + * @m_since_latest */ - explicit MeshVisualizerGL3D(Flags flags); + /* No default value, as at least one Flag has to be set. There's a + deprecated default-value overload below, though. */ + explicit MeshVisualizerGL3D(const Configuration& configuration); #ifdef MAGNUM_BUILD_DEPRECATED /** * @brief Constructor - * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags) + * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(const Configuration&) * instead. */ - explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{Flags{}} {} - #endif + explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Configuration) instead") MeshVisualizerGL3D(); + + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref MeshVisualizerGL3D(const Configuration&) + * instead. + */ + explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(const Configuration& instead") MeshVisualizerGL3D(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param materialCount Size of a @ref MeshVisualizerMaterialUniform - * buffer bound with @ref bindMaterialBuffer() - * @param drawCount Size of a @ref ProjectionUniform3D / - * @ref TransformationUniform3D / - * @ref MeshVisualizerMaterialUniform buffer bound with - * @ref bindProjectionBuffer(), @ref bindTransformationBuffer() - * and @ref bindDrawBuffer() - * @m_since_latest - * - * At least @ref Flag::Wireframe or one of @ref Flag::TangentDirection, - * @ref Flag::BitangentFromTangentDirection, - * @ref Flag::BitangentDirection, @ref Flag::NormalDirection is - * expected to be enabled. - * - * If @p flags contains @ref Flag::UniformBuffers, @p materialCount and - * @p drawCount describe the uniform buffer sizes as these are required - * to have a statically defined size. The draw offset is then set via - * @ref setDrawOffset() and the per-draw materials are specified via - * @ref MeshVisualizerDrawUniform3D::materialId. - * - * If @p flags don't contain @ref Flag::UniformBuffers, - * @p materialCount and @p drawCount is ignored and the constructo - * @see @ref compile(Flags, UnsignedInt, UnsignedInt) + * @m_deprecated_since_latest Use @ref MeshVisualizerGL3D(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions? make a - whole Configuration class? */ - explicit MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(const Configuration& instead") MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif + /** + * @brief Finalize an asynchronous compilation + * @m_since_latest + * + * Takes an asynchronous compilation state returned by @ref compile() + * and forms a ready-to-use shader object. See @ref shaders-async for + * more information. + */ + explicit MeshVisualizerGL3D(CompileState&& state); + /** * @brief Construct without creating the underlying OpenGL object * @@ -1764,16 +1813,6 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua */ explicit MeshVisualizerGL3D(NoCreateT) noexcept: Implementation::MeshVisualizerGLBase{NoCreate} {} - /** - * @brief Finalize an asynchronous compilation - * @m_since_latest - * - * Takes an asynchronous compilation state returned by @ref compile() - * and forms a ready-to-use shader object. See @ref shaders-async for - * more information. - */ - explicit MeshVisualizerGL3D(CompileState&& state); - /** @brief Copying is not allowed */ MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete; @@ -2384,6 +2423,95 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua #endif }; +/** +@brief Configuration +@m_since_latest + +@see @ref MeshVisualizerGL3D(const Configuration&), + @ref compile(const Configuration&) +*/ +class MeshVisualizerGL3D::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * At least one of @ref Flag::Wireframe, @ref Flag::TangentDirection, + * @ref Flag::BitangentFromTangentDirection, + * @ref Flag::BitangentDirection, @ref Flag::NormalDirection, + * @ref Flag::ObjectId, @ref Flag::VertexId, @ref Flag::PrimitiveId or + * @ref Flag::PrimitiveIdFromVertexId is expected to be enabled. No + * flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Material count */ + UnsignedInt materialCount() const { return _materialCount; } + + /** + * @brief Set material count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref MeshVisualizerMaterialUniform buffer bound with + * @ref bindMaterialBuffer(); as uniform buffers are required to have a + * statically defined size. The per-draw materials are then specified + * via @ref MeshVisualizerDrawUniform3D::materialId. Default value is + * @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setDrawCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setMaterialCount(UnsignedInt materialCount) { + _materialCount = materialCount; + return *this; + } + + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref ProjectionUniform3D / @ref TransformationUniform3D + * @ref MeshVisualizerDrawUniform3D / @ref TextureTransformationUniform + * buffer bound with @ref bindProjectionBuffer(), + * @ref bindTransformationBuffer(), @ref bindDrawBuffer() and + * @ref bindTextureTransformationBuffer(); as uniform buffers are + * required to have a statically defined size. The draw offset is then + * set via @ref setDrawOffset(). Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setMaterialCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount = 1; + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest diff --git a/src/Magnum/Shaders/PhongGL.cpp b/src/Magnum/Shaders/PhongGL.cpp index 2777338a2..fd0e24335 100644 --- a/src/Magnum/Shaders/PhongGL.cpp +++ b/src/Magnum/Shaders/PhongGL.cpp @@ -75,16 +75,12 @@ namespace { #endif } -PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount - #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -) { +PhongGL::CompileState PhongGL::compile(const Configuration& configuration) { #ifndef CORRADE_NO_ASSERT { - const bool textureTransformationNotEnabledOrTextured = !(flags & Flag::TextureTransformation) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) + const bool textureTransformationNotEnabledOrTextured = !(configuration.flags() & Flag::TextureTransformation) || (configuration.flags() & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) #ifndef MAGNUM_TARGET_GLES2 - || flags >= Flag::ObjectIdTexture + || configuration.flags() >= Flag::ObjectIdTexture #endif ; CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, @@ -93,35 +89,35 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh #endif #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::InstancedObjectId) || !(flags & Flag::Bitangent), + CORRADE_ASSERT(!(configuration.flags() >= Flag::InstancedObjectId) || !(configuration.flags() & Flag::Bitangent), "Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(), "Shaders::PhongGL: material count can't be zero", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::PhongGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags & Flag::TextureArrays) || (flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || flags >= Flag::ObjectIdTexture, + CORRADE_ASSERT(!(configuration.flags() & Flag::TextureArrays) || (configuration.flags() & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture)) || configuration.flags() >= Flag::ObjectIdTexture, "Shaders::PhongGL: texture arrays enabled but the shader is not textured", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags & Flag::UniformBuffers) || !(flags & Flag::TextureArrays) || flags >= (Flag::TextureArrays|Flag::TextureTransformation), + CORRADE_ASSERT(!(configuration.flags() & Flag::UniformBuffers) || !(configuration.flags() & Flag::TextureArrays) || configuration.flags() >= (Flag::TextureArrays|Flag::TextureTransformation), "Shaders::PhongGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags & Flag::LightCulling) || (flags & Flag::UniformBuffers), + CORRADE_ASSERT(!(configuration.flags() & Flag::LightCulling) || (configuration.flags() & Flag::UniformBuffers), "Shaders::PhongGL: light culling requires uniform buffers to be enabled", CompileState{NoCreate}); #endif - CORRADE_ASSERT(!(flags & Flag::SpecularTexture) || !(flags & (Flag::NoSpecular)), + CORRADE_ASSERT(!(configuration.flags() & Flag::SpecularTexture) || !(configuration.flags() & (Flag::NoSpecular)), "Shaders::PhongGL: specular texture requires the shader to not have specular disabled", CompileState{NoCreate}); #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); #endif #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::MultiDraw) { + if(configuration.flags() >= Flag::MultiDraw) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); #elif !defined(MAGNUM_TARGET_WEBGL) @@ -132,7 +128,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh } #endif #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::TextureArrays) + if(configuration.flags() >= Flag::TextureArrays) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array); #endif @@ -146,7 +142,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh const GL::Context& context = GL::Context::current(); #ifndef MAGNUM_TARGET_GLES - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported(), + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || context.isExtensionSupported(), "Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), CompileState{NoCreate}); #endif @@ -157,14 +153,14 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh #endif PhongGL out{NoInit}; - out._flags = flags; - out._lightCount = lightCount; - out._lightColorsUniform = out._lightPositionsUniform + Int(lightCount); - out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(lightCount); - out._lightRangesUniform = out._lightPositionsUniform + 3*Int(lightCount); + out._flags = configuration.flags(); + out._lightCount = configuration.lightCount(); + out._lightColorsUniform = out._lightPositionsUniform + Int(configuration.lightCount()); + out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(configuration.lightCount()); + out._lightRangesUniform = out._lightPositionsUniform + 3*Int(configuration.lightCount()); #ifndef MAGNUM_TARGET_GLES2 - out._materialCount = materialCount; - out._drawCount = drawCount; + out._materialCount = configuration.materialCount(); + out._drawCount = configuration.drawCount(); #endif GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); @@ -172,7 +168,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh #ifndef MAGNUM_TARGET_GLES std::string lightInitializer; - if(!(flags >= Flag::UniformBuffers) && lightCount) { + if(!(configuration.flags() >= Flag::UniformBuffers) && configuration.lightCount()) { using namespace Containers::Literals; /* Initializer for the light color / position / range arrays -- we need @@ -189,12 +185,12 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh lightPositionInitializerPreamble.size() + lightColorInitializerPreamble.size() + lightRangeInitializerPreamble.size() + - lightCount*(lightPositionInitializerItem.size() + - lightColorInitializerItem.size() + - lightRangeInitializerItem.size())); + configuration.lightCount()*(lightPositionInitializerItem.size() + + lightColorInitializerItem.size() + + lightRangeInitializerItem.size())); lightInitializer.append(lightPositionInitializerPreamble); - for(std::size_t i = 0; i != lightCount; ++i) + for(std::size_t i = 0; i != configuration.lightCount(); ++i) lightInitializer.append(lightPositionInitializerItem); /* Drop the last comma and add a newline at the end */ @@ -202,7 +198,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh lightInitializer.resize(lightInitializer.size() - 1); lightInitializer.append(lightColorInitializerPreamble); - for(std::size_t i = 0; i != lightCount; ++i) + for(std::size_t i = 0; i != configuration.lightCount(); ++i) lightInitializer.append(lightColorInitializerItem); /* Drop the last comma and add a newline at the end */ @@ -210,7 +206,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh lightInitializer.resize(lightInitializer.size() - 1); lightInitializer.append(lightRangeInitializerPreamble); - for(std::size_t i = 0; i != lightCount; ++i) + for(std::size_t i = 0; i != configuration.lightCount(); ++i) lightInitializer.append(lightRangeInitializerItem); /* Drop the last comma and add a newline at the end */ @@ -219,65 +215,65 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh } #endif - vert.addSource((flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture) + vert.addSource((configuration.flags() & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture|Flag::NormalTexture) #ifndef MAGNUM_TARGET_GLES2 - || flags >= Flag::ObjectIdTexture + || configuration.flags() >= Flag::ObjectIdTexture #endif ) ? "#define TEXTURED\n" : "") - .addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") - .addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "") - .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") - .addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") + .addSource(configuration.flags() & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") + .addSource(configuration.flags() & Flag::Bitangent ? "#define BITANGENT\n" : "") + .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") + .addSource(configuration.flags() & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") #endif - .addSource(lightCount ? "#define HAS_LIGHTS\n" : "") + .addSource(configuration.lightCount() ? "#define HAS_LIGHTS\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") #endif - .addSource(flags & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") - .addSource(flags >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : ""); + .addSource(configuration.flags() & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") + .addSource(configuration.flags() >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : ""); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { vert.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n", - drawCount, - lightCount)); - vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount(), + configuration.lightCount())); + vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif vert.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Phong.vert")); - frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") - .addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") - .addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") - .addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") + frag.addSource(configuration.flags() & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") + .addSource(configuration.flags() & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") + .addSource(configuration.flags() & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") + .addSource(configuration.flags() & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") + .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") #endif - .addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "") - .addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") - .addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") + .addSource(configuration.flags() & Flag::Bitangent ? "#define BITANGENT\n" : "") + .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") + .addSource(configuration.flags() & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") #ifndef MAGNUM_TARGET_GLES2 - .addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") - .addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") - .addSource(flags >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") + .addSource(configuration.flags() & Flag::ObjectId ? "#define OBJECT_ID\n" : "") + .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") + .addSource(configuration.flags() >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") #endif - .addSource(flags & Flag::NoSpecular ? "#define NO_SPECULAR\n" : "") + .addSource(configuration.flags() & Flag::NoSpecular ? "#define NO_SPECULAR\n" : "") ; #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { frag.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n" "#define LIGHT_COUNT {}\n", - drawCount, - materialCount, - lightCount)); - frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "") - .addSource(flags >= Flag::LightCulling ? "#define LIGHT_CULLING\n" : ""); + configuration.drawCount(), + configuration.materialCount(), + configuration.lightCount())); + frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "") + .addSource(configuration.flags() >= Flag::LightCulling ? "#define LIGHT_CULLING\n" : ""); } else #endif { @@ -286,13 +282,13 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh "#define LIGHT_COLORS_LOCATION {}\n" "#define LIGHT_SPECULAR_COLORS_LOCATION {}\n" "#define LIGHT_RANGES_LOCATION {}\n", - lightCount, - out._lightPositionsUniform + lightCount, - out._lightPositionsUniform + 2*lightCount, - out._lightPositionsUniform + 3*lightCount)); + configuration.lightCount(), + out._lightPositionsUniform + configuration.lightCount(), + out._lightPositionsUniform + 2*configuration.lightCount(), + out._lightPositionsUniform + 3*configuration.lightCount())); } #ifndef MAGNUM_TARGET_GLES - if(!(flags >= Flag::UniformBuffers) && lightCount) + if(!(configuration.flags() >= Flag::UniformBuffers) && configuration.lightCount()) frag.addSource(std::move(lightInitializer)); #endif frag.addSource(rs.getString("generic.glsl")) @@ -311,35 +307,35 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh #endif { out.bindAttributeLocation(Position::Location, "position"); - if(lightCount) + if(configuration.lightCount()) out.bindAttributeLocation(Normal::Location, "normal"); - if((flags & Flag::NormalTexture) && lightCount) { + if((configuration.flags() & Flag::NormalTexture) && configuration.lightCount()) { out.bindAttributeLocation(Tangent::Location, "tangent"); - if(flags & Flag::Bitangent) + if(configuration.flags() & Flag::Bitangent) out.bindAttributeLocation(Bitangent::Location, "bitangent"); } - if(flags & Flag::VertexColor) + if(configuration.flags() & Flag::VertexColor) out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ - if(flags & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture) + if(configuration.flags() & (Flag::AmbientTexture|Flag::DiffuseTexture|Flag::SpecularTexture) #ifndef MAGNUM_TARGET_GLES2 - || flags >= Flag::ObjectIdTexture + || configuration.flags() >= Flag::ObjectIdTexture #endif ) out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); #ifndef MAGNUM_TARGET_GLES2 - if(flags & Flag::ObjectId) { + if(configuration.flags() & Flag::ObjectId) { out.bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId"); } - if(flags >= Flag::InstancedObjectId) + if(configuration.flags() >= Flag::InstancedObjectId) out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); #endif - if(flags & Flag::InstancedTransformation) { + if(configuration.flags() & Flag::InstancedTransformation) { out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); - if(lightCount) + if(configuration.lightCount()) out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); } - if(flags >= Flag::InstancedTextureOffset) + if(configuration.flags() >= Flag::InstancedTextureOffset) out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); } #endif @@ -349,6 +345,28 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } +PhongGL::CompileState PhongGL::compile() { + return compile(Configuration{}); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount) { + return compile(Configuration{} + .setFlags(flags) + .setLightCount(lightCount)); +} + +#ifndef MAGNUM_TARGET_GLES2 +PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount, const UnsignedInt materialCount, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setLightCount(lightCount) + .setMaterialCount(materialCount) + .setDrawCount(drawCount)); +} +#endif +#endif + PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast(std::move(state))} { #ifdef CORRADE_GRACEFUL_ASSERT /* When graceful assertions fire from within compile(), we get a NoCreate'd @@ -469,14 +487,22 @@ PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast(std::move static_cast(version); } -PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): PhongGL{compile(flags, lightCount)} {} +PhongGL::PhongGL(const Configuration& configuration): PhongGL{compile(configuration)} {} -#ifndef MAGNUM_TARGET_GLES2 -PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount) { - return compile(flags, lightCount, 1, 1); -} +PhongGL::PhongGL(): PhongGL{Configuration{}} {} + +#ifdef MAGNUM_BUILD_DEPRECATED +PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount): PhongGL{Configuration{} + .setFlags(flags) + .setLightCount(lightCount)} {} -PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount, const UnsignedInt materialCount, const UnsignedInt drawCount): PhongGL{compile(flags, lightCount, materialCount, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +PhongGL::PhongGL(const Flags flags, const UnsignedInt lightCount, const UnsignedInt materialCount, const UnsignedInt drawCount): PhongGL{compile(Configuration{} + .setFlags(flags) + .setLightCount(lightCount) + .setMaterialCount(materialCount) + .setDrawCount(drawCount))} {} +#endif #endif PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { diff --git a/src/Magnum/Shaders/PhongGL.h b/src/Magnum/Shaders/PhongGL.h index 3ad3f0ce1..015ec06d9 100644 --- a/src/Magnum/Shaders/PhongGL.h +++ b/src/Magnum/Shaders/PhongGL.h @@ -298,6 +298,7 @@ Besides that, the usage is similar for all shaders, see */ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { public: + class Configuration; class CompileState; /** @@ -761,85 +762,71 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref PhongGL(Flags, UnsignedInt) can perform an + * Compared to @ref PhongGL(const Configuration&) can perform an * asynchronous compilation and linking. See @ref shaders-async for * more information. - * @see @ref PhongGL(CompileState&&), - * @ref compile(Flags, UnsignedInt, UnsignedInt, UnsignedInt) + * @see @ref PhongGL(CompileState&&) + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + static CompileState compile(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + static CompileState compile(const Configuration& configuration); + static CompileState compile(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. */ - static CompileState compile(Flags flags = {}, UnsignedInt lightCount = 1); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt lightCount = 1); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref PhongGL(Flags, UnsignedInt, UnsignedInt, UnsignedInt) - * can perform an asynchronous compilation and linking. See - * @ref shaders-async for more information. - * @see @ref PhongGL(CompileState&&), @ref compile(Flags, UnsignedInt) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * @param lightCount Count of light sources - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref PhongGL(Flags, UnsignedInt, UnsignedInt, UnsignedInt) with - * @p materialCount and @p drawCount set to @cpp 1 @ce. - * @see @ref compile(Flags, UnsignedInt) + * @m_since_latest */ - explicit PhongGL(Flags flags = {}, UnsignedInt lightCount = 1); + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit PhongGL(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + explicit PhongGL(const Configuration& configuration); + explicit PhongGL(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref PhongGL(const Configuration&) + * instead. + */ + explicit CORRADE_DEPRECATED("use PhongGL(const Configuration& instead") PhongGL(Flags flags, UnsignedInt lightCount = 1); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param lightCount Size of a @ref PhongLightUniform buffer bound - * with @ref bindLightBuffer() - * @param materialCount Size of a @ref PhongMaterialUniform buffer - * bound with @ref bindMaterialBuffer() - * @param drawCount Size of a @ref ProjectionUniform3D / - * @ref TransformationUniform3D / @ref PhongDrawUniform / - * @ref TextureTransformationUniform buffer bound with - * @ref bindProjectionBuffer(), @ref bindTransformationBuffer(), - * @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer() - * @m_since_latest - * - * If @p flags contains @ref Flag::UniformBuffers, @p lightCount, - * @p materialCount and @p drawCount describe the uniform buffer sizes - * as these are required to have a statically defined size. The draw - * offset is then set via @ref setDrawOffset() and the per-draw - * materials and lights are specified via - * @ref PhongDrawUniform::materialId, - * @ref PhongDrawUniform::lightOffset and - * @ref PhongDrawUniform::lightCount. - * - * If @p flags don't contain @ref Flag::UniformBuffers, - * @p materialCount and @p drawCount is ignored and the constructor - * behaves the same as @ref PhongGL(Flags, UnsignedInt). - * @see @ref compile(Flags, UnsignedInt, UnsignedInt, UnsignedInt) + * @m_deprecated_since_latest Use @ref PhongGL(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions? make a - whole Configuration class? */ - explicit PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use PhongGL(const Configuration& instead") PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** @@ -1794,6 +1781,118 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram { #endif }; +/** +@brief Configuration +@m_since_latest + +@see @ref PhongGL(const Configuration&), @ref compile(const Configuration&) +*/ +class PhongGL::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * No flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + /** @brief Light count */ + UnsignedInt lightCount() const { return _lightCount; } + + /** + * @brief Set light count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref PhongLightUniform buffer bound with @ref bindLightBuffer(); as + * uniform buffers are required to have a statically defined size. The + * per-draw lights are then specified via + * @ref PhongDrawUniform::lightOffset and + * @ref PhongDrawUniform::lightCount. + * + * If @ref Flag::UniformBuffers isn't set, describes how many lights + * get applied to each draw, and corresponds to the range / array size + * accepted by @ref setLightPosition() / @ref setLightPositions(), + * @ref setLightColor() / @ref setLightColors(), + * @ref setLightSpecularColor() / @ref setLightSpecularColors() and + * @ref setLightRange() / @ref setLightRanges(). + * + * Can be set to @cpp 0 @ce, in which case only the ambient + * contribution to the color is used. Default value is @cpp 1 @ce. + * @see @ref setFlags(), @ref setMaterialCount(), @ref setDrawCount() + */ + Configuration& setLightCount(UnsignedInt count) { + _lightCount = count; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Material count */ + UnsignedInt materialCount() const { return _materialCount; } + + /** + * @brief Set material count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref PhongMaterialUniform buffer bound with + * @ref bindMaterialBuffer(); as uniform buffers are required to have a + * statically defined size. The per-draw materials are then specified + * via @ref PhongDrawUniform::materialId. Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setLightCount(), @ref setDrawCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setMaterialCount(UnsignedInt materialCount) { + _materialCount = materialCount; + return *this; + } + + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref ProjectionUniform3D / @ref TransformationUniform3D / + * @ref PhongDrawUniform / @ref TextureTransformationUniform buffer + * bound with @ref bindProjectionBuffer(), + * @ref bindTransformationBuffer(), @ref bindDrawBuffer() and + * @ref bindTextureTransformationBuffer(); as uniform buffers are + * required to have a statically defined size. The draw offset is then + * set via @ref setDrawOffset(). Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setLightCount(), @ref setMaterialCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + UnsignedInt _lightCount = 1; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount = 1; + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest diff --git a/src/Magnum/Shaders/VectorGL.cpp b/src/Magnum/Shaders/VectorGL.cpp index c85da1339..4334c5685 100644 --- a/src/Magnum/Shaders/VectorGL.cpp +++ b/src/Magnum/Shaders/VectorGL.cpp @@ -64,24 +64,20 @@ namespace { #endif } -template typename VectorGL::CompileState VectorGL::compile(const Flags flags +template typename VectorGL::CompileState VectorGL::compile(const Configuration& configuration) { #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt materialCount, const UnsignedInt drawCount - #endif -) { - #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(), "Shaders::VectorGL: material count can't be zero", CompileState{NoCreate}); - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::VectorGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); #endif #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::MultiDraw) { + if(configuration.flags() >= Flag::MultiDraw) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); #elif !defined(MAGNUM_TARGET_WEBGL) @@ -110,28 +106,28 @@ template typename VectorGL::CompileState Vec GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); - vert.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") + vert.addSource(configuration.flags() & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n"); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { vert.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n", - drawCount)); - vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount())); + vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif vert.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("Vector.vert")); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { frag.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n" "#define MATERIAL_COUNT {}\n", - drawCount, - materialCount)); - frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount(), + configuration.materialCount())); + frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif frag.addSource(rs.getString("generic.glsl")) @@ -141,10 +137,10 @@ template typename VectorGL::CompileState Vec frag.submitCompile(); VectorGL out{NoInit}; - out._flags = flags; + out._flags = configuration.flags(); #ifndef MAGNUM_TARGET_GLES2 - out._materialCount = materialCount; - out._drawCount = drawCount; + out._materialCount = configuration.materialCount(); + out._drawCount = configuration.drawCount(); #endif out.attachShaders({vert, frag}); @@ -165,6 +161,26 @@ template typename VectorGL::CompileState Vec return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } +template typename VectorGL::CompileState VectorGL::compile() { + return compile(Configuration{}); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +template typename VectorGL::CompileState VectorGL::compile(const Flags flags) { + return compile(Configuration{} + .setFlags(flags)); +} + +#ifndef MAGNUM_TARGET_GLES2 +template typename VectorGL::CompileState VectorGL::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount)); +} +#endif +#endif + template VectorGL::VectorGL(CompileState&& state): VectorGL{static_cast(std::move(state))} { #ifdef CORRADE_GRACEFUL_ASSERT /* When graceful assertions fire from within compile(), we get a NoCreate'd @@ -231,14 +247,20 @@ template VectorGL::VectorGL(CompileState&& s static_cast(version); } -template VectorGL::VectorGL(const Flags flags): VectorGL{compile(flags)} {} +template VectorGL::VectorGL(const Configuration& configuration): VectorGL{compile(configuration)} {} -#ifndef MAGNUM_TARGET_GLES2 -template typename VectorGL::CompileState VectorGL::compile(const Flags flags) { - return compile(flags, 1, 1); -} +template VectorGL::VectorGL(): VectorGL{Configuration{}} {} + +#ifdef MAGNUM_BUILD_DEPRECATED +template VectorGL::VectorGL(const Flags flags): VectorGL{compile(Configuration{} + .setFlags(flags))} {} -template VectorGL::VectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): VectorGL{compile(flags, materialCount, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +template VectorGL::VectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): VectorGL{compile(Configuration{} + .setFlags(flags) + .setMaterialCount(materialCount) + .setDrawCount(drawCount))} {} +#endif #endif template VectorGL::VectorGL(NoInitT) {} diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h index 1a64d2f92..e8ffdef5e 100644 --- a/src/Magnum/Shaders/VectorGL.h +++ b/src/Magnum/Shaders/VectorGL.h @@ -117,6 +117,7 @@ example. */ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL::AbstractShaderProgram { public: + class Configuration; class CompileState; /** @@ -220,78 +221,71 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref VectorGL(Flags) can perform an asynchronous - * compilation and linking. See @ref shaders-async for more - * information. - * @see @ref VectorGL(CompileState&&), - * @ref compile(Flags, UnsignedInt, UnsignedInt) + * Compared to @ref VectorGL(const Configuration&) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref VectorGL(CompileState&&) */ - static CompileState compile(Flags flags = {}); + #ifdef DOXYGEN_GENERATING_OUTPUT + static CompileState compile(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + static CompileState compile(const Configuration& configuration); + static CompileState compile(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. + */ + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref VectorGL(Flags, UnsignedInt, UnsignedInt) can - * perform an asynchronous compilation and linking. See - * @ref shaders-async for more information. - * @see @ref VectorGL(CompileState&&), @ref compile(Flags) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref VectorGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount - * and @p drawCount set to @cpp 1 @ce. - * @see @ref compile(Flags) + * @m_since_latest */ - explicit VectorGL(Flags flags = {}); + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit VectorGL(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + explicit VectorGL(const Configuration& configuration); + explicit VectorGL(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref VectorGL(const Configuration&) + * instead. + */ + explicit CORRADE_DEPRECATED("use VectorGL(const Configuration& instead") VectorGL(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param materialCount Size of a @ref VectorMaterialUniform buffer - * bound with @ref bindMaterialBuffer() - * @param drawCount Size of a @ref TransformationProjectionUniform2D - * / @ref TransformationProjectionUniform3D / - * @ref VectorDrawUniform / @ref TextureTransformationUniform - * buffer bound with @ref bindTransformationProjectionBuffer(), - * @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer() - * @m_since_latest - * - * If @p flags contains @ref Flag::UniformBuffers, @p materialCount and - * @p drawCount describe the uniform buffer sizes as these are required - * to have a statically defined size. The draw offset is then set via - * @ref setDrawOffset() and the per-draw materials specified via - * @ref VectorDrawUniform::materialId. - * - * If @p flags don't contain @ref Flag::UniformBuffers, @p drawCount is - * ignored and the constructor behaves the same as @ref VectorGL(Flags). - * @see @ref compile(Flags, UnsignedInt, UnsignedInt) + * @m_deprecated_since_latest Use @ref VectorGL(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions? make a - whole Configuration class? */ - explicit VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use VectorGL(const Configuration& instead") VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount); + #endif #endif /** @@ -587,6 +581,90 @@ template class MAGNUM_SHADERS_EXPORT VectorGL: public GL #endif }; +/** +@brief Configuration +@m_since_latest + +@see @ref VectorGL(const Configuration&), + @ref compile(const Configuration&) +*/ +template class VectorGL::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * No flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Material count */ + UnsignedInt materialCount() const { return _materialCount; } + + /** + * @brief Set material count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref VectorMaterialUniform buffer bound with + * @ref bindMaterialBuffer(); as uniform buffers are required to have a + * statically defined size. The per-draw materials are then specified + * via @ref VectorDrawUniform::materialId. Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setDrawCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setMaterialCount(UnsignedInt materialCount) { + _materialCount = materialCount; + return *this; + } + + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref TransformationProjectionUniform2D / + * @ref TransformationProjectionUniform3D / + * @ref VectorDrawUniform / @ref TextureTransformationUniform buffer + * bound with @ref bindTransformationProjectionBuffer(), + * @ref bindDrawBuffer() and @ref bindTextureTransformationBuffer(); as + * uniform buffers are required to have a statically defined size. The + * draw offset is then set via @ref setDrawOffset(). Default value is + * @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags(), @ref setMaterialCount() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _materialCount = 1; + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest diff --git a/src/Magnum/Shaders/VertexColorGL.cpp b/src/Magnum/Shaders/VertexColorGL.cpp index c6cba2800..abe7280e9 100644 --- a/src/Magnum/Shaders/VertexColorGL.cpp +++ b/src/Magnum/Shaders/VertexColorGL.cpp @@ -57,22 +57,18 @@ namespace { #endif } -template typename VertexColorGL::CompileState VertexColorGL::compile(const Flags flags +template typename VertexColorGL::CompileState VertexColorGL::compile(const Configuration& configuration) { #ifndef MAGNUM_TARGET_GLES2 - , const UnsignedInt drawCount - #endif -) { - #ifndef MAGNUM_TARGET_GLES2 - CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount, + CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(), "Shaders::VertexColorGL: draw count can't be zero", CompileState{NoCreate}); #endif #ifndef MAGNUM_TARGET_GLES - if(flags >= Flag::UniformBuffers) + if(configuration.flags() >= Flag::UniformBuffers) MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); #endif #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::MultiDraw) { + if(configuration.flags() >= Flag::MultiDraw) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); #elif !defined(MAGNUM_TARGET_WEBGL) @@ -103,12 +99,12 @@ template typename VertexColorGL::CompileStat vert.addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n"); #ifndef MAGNUM_TARGET_GLES2 - if(flags >= Flag::UniformBuffers) { + if(configuration.flags() >= Flag::UniformBuffers) { vert.addSource(Utility::formatString( "#define UNIFORM_BUFFERS\n" "#define DRAW_COUNT {}\n", - drawCount)); - vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); + configuration.drawCount())); + vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); } #endif vert.addSource(rs.getString("generic.glsl")) @@ -120,9 +116,9 @@ template typename VertexColorGL::CompileStat frag.submitCompile(); VertexColorGL out{NoInit}; - out._flags = flags; + out._flags = configuration.flags(); #ifndef MAGNUM_TARGET_GLES2 - out._drawCount = drawCount; + out._drawCount = configuration.drawCount(); #endif out.attachShaders({vert, frag}); @@ -143,6 +139,25 @@ template typename VertexColorGL::CompileStat return CompileState{std::move(out), std::move(vert), std::move(frag), version}; } +template typename VertexColorGL::CompileState VertexColorGL::compile() { + return compile(Configuration{}); +} + +#ifdef MAGNUM_BUILD_DEPRECATED +template typename VertexColorGL::CompileState VertexColorGL::compile(const Flags flags) { + return compile(Configuration{} + .setFlags(flags)); +} + +#ifndef MAGNUM_TARGET_GLES2 +template typename VertexColorGL::CompileState VertexColorGL::compile(const Flags flags, const UnsignedInt drawCount) { + return compile(Configuration{} + .setFlags(flags) + .setDrawCount(drawCount)); +} +#endif +#endif + template VertexColorGL::VertexColorGL(CompileState&& state): VertexColorGL{static_cast(std::move(state))} { #ifdef CORRADE_GRACEFUL_ASSERT /* When graceful assertions fire from within compile(), we get a NoCreate'd @@ -195,14 +210,19 @@ template VertexColorGL::VertexColorGL(Compil static_cast(version); } -template VertexColorGL::VertexColorGL(const Flags flags): VertexColorGL{compile(flags)} {} +template VertexColorGL::VertexColorGL(const Configuration& configuration): VertexColorGL{compile(configuration)} {} -#ifndef MAGNUM_TARGET_GLES2 -template typename VertexColorGL::CompileState VertexColorGL::compile(const Flags flags) { - return compile(flags, 1); -} +template VertexColorGL::VertexColorGL(): VertexColorGL{Configuration{}} {} + +#ifdef MAGNUM_BUILD_DEPRECATED +template VertexColorGL::VertexColorGL(const Flags flags): VertexColorGL{compile(Configuration{} + .setFlags(flags))} {} -template VertexColorGL::VertexColorGL(const Flags flags, const UnsignedInt drawCount): VertexColorGL{compile(flags, drawCount)} {} +#ifndef MAGNUM_TARGET_GLES2 +template VertexColorGL::VertexColorGL(const Flags flags, const UnsignedInt drawCount): VertexColorGL{compile(Configuration{} + .setFlags(flags) + .setDrawCount(drawCount))} {} +#endif #endif template VertexColorGL::VertexColorGL(NoInitT) {} diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h index e97108502..5dccbe45e 100644 --- a/src/Magnum/Shaders/VertexColorGL.h +++ b/src/Magnum/Shaders/VertexColorGL.h @@ -112,6 +112,7 @@ similar for all shaders, see @ref shaders-usage-multidraw for an example. */ template class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram { public: + class Configuration; class CompileState; /** @@ -215,74 +216,71 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ * @brief Compile asynchronously * @m_since_latest * - * Compared to @ref VertexColorGL(Flags) can perform an asynchronous - * compilation and linking. See @ref shaders-async for more - * information. - * @see @ref VertexColorGL(CompileState&&), - * @ref compile(Flags, UnsignedInt) + * Compared to @ref VertexColorGL(const Configuration&) can perform an + * asynchronous compilation and linking. See @ref shaders-async for + * more information. + * @see @ref VertexColorGL(CompileState&&) */ - static CompileState compile(Flags flags = {}); + #ifdef DOXYGEN_GENERATING_OUTPUT + static CompileState compile(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + static CompileState compile(const Configuration& configuration); + static CompileState compile(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Compile asynchronously + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. + */ + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Compile for a multi-draw scenario asynchronously - * @m_since_latest - * - * Compared to @ref VertexColorGL(Flags, UnsignedInt) can perform an - * asynchronous compilation and linking. See @ref shaders-async for - * more information. - * @see @ref VertexColorGL(CompileState&&), @ref compile(Flags) + * @m_deprecated_since_latest Use @ref compile(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - static CompileState compile(Flags flags, UnsignedInt drawCount); + CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags, UnsignedInt drawCount); + #endif #endif /** * @brief Constructor - * @param flags Flags - * - * While this function is meant mainly for the classic uniform - * scenario (without @ref Flag::UniformBuffers set), it's equivalent to - * @ref VertexColorGL(Flags, UnsignedInt) with @p drawCount set to - * @cpp 1 @ce. - * @see @ref compile(Flags) + * @m_since_latest + */ + #ifdef DOXYGEN_GENERATING_OUTPUT + explicit VertexColorGL(const Configuration& configuration = Configuration{}); + #else + /* Configuration is forward-declared */ + explicit VertexColorGL(const Configuration& configuration); + explicit VertexColorGL(); + #endif + + #ifdef MAGNUM_BUILD_DEPRECATED + /** + * @brief Constructor + * @m_deprecated_since_latest Use @ref VertexColorGL(const Configuration&) + * instead. */ - explicit VertexColorGL(Flags flags = {}); + explicit CORRADE_DEPRECATED("use VertexColorGL(const Configuration& instead") VertexColorGL(Flags flags); #ifndef MAGNUM_TARGET_GLES2 /** * @brief Construct for a multi-draw scenario - * @param flags Flags - * @param drawCount Size of a @ref TransformationProjectionUniform2D - * / @ref TransformationProjectionUniform3D buffer bound with - * @ref bindTransformationProjectionBuffer() - * @m_since_latest - * - * If @p flags contains @ref Flag::UniformBuffers, @p drawCount - * describes the uniform buffer sizes as these are required to have a - * statically defined size. The draw offset is then set via - * @ref setDrawOffset(). - * - * If @p flags don't contain @ref Flag::UniformBuffers, @p drawCount is - * ignored and the constructor behaves the same as - * @ref VertexColorGL(Flags). - * @see @ref compile(Flags, UnsignedInt) + * @m_deprecated_since_latest Use @ref VertexColorGL(const Configuration&) + * instead. * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. */ - /** @todo this constructor will eventually need to have also joint - count, per-vertex weight count, view count for multiview and clip - plane count ... and putting them in arbitrary order next to each - other is too error-prone, so it needs some other solution - (accepting pairs of parameter type and value like in GL context - creation, e.g., which will probably need a new enum as reusing Flag - for this might be too confusing); what if some parameters won't be - (unsigned) integers? like a string with shader extensions? make a - whole Configuration class? */ - explicit VertexColorGL(Flags flags, UnsignedInt drawCount); + explicit CORRADE_DEPRECATED("use VertexColorGL(const Configuration& instead") VertexColorGL(Flags flags, UnsignedInt drawCount); + #endif #endif /** @@ -436,6 +434,63 @@ template class MAGNUM_SHADERS_EXPORT VertexColorGL: publ #endif }; +/** +@brief Configuration +@m_since_latest + +@see @ref VertexColorGL(const Configuration&), + @ref compile(const Configuration&) +*/ +template class VertexColorGL::Configuration { + public: + explicit Configuration() = default; + + /** @brief Flags */ + Flags flags() const { return _flags; } + + /** + * @brief Set flags + * + * No flags are set by default. + */ + Configuration& setFlags(Flags flags) { + _flags = flags; + return *this; + } + + #ifndef MAGNUM_TARGET_GLES2 + /** @brief Draw count */ + UnsignedInt drawCount() const { return _drawCount; } + + /** + * @brief Set draw count + * + * If @ref Flag::UniformBuffers is set, describes size of a + * @ref TransformationProjectionUniform2D / + * @ref TransformationProjectionUniform3D buffer bound with + * @ref bindTransformationProjectionBuffer(); as uniform buffers are + * required to have a statically defined size. The draw offset is then + * set via @ref setDrawOffset(). Default value is @cpp 1 @ce. + * + * If @ref Flag::UniformBuffers isn't set, this value is ignored. + * @see @ref setFlags() + * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} + * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. + * @requires_webgl20 Uniform buffers are not available in WebGL 1.0. + */ + Configuration& setDrawCount(UnsignedInt drawCount) { + _drawCount = drawCount; + return *this; + } + #endif + + private: + Flags _flags; + #ifndef MAGNUM_TARGET_GLES2 + UnsignedInt _drawCount = 1; + #endif +}; + /** @brief Asynchronous compilation state @m_since_latest