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