Browse Source

Shaders: take constructor arguments via a Configuration instance.

Because it was no longer bearable with three UnsignedInt arguments in a
row, especially when some of them are only available on a subset of
platforms. And it would get even worse with introduction of planned
features such as multiview or skinning.

Backwards compatibility is in place, as always. To ensure nothing
breaks, this commit still has all tests and snippets using the old API.
pull/582/merge
Vladimír Vondruš 4 years ago
parent
commit
c5abcf5140
  1. 4
      doc/changelog.dox
  2. 77
      src/Magnum/Shaders/DistanceFieldVectorGL.cpp
  3. 181
      src/Magnum/Shaders/DistanceFieldVectorGL.h
  4. 127
      src/Magnum/Shaders/FlatGL.cpp
  5. 178
      src/Magnum/Shaders/FlatGL.h
  6. 206
      src/Magnum/Shaders/MeshVisualizerGL.cpp
  7. 384
      src/Magnum/Shaders/MeshVisualizerGL.h
  8. 200
      src/Magnum/Shaders/PhongGL.cpp
  9. 209
      src/Magnum/Shaders/PhongGL.h
  10. 74
      src/Magnum/Shaders/VectorGL.cpp
  11. 178
      src/Magnum/Shaders/VectorGL.h
  12. 58
      src/Magnum/Shaders/VertexColorGL.cpp
  13. 147
      src/Magnum/Shaders/VertexColorGL.h

4
doc/changelog.dox

@ -911,6 +911,10 @@ See also:
and correspondingly renamed typedefs to make room for Vulkan shaders and and correspondingly renamed typedefs to make room for Vulkan shaders and
functionality shared between OpenGL and Vulkan implementation such as functionality shared between OpenGL and Vulkan implementation such as
uniform buffer layout definitions 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::setLightPositions() and
@ref Shaders::PhongGL::setLightPosition() taking three-component vectors @ref Shaders::PhongGL::setLightPosition() taking three-component vectors
are deprecated in favor of variants taking four-component vectors, where the are deprecated in favor of variants taking four-component vectors, where the

77
src/Magnum/Shaders/DistanceFieldVectorGL.cpp

@ -64,24 +64,20 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(),
#endif
) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::DistanceFieldVectorGL: material count can't be zero", CompileState{NoCreate}); "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}); "Shaders::DistanceFieldVectorGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::MultiDraw) { if(configuration.flags() >= Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters);
#elif !defined(MAGNUM_TARGET_WEBGL) #elif !defined(MAGNUM_TARGET_WEBGL)
@ -110,28 +106,28 @@ template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::Com
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
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"); .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n", "#define DRAW_COUNT {}\n",
drawCount)); configuration.drawCount()));
vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
vert.addSource(rs.getString("generic.glsl")) vert.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Vector.vert")); .addSource(rs.getString("Vector.vert"));
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
frag.addSource(Utility::formatString( frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define MATERIAL_COUNT {}\n" "#define MATERIAL_COUNT {}\n"
"#define DRAW_COUNT {}\n", "#define DRAW_COUNT {}\n",
materialCount, configuration.materialCount(),
drawCount)); configuration.drawCount()));
frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
@ -141,10 +137,10 @@ template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::Com
frag.submitCompile(); frag.submitCompile();
DistanceFieldVectorGL<dimensions> out{NoInit}; DistanceFieldVectorGL<dimensions> out{NoInit};
out._flags = flags; out._flags = configuration.flags();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount; out._materialCount = configuration.materialCount();
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
out.attachShaders({vert, frag}); out.attachShaders({vert, frag});
@ -164,6 +160,26 @@ template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::Com
return CompileState{std::move(out), std::move(vert), std::move(frag), version}; return CompileState{std::move(out), std::move(vert), std::move(frag), version};
} }
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile() {
return compile(Configuration{});
}
#ifdef MAGNUM_BUILD_DEPRECATED
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags) {
return compile(Configuration{}
.setFlags(flags));
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) {
return compile(Configuration{}
.setFlags(flags)
.setMaterialCount(materialCount)
.setDrawCount(drawCount));
}
#endif
#endif
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(CompileState&& state): DistanceFieldVectorGL{static_cast<DistanceFieldVectorGL&&>(std::move(state))} { template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(CompileState&& state): DistanceFieldVectorGL{static_cast<DistanceFieldVectorGL&&>(std::move(state))} {
#ifdef CORRADE_GRACEFUL_ASSERT #ifdef CORRADE_GRACEFUL_ASSERT
/* When graceful assertions fire from within compile(), we get a NoCreate'd /* When graceful assertions fire from within compile(), we get a NoCreate'd
@ -234,19 +250,24 @@ template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFiel
static_cast<void>(version); static_cast<void>(version);
} }
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(NoInitT) {} template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Configuration& configuration): DistanceFieldVectorGL{compile(configuration)} {}
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(flags)} {} template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(): DistanceFieldVectorGL{Configuration{}} {}
#ifndef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_BUILD_DEPRECATED
template<UnsignedInt dimensions> typename DistanceFieldVectorGL<dimensions>::CompileState DistanceFieldVectorGL<dimensions>::compile(const Flags flags) { template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags): DistanceFieldVectorGL{compile(Configuration{}
return compile(flags, 1, 1); .setFlags(flags))} {}
}
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): #ifndef MAGNUM_TARGET_GLES2
DistanceFieldVectorGL{compile(flags, materialCount, drawCount)} {} template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): DistanceFieldVectorGL{compile(Configuration{}
.setFlags(flags)
.setMaterialCount(materialCount)
.setDrawCount(drawCount))} {}
#endif
#endif #endif
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>::DistanceFieldVectorGL(NoInitT) {}
template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>& DistanceFieldVectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) { template<UnsignedInt dimensions> DistanceFieldVectorGL<dimensions>& DistanceFieldVectorGL<dimensions>::setTransformationProjectionMatrix(const MatrixTypeFor<dimensions, Float>& matrix) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers), CORRADE_ASSERT(!(_flags >= Flag::UniformBuffers),

181
src/Magnum/Shaders/DistanceFieldVectorGL.h

@ -122,6 +122,7 @@ example.
*/ */
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL: public GL::AbstractShaderProgram { template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVectorGL: public GL::AbstractShaderProgram {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -225,80 +226,71 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @m_since_latest
* *
* Compared to @ref DistanceFieldVectorGL(Flags) can perform an * Compared to @ref DistanceFieldVectorGL(const Configuration&) can
* asynchronous compilation and linking. See @ref shaders-async for * perform an asynchronous compilation and linking. See
* more information. * @ref shaders-async for more information.
* @see @ref DistanceFieldVectorGL(CompileState&&), * @see @ref DistanceFieldVectorGL(CompileState&&)
* @ref compile(Flags, UnsignedInt, UnsignedInt) */
#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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @m_since_latest
* */
* While this function is meant mainly for the classic uniform #ifdef DOXYGEN_GENERATING_OUTPUT
* scenario (without @ref Flag::UniformBuffers set), it's equivalent to explicit DistanceFieldVectorGL(const Configuration& configuration = Configuration{});
* @ref DistanceFieldVectorGL(Flags, UnsignedInt, UnsignedInt) with #else
* @p materialCount and @p drawCount set to @cpp 1 @ce. /* Configuration is forward-declared */
* @see @ref compile(Flags) 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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref DistanceFieldVectorGL(const Configuration&)
* @param materialCount Size of a @ref DistanceFieldVectorMaterialUniform * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use DistanceFieldVectorGL(const Configuration& instead") DistanceFieldVectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#endif #endif
/** /**
@ -637,6 +629,91 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT DistanceFieldVector
#endif #endif
}; };
/**
@brief Configuration
@m_since_latest
@see @ref DistanceFieldVectorGL(const Configuration&),
@ref compile(const Configuration&)
*/
template<UnsignedInt dimensions> class DistanceFieldVectorGL<dimensions>::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 @brief Asynchronous compilation state
@m_since_latest @m_since_latest

127
src/Magnum/Shaders/FlatGL.cpp

@ -69,16 +69,12 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(const Flags flags template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
) {
#ifndef CORRADE_NO_ASSERT #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 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || configuration.flags() >= Flag::ObjectIdTexture
#endif #endif
; ;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
@ -87,25 +83,25 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #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}); "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}); "Shaders::FlatGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #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}); "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}); "Shaders::FlatGL: texture arrays require texture transformation enabled as well if uniform buffers are used", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::MultiDraw) { if(configuration.flags() >= Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters);
#elif !defined(MAGNUM_TARGET_WEBGL) #elif !defined(MAGNUM_TARGET_WEBGL)
@ -116,7 +112,7 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::TextureArrays) if(configuration.flags() >= Flag::TextureArrays)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array);
#endif #endif
@ -138,54 +134,54 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
vert.addSource((flags & Flag::Textured vert.addSource((configuration.flags() & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || configuration.flags() >= Flag::ObjectIdTexture
#endif #endif
) ? "#define TEXTURED\n" : "") ) ? "#define TEXTURED\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(configuration.flags() & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif #endif
.addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n") .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif #endif
.addSource(flags & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") .addSource(configuration.flags() & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
.addSource(flags >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : ""); .addSource(configuration.flags() >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n", "#define DRAW_COUNT {}\n",
drawCount)); configuration.drawCount()));
vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
vert.addSource(rs.getString("generic.glsl")) vert.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Flat.vert")); .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 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif #endif
.addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") .addSource(configuration.flags() & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(configuration.flags() & Flag::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(flags >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") .addSource(configuration.flags() >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "")
#endif #endif
; ;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
frag.addSource(Utility::formatString( frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
drawCount, configuration.drawCount(),
materialCount)); configuration.materialCount()));
frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
@ -195,10 +191,10 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
frag.submitCompile(); frag.submitCompile();
FlatGL<dimensions> out{NoInit}; FlatGL<dimensions> out{NoInit};
out._flags = flags; out._flags = configuration.flags();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount; out._materialCount = configuration.materialCount();
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
out.attachShaders({vert, frag}); out.attachShaders({vert, frag});
@ -211,25 +207,25 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
#endif #endif
{ {
out.bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
if(flags & Flag::Textured if(configuration.flags() & Flag::Textured
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || configuration.flags() >= Flag::ObjectIdTexture
#endif #endif
) )
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags & Flag::VertexColor) if(configuration.flags() & Flag::VertexColor)
out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) { if(configuration.flags() & Flag::ObjectId) {
out.bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ColorOutput, "color");
out.bindFragmentDataLocation(ObjectIdOutput, "objectId"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
} }
if(flags >= Flag::InstancedObjectId) if(configuration.flags() >= Flag::InstancedObjectId)
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) if(configuration.flags() & Flag::InstancedTransformation)
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(flags >= Flag::InstancedTextureOffset) if(configuration.flags() >= Flag::InstancedTextureOffset)
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
} }
#endif #endif
@ -239,6 +235,26 @@ template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatG
return CompileState{std::move(out), std::move(vert), std::move(frag), version}; return CompileState{std::move(out), std::move(vert), std::move(frag), version};
} }
template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile() {
return compile(Configuration{});
}
#ifdef MAGNUM_BUILD_DEPRECATED
template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(const Flags flags) {
return compile(Configuration{}
.setFlags(flags));
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) {
return compile(Configuration{}
.setFlags(flags)
.setMaterialCount(materialCount)
.setDrawCount(drawCount));
}
#endif
#endif
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(CompileState&& state): FlatGL{static_cast<FlatGL&&>(std::move(state))} { template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(CompileState&& state): FlatGL{static_cast<FlatGL&&>(std::move(state))} {
#ifdef CORRADE_GRACEFUL_ASSERT #ifdef CORRADE_GRACEFUL_ASSERT
/* When graceful assertions fire from within compile(), we get a NoCreate'd /* When graceful assertions fire from within compile(), we get a NoCreate'd
@ -315,15 +331,20 @@ template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(CompileState&& state
static_cast<void>(context); static_cast<void>(context);
} }
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(Flags flags): FlatGL{compile(flags)} {} template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Configuration& configuration): FlatGL{compile(configuration)} {}
#ifndef MAGNUM_TARGET_GLES2 template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(): FlatGL{Configuration{}} {}
template<UnsignedInt dimensions> typename FlatGL<dimensions>::CompileState FlatGL<dimensions>::compile(Flags flags) {
return compile(flags, 1, 1); #ifdef MAGNUM_BUILD_DEPRECATED
} template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags): FlatGL{compile(Configuration{}
.setFlags(flags))} {}
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount): #ifndef MAGNUM_TARGET_GLES2
FlatGL{compile(flags, materialCount, drawCount)} {} template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): FlatGL{compile(Configuration{}
.setFlags(flags)
.setMaterialCount(materialCount)
.setDrawCount(drawCount))} {}
#endif
#endif #endif
template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(NoInitT) {} template<UnsignedInt dimensions> FlatGL<dimensions>::FlatGL(NoInitT) {}

178
src/Magnum/Shaders/FlatGL.h

@ -203,6 +203,7 @@ all shaders, see @ref shaders-usage-multidraw for an example.
*/ */
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram { template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -548,79 +549,71 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @m_since_latest
* *
* Compared to @ref FlatGL(Flags) can perform an asynchronous * Compared to @ref FlatGL(const Configuration&) can perform an
* compilation and linking. See @ref shaders-async for more * asynchronous compilation and linking. See @ref shaders-async for
* information. * more information.
* @see @ref FlatGL(CompileState&&), * @see @ref FlatGL(CompileState&&)
* @ref compile(Flags, UnsignedInt, UnsignedInt)
*/ */
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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @m_since_latest
* */
* While this function is meant mainly for the classic uniform #ifdef DOXYGEN_GENERATING_OUTPUT
* scenario (without @ref Flag::UniformBuffers set), it's equivalent to explicit FlatGL(const Configuration& configuration = Configuration{});
* @ref FlatGL(Flags, UnsignedInt, UnsignedInt) with @p materialCount #else
* and @p drawCount set to @cpp 1 @ce. /* Configuration is forward-declared */
* @see @ref compile(Flags) 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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref FlatGL(const Configuration&)
* @param materialCount Size of a @ref FlatMaterialUniform buffer * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use FlatGL(const Configuration& instead") FlatGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#endif #endif
/** /**
@ -1048,6 +1041,89 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::
#endif #endif
}; };
/**
@brief Configuration
@m_since_latest
@see @ref FlatGL(const Configuration&), @ref compile(const Configuration&)
*/
template<UnsignedInt dimensions> class FlatGL<dimensions>::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 @brief Asynchronous compilation state
@m_since_latest @m_since_latest

206
src/Magnum/Shaders/MeshVisualizerGL.cpp

@ -376,19 +376,15 @@ MeshVisualizerGLBase& MeshVisualizerGLBase::bindObjectIdTexture(GL::Texture2DArr
} }
MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2 const FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(configuration.flags()));
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
) {
const FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags));
assertExtensions(baseFlags); assertExtensions(baseFlags);
#ifndef MAGNUM_TARGET_GLES2 #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}); "Shaders::MeshVisualizerGL2D: at least one visualization feature has to be enabled", CompileState{NoCreate});
#else #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}); "Shaders::MeshVisualizerGL2D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate});
#endif #endif
@ -396,9 +392,9 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags
constructor when testing for asserts -- GLSL compilation would fail constructor when testing for asserts -- GLSL compilation would fail
otherwise */ otherwise */
#ifndef MAGNUM_TARGET_GLES2 #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}); "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}); "Shaders::MeshVisualizerGL2D: draw count can't be zero", CompileState{NoCreate});
#endif #endif
@ -411,7 +407,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags
GL::Shader frag{NoCreate}; GL::Shader frag{NoCreate};
const GL::Version version = setupShaders(vert, frag, rs, baseFlags const GL::Version version = setupShaders(vert, frag, rs, baseFlags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, materialCount, drawCount , configuration.materialCount(), configuration.drawCount()
#endif #endif
); );
Containers::Optional<GL::Shader> geom; Containers::Optional<GL::Shader> geom;
@ -420,7 +416,7 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags
/* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when
nothing actually needs it, as that makes checks much simpler in nothing actually needs it, as that makes checks much simpler in
the shader code */ the shader code */
.addSource((flags & Flag::NoGeometryShader) || !(flags & Flag::Wireframe) ? .addSource((configuration.flags() & Flag::NoGeometryShader) || !(configuration.flags() & Flag::Wireframe) ?
"#define NO_GEOMETRY_SHADER\n" : "") "#define NO_GEOMETRY_SHADER\n" : "")
.addSource(rs.getString("generic.glsl")) .addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("MeshVisualizer.vert")); .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 /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when
nothing actually needs it, as that makes checks much simpler in nothing actually needs it, as that makes checks much simpler in
the shader code */ the shader code */
.addSource((flags & Flag::NoGeometryShader) || !(flags & Flag::Wireframe) ? .addSource((configuration.flags() & Flag::NoGeometryShader) || !(configuration.flags() & Flag::Wireframe) ?
"#define NO_GEOMETRY_SHADER\n" : ""); "#define NO_GEOMETRY_SHADER\n" : "");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
frag.addSource("#define TWO_DIMENSIONS\n"); frag.addSource("#define TWO_DIMENSIONS\n");
#endif #endif
frag.addSource(rs.getString("generic.glsl")) 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 !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 = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry);
(*geom) (*geom)
.addSource("#define WIREFRAME_RENDERING\n#define MAX_VERTICES 3\n") .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_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : ""); "#define PRIMITIVE_ID\n") : "");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
geom->addSource(Utility::formatString( geom->addSource(Utility::formatString(
"#define TWO_DIMENSIONS\n" "#define TWO_DIMENSIONS\n"
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
drawCount, configuration.drawCount(),
materialCount)); configuration.materialCount()));
geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); geom->addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
geom->addSource(rs.getString("MeshVisualizer.geom")); geom->addSource(rs.getString("MeshVisualizer.geom"));
@ -477,8 +473,8 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags
MeshVisualizerGL2D out{NoInit}; MeshVisualizerGL2D out{NoInit};
out._flags = baseFlags; out._flags = baseFlags;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount; out._materialCount = configuration.materialCount();
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
out.attachShaders({vert, frag}); out.attachShaders({vert, frag});
@ -492,15 +488,15 @@ MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags
{ {
out.bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) if(configuration.flags() >= Flag::ObjectIdTexture)
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags >= Flag::InstancedObjectId) if(configuration.flags() >= Flag::InstancedObjectId)
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) if(configuration.flags() & Flag::InstancedTransformation)
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::InstancedTextureOffset) if(configuration.flags() >= Flag::InstancedTextureOffset)
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif #endif
#if !defined(MAGNUM_TARGET_GLES) || defined(MAGNUM_TARGET_GLES2) #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}; return CompileState{std::move(out), std::move(vert), std::move(frag), geom ? &*geom : nullptr, version};
} }
MeshVisualizerGL2D::MeshVisualizerGL2D(const Flags flags): MeshVisualizerGL2D{compile(flags)} {} #ifdef MAGNUM_BUILD_DEPRECATED
#ifndef MAGNUM_TARGET_GLES2
MeshVisualizerGL2D::CompileState MeshVisualizerGL2D::compile(const Flags flags) { 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 #endif
MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D{static_cast<MeshVisualizerGL2D&&>(std::move(state))} { MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D{static_cast<MeshVisualizerGL2D&&>(std::move(state))} {
@ -643,6 +645,20 @@ MeshVisualizerGL2D::MeshVisualizerGL2D(CompileState&& state): MeshVisualizerGL2D
static_cast<void>(version); static_cast<void>(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) { MeshVisualizerGL2D& MeshVisualizerGL2D::setViewportSize(const Vector2& size) {
/* Not asserting here, since the relation to wireframe is a bit vague. /* Not asserting here, since the relation to wireframe is a bit vague.
Also it's an ugly hack that should be removed, ideally. */ Also it's an ugly hack that should be removed, ideally. */
@ -703,31 +719,27 @@ MeshVisualizerGL2D& MeshVisualizerGL2D::bindDrawBuffer(GL::Buffer& buffer, const
} }
#endif #endif
MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2 FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(configuration.flags()));
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
) {
FlagsBase baseFlags = Implementation::MeshVisualizerGLBase::FlagBase(UnsignedInt(flags));
assertExtensions(baseFlags); assertExtensions(baseFlags);
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #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}); "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}); "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}); "Shaders::MeshVisualizerGL3D: Flag::BitangentDirection and Flag::BitangentFromTangentDirection are mutually exclusive", CompileState{NoCreate});
#elif !defined(MAGNUM_TARGET_GLES2) #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}); "Shaders::MeshVisualizerGL3D: at least one visualization feature has to be enabled", CompileState{NoCreate});
#else #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}); "Shaders::MeshVisualizerGL3D: at least Flag::Wireframe has to be enabled", CompileState{NoCreate});
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #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}); "Shaders::MeshVisualizerGL3D: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate});
#endif #endif
@ -735,9 +747,9 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
constructor when testing for asserts -- GLSL compilation would fail constructor when testing for asserts -- GLSL compilation would fail
otherwise */ otherwise */
#ifndef MAGNUM_TARGET_GLES2 #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}); "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}); "Shaders::MeshVisualizerGL3D: draw count can't be zero", CompileState{NoCreate});
#endif #endif
@ -750,32 +762,32 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
GL::Shader frag{NoCreate}; GL::Shader frag{NoCreate};
const GL::Version version = setupShaders(vert, frag, rs, baseFlags const GL::Version version = setupShaders(vert, frag, rs, baseFlags
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, materialCount, drawCount , configuration.materialCount(), configuration.drawCount()
#endif #endif
); );
Containers::Optional<GL::Shader> geom; Containers::Optional<GL::Shader> geom;
/* Expands the check done for wireframe in MeshVisualizerBase with TBN */ /* Expands the check done for wireframe in MeshVisualizerBase with TBN */
#ifndef MAGNUM_TARGET_GLES #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) #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 #endif
vert.addSource("#define THREE_DIMENSIONS\n") vert.addSource("#define THREE_DIMENSIONS\n")
/* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when
nothing actually needs it, as that makes checks much simpler in nothing actually needs it, as that makes checks much simpler in
the vertex shader code */ 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) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection|Flag::NormalDirection |Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection|Flag::NormalDirection
#endif #endif
)) ? "#define NO_GEOMETRY_SHADER\n" : "") )) ? "#define NO_GEOMETRY_SHADER\n" : "")
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
.addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") .addSource(configuration.flags() & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "")
.addSource(flags & Flag::BitangentFromTangentDirection ? "#define BITANGENT_FROM_TANGENT_DIRECTION\n" : "") .addSource(configuration.flags() & Flag::BitangentFromTangentDirection ? "#define BITANGENT_FROM_TANGENT_DIRECTION\n" : "")
.addSource(flags & Flag::BitangentDirection ? "#define BITANGENT_DIRECTION\n" : "") .addSource(configuration.flags() & Flag::BitangentDirection ? "#define BITANGENT_DIRECTION\n" : "")
.addSource(flags & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : "") .addSource(configuration.flags() & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : "")
#endif #endif
; ;
vert.addSource(rs.getString("generic.glsl")) 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 /* Pass NO_GEOMETRY_SHADER not only when NoGeometryShader but also when
nothing actually needs it, as that makes checks much simpler in nothing actually needs it, as that makes checks much simpler in
the vertex shader code */ 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) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection|Flag::NormalDirection |Flag::TangentDirection|Flag::BitangentDirection|Flag::BitangentFromTangentDirection|Flag::NormalDirection
#endif #endif
)) ? "#define NO_GEOMETRY_SHADER\n" : "") )) ? "#define NO_GEOMETRY_SHADER\n" : "")
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #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 #endif
; ;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
frag.addSource("#define THREE_DIMENSIONS\n"); frag.addSource("#define THREE_DIMENSIONS\n");
#endif #endif
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("MeshVisualizer.frag")); .addSource(rs.getString("MeshVisualizer.frag"));
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #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; Int maxVertices = 0;
if(flags & Flag::Wireframe) maxVertices += 3; if(configuration.flags() & Flag::Wireframe) maxVertices += 3;
if(flags & Flag::TangentDirection) maxVertices += 3*6; if(configuration.flags() & Flag::TangentDirection) maxVertices += 3*6;
if(flags & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection)) if(configuration.flags() & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection))
maxVertices += 3*6; 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 = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Geometry);
(*geom) (*geom)
.addSource(Utility::formatString("#define MAX_VERTICES {}\n", maxVertices)) .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::ObjectIdTexture ? "#define TEXTURED\n" : "")
.addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(baseFlags & FlagBase::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
.addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(baseFlags & FlagBase::ObjectId ? "#define OBJECT_ID\n" : "")
@ -822,19 +834,19 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
(baseFlags >= FlagBase::PrimitiveIdFromVertexId ? (baseFlags >= FlagBase::PrimitiveIdFromVertexId ?
"#define PRIMITIVE_ID_FROM_VERTEX_ID\n" : "#define PRIMITIVE_ID_FROM_VERTEX_ID\n" :
"#define PRIMITIVE_ID\n") : "") "#define PRIMITIVE_ID\n") : "")
.addSource(flags & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "") .addSource(configuration.flags() & Flag::TangentDirection ? "#define TANGENT_DIRECTION\n" : "")
.addSource(flags & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection) ? "#define BITANGENT_DIRECTION\n" : "") .addSource(configuration.flags() & (Flag::BitangentDirection|Flag::BitangentFromTangentDirection) ? "#define BITANGENT_DIRECTION\n" : "")
.addSource(flags & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : ""); .addSource(configuration.flags() & Flag::NormalDirection ? "#define NORMAL_DIRECTION\n" : "");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
geom->addSource(Utility::formatString( geom->addSource(Utility::formatString(
"#define THREE_DIMENSIONS\n" "#define THREE_DIMENSIONS\n"
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
drawCount, configuration.drawCount(),
materialCount)); configuration.materialCount()));
geom->addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); geom->addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
geom->addSource(rs.getString("MeshVisualizer.geom")); geom->addSource(rs.getString("MeshVisualizer.geom"));
@ -850,8 +862,8 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
MeshVisualizerGL3D out{NoInit}; MeshVisualizerGL3D out{NoInit};
out._flags = baseFlags; out._flags = baseFlags;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount; out._materialCount = configuration.materialCount();
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
out.attachShaders({vert, frag}); out.attachShaders({vert, frag});
@ -865,30 +877,30 @@ MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(Flags flags
{ {
out.bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::ObjectIdTexture) if(configuration.flags() >= Flag::ObjectIdTexture)
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
if(flags >= Flag::InstancedObjectId) if(configuration.flags() >= Flag::InstancedObjectId)
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) { if(configuration.flags() & Flag::InstancedTransformation) {
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #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"); out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
#endif #endif
} }
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::InstancedTextureOffset) if(configuration.flags() >= Flag::InstancedTextureOffset)
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
#endif #endif
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL) #if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
if(flags & Flag::TangentDirection || if(configuration.flags() & Flag::TangentDirection ||
flags & Flag::BitangentFromTangentDirection) configuration.flags() & Flag::BitangentFromTangentDirection)
out.bindAttributeLocation(Tangent4::Location, "tangent"); out.bindAttributeLocation(Tangent4::Location, "tangent");
if(flags & Flag::BitangentDirection) if(configuration.flags() & Flag::BitangentDirection)
out.bindAttributeLocation(Bitangent::Location, "bitangent"); out.bindAttributeLocation(Bitangent::Location, "bitangent");
if(flags & Flag::NormalDirection || if(configuration.flags() & Flag::NormalDirection ||
flags & Flag::BitangentFromTangentDirection) configuration.flags() & Flag::BitangentFromTangentDirection)
out.bindAttributeLocation(Normal::Location, "normal"); out.bindAttributeLocation(Normal::Location, "normal");
#endif #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}; 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<MeshVisualizerGL3D&&>(std::move(state))} { MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D{static_cast<MeshVisualizerGL3D&&>(std::move(state))} {
#ifdef CORRADE_GRACEFUL_ASSERT #ifdef CORRADE_GRACEFUL_ASSERT
/* When graceful assertions fire from within compile(), we get a NoCreate'd /* When graceful assertions fire from within compile(), we get a NoCreate'd
@ -1055,14 +1083,20 @@ MeshVisualizerGL3D::MeshVisualizerGL3D(CompileState&& state): MeshVisualizerGL3D
static_cast<void>(version); static_cast<void>(version);
} }
MeshVisualizerGL3D::MeshVisualizerGL3D(const Flags flags): MeshVisualizerGL3D{compile(flags)} {} MeshVisualizerGL3D::MeshVisualizerGL3D(const Configuration& configuration): MeshVisualizerGL3D{compile(configuration)} {}
#ifndef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_BUILD_DEPRECATED
MeshVisualizerGL3D::CompileState MeshVisualizerGL3D::compile(const Flags flags) { MeshVisualizerGL3D::MeshVisualizerGL3D(): MeshVisualizerGL3D{Configuration{}} {}
return compile(flags, 1, 1);
} 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 #endif
MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) { MeshVisualizerGL3D& MeshVisualizerGL3D::setTransformationMatrix(const Matrix4& matrix) {

384
src/Magnum/Shaders/MeshVisualizerGL.h

@ -180,6 +180,7 @@ texture offset (or offset and layer).
*/ */
class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisualizerGLBase { class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisualizerGLBase {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -443,82 +444,61 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @m_since_latest
* *
* Compared to @ref MeshVisualizerGL2D(Flags) can perform an * Compared to @ref MeshVisualizerGL2D(const Configuration&) can
* asynchronous compilation and linking. See @ref shaders-async for * perform an asynchronous compilation and linking. See
* more information. * @ref shaders-async for more information.
* @see @ref MeshVisualizerGL2D(CompileState&&), * @see @ref MeshVisualizerGL2D(CompileState&&)
* @ref compile(Flags, UnsignedInt, UnsignedInt)
*/ */
/* No default value, consistently with MeshVisualizerGL2D(Flags) */ /* No default value, consistently with MeshVisualizerGL2D(Configuration) */
static CompileState compile(Flags flags); 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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @m_since_latest
*
* 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)
*/ */
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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref MeshVisualizerGL2D(const Configuration&)
* @param materialCount Size of a @ref MeshVisualizerMaterialUniform * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use MeshVisualizerGL2D(const Configuration& instead") MeshVisualizerGL2D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#endif #endif
/** /**
@ -878,6 +858,93 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL2D: public Implementation::MeshVisua
Int _transformationProjectionMatrixUniform{9}; 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 @brief Asynchronous compilation state
@m_since_latest @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 { class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisualizerGLBase {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -1656,100 +1724,81 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @m_since_latest
* *
* Compared to @ref MeshVisualizerGL3D(Flags) can perform an * Compared to @ref MeshVisualizerGL3D(const Configuration&) can
* asynchronous compilation and linking. See @ref shaders-async for * perform an asynchronous compilation and linking. See
* more information. * @ref shaders-async for more information.
* @see @ref MeshVisualizerGL3D(CompileState&&), * @see @ref MeshVisualizerGL3D(CompileState&&)
* @ref compile(Flags, UnsignedInt, UnsignedInt) */
/* 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) */ CORRADE_DEPRECATED("use compile(const Configuration& instead") static CompileState compile(Flags flags);
static CompileState compile(Flags flags);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @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.
*
* 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)
*/ */
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 #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @brief Constructor * @brief Constructor
* @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(Flags) * @m_deprecated_since{2020,06} Use @ref MeshVisualizerGL3D(const Configuration&)
* instead. * instead.
*/ */
explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Flags) instead") MeshVisualizerGL3D(): MeshVisualizerGL3D{Flags{}} {} explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(Configuration) instead") MeshVisualizerGL3D();
#endif
/**
* @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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref MeshVisualizerGL3D(const Configuration&)
* @param materialCount Size of a @ref MeshVisualizerMaterialUniform * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use MeshVisualizerGL3D(const Configuration& instead") MeshVisualizerGL3D(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#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 * @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} {} 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 */ /** @brief Copying is not allowed */
MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete; MeshVisualizerGL3D(const MeshVisualizerGL3D&) = delete;
@ -2384,6 +2423,95 @@ class MAGNUM_SHADERS_EXPORT MeshVisualizerGL3D: public Implementation::MeshVisua
#endif #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 @brief Asynchronous compilation state
@m_since_latest @m_since_latest

200
src/Magnum/Shaders/PhongGL.cpp

@ -75,16 +75,12 @@ namespace {
#endif #endif
} }
PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount PhongGL::CompileState PhongGL::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount
#endif
) {
#ifndef CORRADE_NO_ASSERT #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 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || configuration.flags() >= Flag::ObjectIdTexture
#endif #endif
; ;
CORRADE_ASSERT(textureTransformationNotEnabledOrTextured, CORRADE_ASSERT(textureTransformationNotEnabledOrTextured,
@ -93,35 +89,35 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #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}); "Shaders::PhongGL: Bitangent attribute binding conflicts with the ObjectId attribute, use a Tangent4 attribute with instanced object ID rendering instead", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #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}); "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}); "Shaders::PhongGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #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}); "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}); "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}); "Shaders::PhongGL: light culling requires uniform buffers to be enabled", CompileState{NoCreate});
#endif #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}); "Shaders::PhongGL: specular texture requires the shader to not have specular disabled", CompileState{NoCreate});
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::MultiDraw) { if(configuration.flags() >= Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters);
#elif !defined(MAGNUM_TARGET_WEBGL) #elif !defined(MAGNUM_TARGET_WEBGL)
@ -132,7 +128,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh
} }
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::TextureArrays) if(configuration.flags() >= Flag::TextureArrays)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::EXT::texture_array);
#endif #endif
@ -146,7 +142,7 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh
const GL::Context& context = GL::Context::current(); const GL::Context& context = GL::Context::current();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || context.isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>(), CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || context.isExtensionSupported<GL::Extensions::ARB::uniform_buffer_object>(),
"Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), CompileState{NoCreate}); "Shaders::PhongGL: uniform buffers require" << GL::Extensions::ARB::uniform_buffer_object::string(), CompileState{NoCreate});
#endif #endif
@ -157,14 +153,14 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh
#endif #endif
PhongGL out{NoInit}; PhongGL out{NoInit};
out._flags = flags; out._flags = configuration.flags();
out._lightCount = lightCount; out._lightCount = configuration.lightCount();
out._lightColorsUniform = out._lightPositionsUniform + Int(lightCount); out._lightColorsUniform = out._lightPositionsUniform + Int(configuration.lightCount());
out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(lightCount); out._lightSpecularColorsUniform = out._lightPositionsUniform + 2*Int(configuration.lightCount());
out._lightRangesUniform = out._lightPositionsUniform + 3*Int(lightCount); out._lightRangesUniform = out._lightPositionsUniform + 3*Int(configuration.lightCount());
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount; out._materialCount = configuration.materialCount();
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); 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 #ifndef MAGNUM_TARGET_GLES
std::string lightInitializer; std::string lightInitializer;
if(!(flags >= Flag::UniformBuffers) && lightCount) { if(!(configuration.flags() >= Flag::UniformBuffers) && configuration.lightCount()) {
using namespace Containers::Literals; using namespace Containers::Literals;
/* Initializer for the light color / position / range arrays -- we need /* 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() + lightPositionInitializerPreamble.size() +
lightColorInitializerPreamble.size() + lightColorInitializerPreamble.size() +
lightRangeInitializerPreamble.size() + lightRangeInitializerPreamble.size() +
lightCount*(lightPositionInitializerItem.size() + configuration.lightCount()*(lightPositionInitializerItem.size() +
lightColorInitializerItem.size() + lightColorInitializerItem.size() +
lightRangeInitializerItem.size())); lightRangeInitializerItem.size()));
lightInitializer.append(lightPositionInitializerPreamble); 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); lightInitializer.append(lightPositionInitializerItem);
/* Drop the last comma and add a newline at the end */ /* 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.resize(lightInitializer.size() - 1);
lightInitializer.append(lightColorInitializerPreamble); 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); lightInitializer.append(lightColorInitializerItem);
/* Drop the last comma and add a newline at the end */ /* 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.resize(lightInitializer.size() - 1);
lightInitializer.append(lightRangeInitializerPreamble); 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); lightInitializer.append(lightRangeInitializerItem);
/* Drop the last comma and add a newline at the end */ /* 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 #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 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || configuration.flags() >= Flag::ObjectIdTexture
#endif #endif
) ? "#define TEXTURED\n" : "") ) ? "#define TEXTURED\n" : "")
.addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") .addSource(configuration.flags() & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "")
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "") .addSource(configuration.flags() & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "") .addSource(configuration.flags() & Flag::TextureTransformation ? "#define TEXTURE_TRANSFORMATION\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif #endif
.addSource(lightCount ? "#define HAS_LIGHTS\n" : "") .addSource(configuration.lightCount() ? "#define HAS_LIGHTS\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
#endif #endif
.addSource(flags & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "") .addSource(configuration.flags() & Flag::InstancedTransformation ? "#define INSTANCED_TRANSFORMATION\n" : "")
.addSource(flags >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : ""); .addSource(configuration.flags() >= Flag::InstancedTextureOffset ? "#define INSTANCED_TEXTURE_OFFSET\n" : "");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n", "#define DRAW_COUNT {}\n",
drawCount, configuration.drawCount(),
lightCount)); configuration.lightCount()));
vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
vert.addSource(rs.getString("generic.glsl")) vert.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Phong.vert")); .addSource(rs.getString("Phong.vert"));
frag.addSource(flags & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "") frag.addSource(configuration.flags() & Flag::AmbientTexture ? "#define AMBIENT_TEXTURE\n" : "")
.addSource(flags & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "") .addSource(configuration.flags() & Flag::DiffuseTexture ? "#define DIFFUSE_TEXTURE\n" : "")
.addSource(flags & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "") .addSource(configuration.flags() & Flag::SpecularTexture ? "#define SPECULAR_TEXTURE\n" : "")
.addSource(flags & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "") .addSource(configuration.flags() & Flag::NormalTexture ? "#define NORMAL_TEXTURE\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "") .addSource(configuration.flags() & Flag::TextureArrays ? "#define TEXTURE_ARRAYS\n" : "")
#endif #endif
.addSource(flags & Flag::Bitangent ? "#define BITANGENT\n" : "") .addSource(configuration.flags() & Flag::Bitangent ? "#define BITANGENT\n" : "")
.addSource(flags & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "") .addSource(configuration.flags() & Flag::VertexColor ? "#define VERTEX_COLOR\n" : "")
.addSource(flags & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "") .addSource(configuration.flags() & Flag::AlphaMask ? "#define ALPHA_MASK\n" : "")
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
.addSource(flags & Flag::ObjectId ? "#define OBJECT_ID\n" : "") .addSource(configuration.flags() & Flag::ObjectId ? "#define OBJECT_ID\n" : "")
.addSource(flags >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "") .addSource(configuration.flags() >= Flag::InstancedObjectId ? "#define INSTANCED_OBJECT_ID\n" : "")
.addSource(flags >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "") .addSource(configuration.flags() >= Flag::ObjectIdTexture ? "#define OBJECT_ID_TEXTURE\n" : "")
#endif #endif
.addSource(flags & Flag::NoSpecular ? "#define NO_SPECULAR\n" : "") .addSource(configuration.flags() & Flag::NoSpecular ? "#define NO_SPECULAR\n" : "")
; ;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
frag.addSource(Utility::formatString( frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n" "#define MATERIAL_COUNT {}\n"
"#define LIGHT_COUNT {}\n", "#define LIGHT_COUNT {}\n",
drawCount, configuration.drawCount(),
materialCount, configuration.materialCount(),
lightCount)); configuration.lightCount()));
frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "") frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "")
.addSource(flags >= Flag::LightCulling ? "#define LIGHT_CULLING\n" : ""); .addSource(configuration.flags() >= Flag::LightCulling ? "#define LIGHT_CULLING\n" : "");
} else } else
#endif #endif
{ {
@ -286,13 +282,13 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh
"#define LIGHT_COLORS_LOCATION {}\n" "#define LIGHT_COLORS_LOCATION {}\n"
"#define LIGHT_SPECULAR_COLORS_LOCATION {}\n" "#define LIGHT_SPECULAR_COLORS_LOCATION {}\n"
"#define LIGHT_RANGES_LOCATION {}\n", "#define LIGHT_RANGES_LOCATION {}\n",
lightCount, configuration.lightCount(),
out._lightPositionsUniform + lightCount, out._lightPositionsUniform + configuration.lightCount(),
out._lightPositionsUniform + 2*lightCount, out._lightPositionsUniform + 2*configuration.lightCount(),
out._lightPositionsUniform + 3*lightCount)); out._lightPositionsUniform + 3*configuration.lightCount()));
} }
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!(flags >= Flag::UniformBuffers) && lightCount) if(!(configuration.flags() >= Flag::UniformBuffers) && configuration.lightCount())
frag.addSource(std::move(lightInitializer)); frag.addSource(std::move(lightInitializer));
#endif #endif
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
@ -311,35 +307,35 @@ PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt ligh
#endif #endif
{ {
out.bindAttributeLocation(Position::Location, "position"); out.bindAttributeLocation(Position::Location, "position");
if(lightCount) if(configuration.lightCount())
out.bindAttributeLocation(Normal::Location, "normal"); out.bindAttributeLocation(Normal::Location, "normal");
if((flags & Flag::NormalTexture) && lightCount) { if((configuration.flags() & Flag::NormalTexture) && configuration.lightCount()) {
out.bindAttributeLocation(Tangent::Location, "tangent"); out.bindAttributeLocation(Tangent::Location, "tangent");
if(flags & Flag::Bitangent) if(configuration.flags() & Flag::Bitangent)
out.bindAttributeLocation(Bitangent::Location, "bitangent"); out.bindAttributeLocation(Bitangent::Location, "bitangent");
} }
if(flags & Flag::VertexColor) if(configuration.flags() & Flag::VertexColor)
out.bindAttributeLocation(Color3::Location, "vertexColor"); /* Color4 is the same */ 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 #ifndef MAGNUM_TARGET_GLES2
|| flags >= Flag::ObjectIdTexture || configuration.flags() >= Flag::ObjectIdTexture
#endif #endif
) )
out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); out.bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags & Flag::ObjectId) { if(configuration.flags() & Flag::ObjectId) {
out.bindFragmentDataLocation(ColorOutput, "color"); out.bindFragmentDataLocation(ColorOutput, "color");
out.bindFragmentDataLocation(ObjectIdOutput, "objectId"); out.bindFragmentDataLocation(ObjectIdOutput, "objectId");
} }
if(flags >= Flag::InstancedObjectId) if(configuration.flags() >= Flag::InstancedObjectId)
out.bindAttributeLocation(ObjectId::Location, "instanceObjectId"); out.bindAttributeLocation(ObjectId::Location, "instanceObjectId");
#endif #endif
if(flags & Flag::InstancedTransformation) { if(configuration.flags() & Flag::InstancedTransformation) {
out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix"); out.bindAttributeLocation(TransformationMatrix::Location, "instancedTransformationMatrix");
if(lightCount) if(configuration.lightCount())
out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix"); out.bindAttributeLocation(NormalMatrix::Location, "instancedNormalMatrix");
} }
if(flags >= Flag::InstancedTextureOffset) if(configuration.flags() >= Flag::InstancedTextureOffset)
out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset"); out.bindAttributeLocation(TextureOffset::Location, "instancedTextureOffset");
} }
#endif #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}; 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<PhongGL&&>(std::move(state))} { PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast<PhongGL&&>(std::move(state))} {
#ifdef CORRADE_GRACEFUL_ASSERT #ifdef CORRADE_GRACEFUL_ASSERT
/* When graceful assertions fire from within compile(), we get a NoCreate'd /* When graceful assertions fire from within compile(), we get a NoCreate'd
@ -469,14 +487,22 @@ PhongGL::PhongGL(CompileState&& state): PhongGL{static_cast<PhongGL&&>(std::move
static_cast<void>(version); static_cast<void>(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::PhongGL(): PhongGL{Configuration{}} {}
PhongGL::CompileState PhongGL::compile(const Flags flags, const UnsignedInt lightCount) {
return compile(flags, lightCount, 1, 1); #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 #endif
PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) { PhongGL& PhongGL::setAmbientColor(const Magnum::Color4& color) {

209
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 { class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -761,85 +762,71 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @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 * asynchronous compilation and linking. See @ref shaders-async for
* more information. * more information.
* @see @ref PhongGL(CompileState&&), * @see @ref PhongGL(CompileState&&)
* @ref compile(Flags, UnsignedInt, UnsignedInt, UnsignedInt) */
#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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @m_since_latest
* @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)
*/ */
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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref PhongGL(const Configuration&)
* @param lightCount Size of a @ref PhongLightUniform buffer bound * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use PhongGL(const Configuration& instead") PhongGL(Flags flags, UnsignedInt lightCount, UnsignedInt materialCount, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#endif #endif
/** /**
@ -1794,6 +1781,118 @@ class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
#endif #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 @brief Asynchronous compilation state
@m_since_latest @m_since_latest

74
src/Magnum/Shaders/VectorGL.cpp

@ -64,24 +64,20 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(const Flags flags template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt materialCount, const UnsignedInt drawCount CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.materialCount(),
#endif
) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || materialCount,
"Shaders::VectorGL: material count can't be zero", CompileState{NoCreate}); "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}); "Shaders::VectorGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::MultiDraw) { if(configuration.flags() >= Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters);
#elif !defined(MAGNUM_TARGET_WEBGL) #elif !defined(MAGNUM_TARGET_WEBGL)
@ -110,28 +106,28 @@ template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState Vec
GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex); GL::Shader vert = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Vertex);
GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment); GL::Shader frag = Implementation::createCompatibilityShader(rs, version, GL::Shader::Type::Fragment);
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"); .addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n", "#define DRAW_COUNT {}\n",
drawCount)); configuration.drawCount()));
vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
vert.addSource(rs.getString("generic.glsl")) vert.addSource(rs.getString("generic.glsl"))
.addSource(rs.getString("Vector.vert")); .addSource(rs.getString("Vector.vert"));
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
frag.addSource(Utility::formatString( frag.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n" "#define DRAW_COUNT {}\n"
"#define MATERIAL_COUNT {}\n", "#define MATERIAL_COUNT {}\n",
drawCount, configuration.drawCount(),
materialCount)); configuration.materialCount()));
frag.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); frag.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
frag.addSource(rs.getString("generic.glsl")) frag.addSource(rs.getString("generic.glsl"))
@ -141,10 +137,10 @@ template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState Vec
frag.submitCompile(); frag.submitCompile();
VectorGL out{NoInit}; VectorGL out{NoInit};
out._flags = flags; out._flags = configuration.flags();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._materialCount = materialCount; out._materialCount = configuration.materialCount();
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
out.attachShaders({vert, frag}); out.attachShaders({vert, frag});
@ -165,6 +161,26 @@ template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState Vec
return CompileState{std::move(out), std::move(vert), std::move(frag), version}; return CompileState{std::move(out), std::move(vert), std::move(frag), version};
} }
template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile() {
return compile(Configuration{});
}
#ifdef MAGNUM_BUILD_DEPRECATED
template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(const Flags flags) {
return compile(Configuration{}
.setFlags(flags));
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount) {
return compile(Configuration{}
.setFlags(flags)
.setMaterialCount(materialCount)
.setDrawCount(drawCount));
}
#endif
#endif
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(CompileState&& state): VectorGL{static_cast<VectorGL&&>(std::move(state))} { template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(CompileState&& state): VectorGL{static_cast<VectorGL&&>(std::move(state))} {
#ifdef CORRADE_GRACEFUL_ASSERT #ifdef CORRADE_GRACEFUL_ASSERT
/* When graceful assertions fire from within compile(), we get a NoCreate'd /* When graceful assertions fire from within compile(), we get a NoCreate'd
@ -231,14 +247,20 @@ template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(CompileState&& s
static_cast<void>(version); static_cast<void>(version);
} }
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags): VectorGL{compile(flags)} {} template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Configuration& configuration): VectorGL{compile(configuration)} {}
#ifndef MAGNUM_TARGET_GLES2 template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(): VectorGL{Configuration{}} {}
template<UnsignedInt dimensions> typename VectorGL<dimensions>::CompileState VectorGL<dimensions>::compile(const Flags flags) {
return compile(flags, 1, 1); #ifdef MAGNUM_BUILD_DEPRECATED
} template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags): VectorGL{compile(Configuration{}
.setFlags(flags))} {}
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): VectorGL{compile(flags, materialCount, drawCount)} {} #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(const Flags flags, const UnsignedInt materialCount, const UnsignedInt drawCount): VectorGL{compile(Configuration{}
.setFlags(flags)
.setMaterialCount(materialCount)
.setDrawCount(drawCount))} {}
#endif
#endif #endif
template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(NoInitT) {} template<UnsignedInt dimensions> VectorGL<dimensions>::VectorGL(NoInitT) {}

178
src/Magnum/Shaders/VectorGL.h

@ -117,6 +117,7 @@ example.
*/ */
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL::AbstractShaderProgram { template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL::AbstractShaderProgram {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -220,78 +221,71 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @m_since_latest
* *
* Compared to @ref VectorGL(Flags) can perform an asynchronous * Compared to @ref VectorGL(const Configuration&) can perform an
* compilation and linking. See @ref shaders-async for more * asynchronous compilation and linking. See @ref shaders-async for
* information. * more information.
* @see @ref VectorGL(CompileState&&), * @see @ref VectorGL(CompileState&&)
* @ref compile(Flags, UnsignedInt, UnsignedInt)
*/ */
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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @m_since_latest
*
* 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)
*/ */
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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref VectorGL(const Configuration&)
* @param materialCount Size of a @ref VectorMaterialUniform buffer * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use VectorGL(const Configuration& instead") VectorGL(Flags flags, UnsignedInt materialCount, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#endif #endif
/** /**
@ -587,6 +581,90 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL
#endif #endif
}; };
/**
@brief Configuration
@m_since_latest
@see @ref VectorGL(const Configuration&),
@ref compile(const Configuration&)
*/
template<UnsignedInt dimensions> class VectorGL<dimensions>::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 @brief Asynchronous compilation state
@m_since_latest @m_since_latest

58
src/Magnum/Shaders/VertexColorGL.cpp

@ -57,22 +57,18 @@ namespace {
#endif #endif
} }
template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(const Flags flags template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(const Configuration& configuration) {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
, const UnsignedInt drawCount CORRADE_ASSERT(!(configuration.flags() >= Flag::UniformBuffers) || configuration.drawCount(),
#endif
) {
#ifndef MAGNUM_TARGET_GLES2
CORRADE_ASSERT(!(flags >= Flag::UniformBuffers) || drawCount,
"Shaders::VertexColorGL: draw count can't be zero", CompileState{NoCreate}); "Shaders::VertexColorGL: draw count can't be zero", CompileState{NoCreate});
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(flags >= Flag::UniformBuffers) if(configuration.flags() >= Flag::UniformBuffers)
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::uniform_buffer_object);
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::MultiDraw) { if(configuration.flags() >= Flag::MultiDraw) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters); MAGNUM_ASSERT_GL_EXTENSION_SUPPORTED(GL::Extensions::ARB::shader_draw_parameters);
#elif !defined(MAGNUM_TARGET_WEBGL) #elif !defined(MAGNUM_TARGET_WEBGL)
@ -103,12 +99,12 @@ template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileStat
vert.addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n"); vert.addSource(dimensions == 2 ? "#define TWO_DIMENSIONS\n" : "#define THREE_DIMENSIONS\n");
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
if(flags >= Flag::UniformBuffers) { if(configuration.flags() >= Flag::UniformBuffers) {
vert.addSource(Utility::formatString( vert.addSource(Utility::formatString(
"#define UNIFORM_BUFFERS\n" "#define UNIFORM_BUFFERS\n"
"#define DRAW_COUNT {}\n", "#define DRAW_COUNT {}\n",
drawCount)); configuration.drawCount()));
vert.addSource(flags >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : ""); vert.addSource(configuration.flags() >= Flag::MultiDraw ? "#define MULTI_DRAW\n" : "");
} }
#endif #endif
vert.addSource(rs.getString("generic.glsl")) vert.addSource(rs.getString("generic.glsl"))
@ -120,9 +116,9 @@ template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileStat
frag.submitCompile(); frag.submitCompile();
VertexColorGL<dimensions> out{NoInit}; VertexColorGL<dimensions> out{NoInit};
out._flags = flags; out._flags = configuration.flags();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
out._drawCount = drawCount; out._drawCount = configuration.drawCount();
#endif #endif
out.attachShaders({vert, frag}); out.attachShaders({vert, frag});
@ -143,6 +139,25 @@ template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileStat
return CompileState{std::move(out), std::move(vert), std::move(frag), version}; return CompileState{std::move(out), std::move(vert), std::move(frag), version};
} }
template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile() {
return compile(Configuration{});
}
#ifdef MAGNUM_BUILD_DEPRECATED
template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(const Flags flags) {
return compile(Configuration{}
.setFlags(flags));
}
#ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(const Flags flags, const UnsignedInt drawCount) {
return compile(Configuration{}
.setFlags(flags)
.setDrawCount(drawCount));
}
#endif
#endif
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(CompileState&& state): VertexColorGL{static_cast<VertexColorGL&&>(std::move(state))} { template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(CompileState&& state): VertexColorGL{static_cast<VertexColorGL&&>(std::move(state))} {
#ifdef CORRADE_GRACEFUL_ASSERT #ifdef CORRADE_GRACEFUL_ASSERT
/* When graceful assertions fire from within compile(), we get a NoCreate'd /* When graceful assertions fire from within compile(), we get a NoCreate'd
@ -195,14 +210,19 @@ template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(Compil
static_cast<void>(version); static_cast<void>(version);
} }
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Flags flags): VertexColorGL{compile(flags)} {} template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Configuration& configuration): VertexColorGL{compile(configuration)} {}
#ifndef MAGNUM_TARGET_GLES2 template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(): VertexColorGL{Configuration{}} {}
template<UnsignedInt dimensions> typename VertexColorGL<dimensions>::CompileState VertexColorGL<dimensions>::compile(const Flags flags) {
return compile(flags, 1); #ifdef MAGNUM_BUILD_DEPRECATED
} template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Flags flags): VertexColorGL{compile(Configuration{}
.setFlags(flags))} {}
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Flags flags, const UnsignedInt drawCount): VertexColorGL{compile(flags, drawCount)} {} #ifndef MAGNUM_TARGET_GLES2
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(const Flags flags, const UnsignedInt drawCount): VertexColorGL{compile(Configuration{}
.setFlags(flags)
.setDrawCount(drawCount))} {}
#endif
#endif #endif
template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(NoInitT) {} template<UnsignedInt dimensions> VertexColorGL<dimensions>::VertexColorGL(NoInitT) {}

147
src/Magnum/Shaders/VertexColorGL.h

@ -112,6 +112,7 @@ similar for all shaders, see @ref shaders-usage-multidraw for an example.
*/ */
template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram { template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram {
public: public:
class Configuration;
class CompileState; class CompileState;
/** /**
@ -215,74 +216,71 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
* @brief Compile asynchronously * @brief Compile asynchronously
* @m_since_latest * @m_since_latest
* *
* Compared to @ref VertexColorGL(Flags) can perform an asynchronous * Compared to @ref VertexColorGL(const Configuration&) can perform an
* compilation and linking. See @ref shaders-async for more * asynchronous compilation and linking. See @ref shaders-async for
* information. * more information.
* @see @ref VertexColorGL(CompileState&&), * @see @ref VertexColorGL(CompileState&&)
* @ref compile(Flags, UnsignedInt)
*/ */
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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Compile for a multi-draw scenario asynchronously * @brief Compile for a multi-draw scenario asynchronously
* @m_since_latest * @m_deprecated_since_latest Use @ref compile(const Configuration&)
* * instead.
* 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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.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 #endif
/** /**
* @brief Constructor * @brief Constructor
* @param flags Flags * @m_since_latest
* */
* While this function is meant mainly for the classic uniform #ifdef DOXYGEN_GENERATING_OUTPUT
* scenario (without @ref Flag::UniformBuffers set), it's equivalent to explicit VertexColorGL(const Configuration& configuration = Configuration{});
* @ref VertexColorGL(Flags, UnsignedInt) with @p drawCount set to #else
* @cpp 1 @ce. /* Configuration is forward-declared */
* @see @ref compile(Flags) 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 #ifndef MAGNUM_TARGET_GLES2
/** /**
* @brief Construct for a multi-draw scenario * @brief Construct for a multi-draw scenario
* @param flags Flags * @m_deprecated_since_latest Use @ref VertexColorGL(const Configuration&)
* @param drawCount Size of a @ref TransformationProjectionUniform2D * instead.
* / @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)
* @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} * @requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0. * @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
* @requires_webgl20 Uniform buffers are not available in WebGL 1.0. * @requires_webgl20 Uniform buffers are not available in WebGL 1.0.
*/ */
/** @todo this constructor will eventually need to have also joint explicit CORRADE_DEPRECATED("use VertexColorGL(const Configuration& instead") VertexColorGL(Flags flags, UnsignedInt drawCount);
count, per-vertex weight count, view count for multiview and clip #endif
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);
#endif #endif
/** /**
@ -436,6 +434,63 @@ template<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: publ
#endif #endif
}; };
/**
@brief Configuration
@m_since_latest
@see @ref VertexColorGL(const Configuration&),
@ref compile(const Configuration&)
*/
template<UnsignedInt dimensions> class VertexColorGL<dimensions>::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 @brief Asynchronous compilation state
@m_since_latest @m_since_latest

Loading…
Cancel
Save