diff --git a/doc/changelog.dox b/doc/changelog.dox
index 2cb5cfe4b..a805c3a9a 100644
--- a/doc/changelog.dox
+++ b/doc/changelog.dox
@@ -149,7 +149,8 @@ See also:
- All builtin shaders now have opt-in support for uniform buffers on desktop,
OpenGL ES 3.0+ and WebGL 2.0, including multi-draw functionality for
- massive driver overhead reduction
+ massive driver overhead reduction. The @ref shaders overview page was
+ updated with an introduction the new features.
- @ref Shaders::FlatGL and @ref Shaders::PhongGL now support texture arrays,
available also in multi-draw and instanced scenarios
- Added @ref Shaders::PhongGL::setNormalTextureScale(), consuming the
diff --git a/doc/shaders.dox b/doc/shaders.dox
index eb867025f..f04dd56c3 100644
--- a/doc/shaders.dox
+++ b/doc/shaders.dox
@@ -34,8 +34,7 @@ namespace Magnum {
Magnum contains a set of general-purpose shaders for easy prototyping, UI
rendering and data visualization/debugging in both 2D and 3D scenes. The
-following shaders are available, see documentation of each class for sample
-output and example setup:
+following shaders are available:
- @ref Shaders::FlatGL "Shaders::FlatGL*D" --- flat shading using single
color or texture
@@ -48,32 +47,245 @@ output and example setup:
- @ref Shaders::MeshVisualizerGL2D / @ref Shaders::MeshVisualizerGL3D ---
wireframe visualization
-All the builtin shaders can be used on unextended OpenGL 2.1 and OpenGL ES 2.0
-/ WebGL 1.0, but they try to use the most recent technology available to have
-them as efficient as possible on every configuration.
+The essential functionality of builtin shaders can be used even on unextended
+OpenGL 2.1 and OpenGL ES 2.0 / WebGL 1.0, but the code will try to use the most
+recent technology available to have them as efficient as possible on every
+configuration. Some functionality, such as uniform buffers, texture arrays or
+object ID rendering, requires newer versions or extensions, as noted in
+documentation of a particular feature.
@section shaders-usage Usage
-Shader usage is divided into two parts: configuring vertex attributes in the
-mesh and configuring the shader itself.
+Shader usage is divided into two parts: describing vertex attributes in the
+mesh and setting up the shader itself.
-Each shader expects some set of vertex attributes, thus when adding vertex
+Each shader expects some set of vertex attributes, thus when adding a vertex
buffer into the mesh, you need to specify which shader attributes are on which
position in the buffer. See @ref GL::Mesh::addVertexBuffer() for details and
-usage examples. Example mesh configuration for @ref Shaders::PhongGL shader:
+usage examples. Example mesh configuration for the @ref Shaders::PhongGL
+shader:
@snippet MagnumShaders-gl.cpp shaders-setup
Each shader then has its own set of configuration functions. Some configuration
is static, specified commonly as flags in constructor, directly affecting
compiled shader code. Other configuration is specified through uniforms and
-various binding points, commonly exposed through various setters. All shader
-uniforms have a reasonable defaults so you are able to see at least something
-when using the shader directly without any further configuration, but in most
-cases you may want to specify at least the transformation/projection matrices.
-Example configuration and rendering using @link Shaders::PhongGL @endlink:
+various binding points, commonly exposed through various setters. For uniforms
+there's two different workflows --- a classical one, where uniforms have
+immediate setters, and a uniform buffer workflow, where the uniform parameters
+are saved to a structure and then uploaded to a GPU buffer. Let's compare both
+approaches:
-@snippet MagnumShaders-gl.cpp shaders-rendering
+@subsection shaders-usage-classic Using classic uniforms
+
+The most straightforward and portable way, working even on old OpenGL ES 2.0
+and WebGL 1.0 platforms, is using classic uniform setters. All shader uniforms
+have a reasonable defaults so you are able to see at least something when using
+the shader directly without any further configuration, but in most cases you
+may want to specify at least the transformation/projection matrices.
+Example configuration and rendering using @link Shaders::PhongGL @endlink ---
+by default it's just colored and uses a single light, and we set a color of
+both in addition to transformation, projection and normal matrices:
+
+@snippet MagnumShaders-gl.cpp shaders-classic
+
+@subsection shaders-usage-ubo Using uniform buffers
+
+Uniform buffers require GL 3.1, OpenGL ES 3.0 or WebGL 2.0 and are more verbose
+to set up, but when used the right way they can result in greatly reduced
+driver overhead. Uniform buffers get enabled using the
+@relativeref{Shaders::PhongGL,Flag::UniformBuffers} flag that's implemented for
+all builtin shaders, and after that you're not supposed to use most of the
+`set*()` APIs anymore, instead you have to fill uniform structures, upload them
+to @ref GL::Buffer instances and then bind those via various `bind*Buffer()`
+APIs. To simplify porting, documentation of each classic uniform setter lists
+the equivalent uniform buffer APIs.
+
+Because some parameters such as projection, material or light setup don't
+change every draw, they are organized into buffers based on expected frequency
+of change. This way you can fill the projection and material buffers just once
+at the start, light setup only when the camera position changes and with much
+less to upload for every draw. The separation is also done in a way that makes
+it possible to reuse projection/transformation data among different shaders,
+e.g. for a depth pre-pass.
+
+In the following example, projection and transformation parameters are supplied
+via generic shader-independent @ref Shaders::ProjectionUniform3D and
+@ref Shaders::TransformationUniform3D structures and Phong-specific parameters
+then via @ref Shaders::PhongDrawUniform, @ref Shaders::PhongMaterialUniform and
+@ref Shaders::PhongLightUniform structures. While the structures expose the
+fields directly, the data layout may be non-trivial and it's thus recommended
+to use the setters unless they prove to be a performance bottleneck:
+
+@snippet MagnumShaders-gl.cpp shaders-ubo
+
+Altogether, this results in the same output as in the classic uniform case
+shown above. Similarly to the classic uniforms, default-constructed structures
+have reasonable defaults to make the shader render at least something, but note
+that you *have to* bind the buffer to get the defaults, without a buffer bound
+you'll get a fully black mesh at best and nothing rendered at all in the worst
+cases.
+
+@m_class{m-block m-success}
+
+@par Importance of buffer usage and storage flags
+ With uniform buffers, it's very important what kind of memory gets used for
+ the backing storage. In the above snippets, the (implicit)
+ @ref GL::BufferUsage::StaticDraw got used for simplicity, but for data that
+ are changed for every draw it could make sense to pick
+ @ref GL::BufferUsage::DynamicDraw instead.
+@par
+ The most ideal way may be to use @gl_extension{ARB,buffer_storage}
+ from OpenGL 4.4, and instead of @ref GL::Buffer::setData() calling
+ @relativeref{GL::Buffer,setStorage()} directly with the uniform data and
+ with empty @ref GL::Buffer::StorageFlags, which makes the buffer immutable.
+ Updating such immutable buffer can be still done via
+ @ref GL::Buffer::copy() from another buffer, but setting or mapping the
+ data from the CPU side won't be possible.
+@par
+ As with everything, be sure to profile and pick the best workflow for your
+ target platform --- what's best for desktop may not be the best in WebGL,
+ and what works with WebGL running on top GL may not be the best with WebGL
+ that's itself implemented using D3D or Metal.
+
+@subsection shaders-usage-multidraw Multidraw and reducing driver overhead
+
+The main advantage of uniform buffers is the ability to specify data for
+multiple draws together --- after all, having to reupload three or four buffers
+for every draw like shown above wouldn't be really faster or easier than
+setting the uniforms directly. On the other hand, uploading everything first
+and binding a different subrange each time would avoid the reupload, but since
+most drivers have uniform buffer alignment requirement as high as 256 bytes
+(@ref GL::Buffer::uniformOffsetAlignment()), the per-draw buffers would have to
+be very sparse.
+
+Instead, it's possible to construct the shaders with a statically defined
+draw count, fill the buffers with data for that many draws at once and then use
+@relativeref{Shaders::PhongGL,setDrawOffset()} to pick concrete per-draw
+parameters. Since material parameters are commonly shared among multiple draws,
+the desired usage is to upload unique materials and then reference them via a
+@ref Shaders::PhongDrawUniform::materialId "Shaders::*DrawUniform::materialId".
+The following snippet shows drawing three different meshes, where two of them
+share the same material definition. The projection and light buffer is the same
+as above:
+
+@snippet MagnumShaders-gl.cpp shaders-multi
+
+While this minimizes the state changes to just a single immediate uniform being
+changed between draws, it's possible to go even further by using
+@ref GL::MeshView instances onto a single @ref GL::Mesh instead of several
+different @ref GL::Mesh objects --- that way the attribute layout doesn't need
+to be updated and it's just submitting draws with different offsets and counts.
+
+Finally, with mesh views and on platforms that support @gl_extension{ARB,shader_draw_parameters} from OpenGL 4.6 or the
+@gl_extension{ANGLE,multi_draw} / @webgl_extension{WEBGL,multi_draw} ES and
+WebGL extension, it's possible to directly submit a multi-draw command. The
+shader needs to have @relativeref{Shaders::PhongGL,Flag::MultiDraw} enabled,
+which will make it use the @glsl gl_DrawID @ce builtin to pick the per-draw
+parameters on its own. The above snippet modified for multidraw would then look
+like this, uniform upload and binding is the same as before:
+
+@snippet MagnumShaders-gl.cpp shaders-multidraw
+
+
+
+@m_class{m-block m-warning}
+
+@par Uniform buffer size limits
+ Note that size of a single uniform buffer that can be bound to a shader is
+ quite limited (@ref GL::AbstractShaderProgram::maxUniformBlockSize(),
+ usually just 16 or 64 kB), and another reason the parameters are separated
+ and deduplicated among several buffers is to maximize use of that memory.
+ With that you should always be able to submit at least 256 draws at once as
+ the biggest per-draw uniform structure used by builtin shaders has a size
+ of a 4x4 matrix.
+@par
+ For larger batches the expected workflow is to still upload everything at
+ once but then bind and draw smaller (and properly aligned) subranges that
+ fit into the limit. For convenience, all uniform structures are guaranteed
+ to fit evenly into multiples of 768 bytes, which should be large enough for
+ even the strictest @ref GL::Buffer::uniformOffsetAlignment() requirements.
+
+@subsection shaders-usage-instancing Instancing
+
+@ref Shaders::FlatGL and @ref Shaders::PhongGL support instancing, which allows
+them to render the same mesh several times but with different transformation
+and material applied. It can be thought of as a more constrained variant of the
+multidraw mentioned above, but instead of uniform buffers the per-instance
+parameters are passed through instanced mesh attributes.
+
+No uniform buffer requirement means this feature can be used even on OpenGL ES
+2.0 and WebGL 1.0 targets if corresponding instancing extensions are available.
+Using attributes instead of uniform buffers also means there's no limitation on
+how many instances can be drawn at once, on the other hand a mesh can have only
+a certain amount of attribute bindings and thus only the basic properties can
+be specified per-instance such as the transformation matrix or base color.
+
+The following snippet shows a setup similar to the multidraw above, except that
+it's just the same sphere drawn three times in different locations and with a
+different material applied. Note that the per-instance color is achieved by
+using the usual vertex color attribute, only instanced:
+
+@snippet MagnumShaders-gl.cpp shaders-instancing
+
+@subsection shaders-usage-textures Using textures
+
+Unless the shader requires a texture to work (which is the case of
+@ref Shaders::VectorGL and @ref Shaders::DistanceFieldVectorGL), by default all
+shaders are just colored. Enabling a texture is done via a flag (such as
+@ref Shaders::Phong::Flag::DiffuseTexture) and then the texture is bound via an
+appropriate `bind*Texture()` call. In most cases the texture value is
+multiplied with the corresponding color uniform.
+
+@snippet MagnumShaders-gl.cpp shaders-textures
+
+All shaders that support textures are also able to apply arbitrary
+transformation to the texture coordinate attribute by enabling
+@relativeref{Shaders::PhongGL,Flag::TextureTransformation} on a particular
+shader. Desired transformation is then supplied via
+@relativeref{Shaders::PhongGL,setTextureMatrix()} (or a
+@ref Shaders::TextureTransformationUniform in case uniform buffers are used).
+This can be useful for animations, when you have a larger atlas with switchable
+texture variations for a single mesh, or when you have texture coordinates
+quantized in some nontrivial way.
+
+Texture transformation is also useful in the
+@ref shaders-usage-multidraw "multidraw" or
+@ref shaders-usage-instancing "instancing" scenarios mentioned above, since
+each draw will most likely require a different texture. There are two options:
+
+- Upload the textures to subrectangles of a larger @ref GL::Texture2D and
+ then specify @ref Shaders::TextureTransformationUniform::offset and
+ @relativeref{Shaders::TextureTransformationUniform,rotationScaling} for
+ each draw, or in case of an instanced draw supply an instanced
+ @relativeref{Shaders::PhongGL,TextureOffset} attribute and have a global
+ scale set for all instanced via
+ @relativeref{Shaders::PhongGL,setTextureMatrix()}.
+- Enable @relativeref{Shaders::PhongGL,Flag::TextureArrays} in the shader
+ (not available on OpenGL ES 2.0 or WebGL 1.0), upload the textures to
+ slices of a @ref GL::Texture2DArray and specify
+ @ref Shaders::TextureTransformationUniform::layer for each draw, or in case
+ of an instanced draw supply a layer in an instanced
+ @relativeref{Shaders::PhongGL,TextureOffsetLayer} attribute.
+
+While with a @ref GL::Texture2D you may hit texture size limits (not to mention
+you possible issues with materials that relied on a certain wrapping mode),
+@ref GL::Texture2DArray is generally able to contain a lot more data, however
+all slices have to be of the same size. You can also combine the two approaches
+and pack differently sized textures to slices of a texture array and then set
+both offset/scale and a layer per-draw.
+
+The following snippet shows a multi-draw setup with a different texture array
+layer used by each draw. While the projection, transformation, draw material
+and light buffers are the same as before, there's a new per-draw
+@ref Shaders::TextureTransformationUniform buffer supplying the layer
+information:
+
+@snippet MagnumShaders-gl.cpp shaders-texture-arrays
+
+While the primary use case of texture arrays is with uniform buffers and
+multidraw, they work in the classic uniform workflow as well --- use
+@relativeref{Shaders::PhongGL,setTextureLayer()} there instead.
@section shaders-generic Generic vertex attributes and framebuffer attachments
@@ -81,28 +293,29 @@ Many shaders share the same vertex attribute definitions, such as positions,
normals, texture coordinates etc. It's thus possible to configure the mesh
for a *generic* shader and then render it with any compatible shader.
Definition of all generic attributes is available in the
-@ref Shaders::GenericGL class. Configuration of the above mesh using generic
-attributes could then look like this:
+@ref Shaders::GenericGL class. Setup of the mesh @ref shaders-usage "shown above"
+using generic attributes could then look like this:
@snippet MagnumShaders-gl.cpp shaders-generic
-Note that in this particular case both configurations are equivalent, because
-@ref Shaders::PhongGL also uses generic vertex attribute definitions. Then you
-can render the mesh using @ref Shaders::PhongGL shader like above, or use for
-example @ref Shaders::FlatGL3D or even @ref Shaders::MeshVisualizerGL3D with
-the same mesh reconfiguration. The unused attributes will be simply ignored.
+Note that in this particular case both setups are equivalent, because
+@ref Shaders::PhongGL attribute definitions are just aliases to the generic
+ones. Then you can render the mesh using the @ref Shaders::PhongGL shader like
+above, or use for example @ref Shaders::FlatGL3D or even
+@ref Shaders::MeshVisualizerGL3D with the same mesh reconfiguration. The unused
+attributes will be simply ignored.
@snippet MagnumShaders-gl.cpp shaders-meshvisualizer
The @ref MeshTools::compile() utility configures meshes using generic vertex
-attribute definitions to make them usable with any shader.
-
-Besides vertex attributes, the @ref Shaders::GenericGL contains generic
-definitions for framebuffer outputs as well --- in many cases a shader has just
-one (color) output, but some shaders such as @ref Shaders::FlatGL or
-@ref Shaders::PhongGL offer an object ID output as well. A setup equivalent to
-what's done in Flat shader's @ref Shaders-FlatGL-object-id but using the
-generic definitions would look like this:
+attribute definitions to make them usable with any builtin shader.
+
+Besides vertex attributes, @ref Shaders::GenericGL contains generic definitions
+for framebuffer outputs as well --- in many cases a shader has just one (color)
+output, but some shaders such as @ref Shaders::FlatGL or @ref Shaders::PhongGL
+offer an object ID output as well. A setup equivalent to what's done in Flat
+shader's @ref Shaders-FlatGL-object-id but using the generic definitions would
+look like this:
@snippet MagnumShaders-gl.cpp shaders-generic-object-id
*/
diff --git a/doc/snippets/MagnumShaders-gl.cpp b/doc/snippets/MagnumShaders-gl.cpp
index 96177ac94..0489a52a2 100644
--- a/doc/snippets/MagnumShaders-gl.cpp
+++ b/doc/snippets/MagnumShaders-gl.cpp
@@ -35,6 +35,7 @@
#include "Magnum/GL/DefaultFramebuffer.h"
#include "Magnum/GL/Framebuffer.h"
#include "Magnum/GL/Mesh.h"
+#include "Magnum/GL/MeshView.h"
#include "Magnum/GL/Shader.h"
#include "Magnum/GL/Renderbuffer.h"
#include "Magnum/GL/RenderbufferFormat.h"
@@ -54,6 +55,16 @@
#include "Magnum/Shaders/VertexColorGL.h"
#include "Magnum/Trade/LightData.h"
+#ifndef MAGNUM_TARGET_GLES2
+#include "Magnum/GL/TextureArray.h"
+#include "Magnum/Shaders/DistanceFieldVector.h"
+#include "Magnum/Shaders/Flat.h"
+#include "Magnum/Shaders/Generic.h"
+#include "Magnum/Shaders/MeshVisualizer.h"
+#include "Magnum/Shaders/Phong.h"
+#include "Magnum/Shaders/Vector.h"
+#endif
+
#define DOXYGEN_IGNORE(...) __VA_ARGS__
using namespace Magnum;
@@ -86,29 +97,241 @@ mesh.addVertexBuffer(vertices, 0,
//...
;
/* [shaders-setup] */
+}
+#endif
-/* [shaders-rendering] */
-Matrix4 transformationMatrix, projectionMatrix;
-GL::Texture2D diffuseTexture, specularTexture;
+{
+GL::Mesh mesh;
+/* [shaders-classic] */
+Matrix4 transformationMatrix{DOXYGEN_IGNORE()}, projectionMatrix{DOXYGEN_IGNORE()};
-Shaders::PhongGL shader{Shaders::PhongGL::Flag::DiffuseTexture};
-shader.bindDiffuseTexture(diffuseTexture)
+Shaders::PhongGL shader;
+shader
.setTransformationMatrix(transformationMatrix)
+ .setProjectionMatrix(projectionMatrix)
.setNormalMatrix(transformationMatrix.normalMatrix())
+ .setDiffuseColor(0x2f83cc_rgbf)
+ .setLightColors({0xe9ecae_rgbf})
+ .draw(mesh);
+/* [shaders-classic] */
+}
+
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix4 transformationMatrix, projectionMatrix;
+/* [shaders-ubo] */
+GL::Buffer projectionUniform, lightUniform, materialUniform,
+ transformationUniform, drawUniform;
+projectionUniform.setData({
+ Shaders::ProjectionUniform3D{}
+ .setProjectionMatrix(projectionMatrix)
+});
+lightUniform.setData({
+ Shaders::PhongLightUniform{}
+ .setColor(0xe9ecae_rgbf)
+});
+materialUniform.setData({
+ Shaders::PhongMaterialUniform{}
+ .setDiffuseColor(0x2f83cc_rgbf)
+});
+transformationUniform.setData({
+ Shaders::TransformationUniform3D{}
+ .setTransformationMatrix(transformationMatrix)
+});
+drawUniform.setData({
+ Shaders::PhongDrawUniform{}
+ .setNormalMatrix(transformationMatrix.normalMatrix())
+});
+
+Shaders::PhongGL shader{Shaders::PhongGL::Flag::UniformBuffers};
+shader
+ .bindProjectionBuffer(projectionUniform)
+ .bindLightBuffer(lightUniform)
+ .bindMaterialBuffer(materialUniform)
+ .bindTransformationBuffer(transformationUniform)
+ .bindDrawBuffer(drawUniform)
+ .draw(mesh);
+/* [shaders-ubo] */
+}
+
+{
+GL::Buffer projectionUniform, transformationUniform, drawUniform, lightUniform,
+ materialUniform;
+/* [shaders-multi] */
+GL::Mesh redCone{DOXYGEN_IGNORE()}, yellowCube{DOXYGEN_IGNORE()}, redSphere{DOXYGEN_IGNORE()};
+Matrix4 redConeTransformation{DOXYGEN_IGNORE()},
+ yellowCubeTransformation{DOXYGEN_IGNORE()},
+ redSphereTransformation{DOXYGEN_IGNORE()};
+
+materialUniform.setData({
+ Shaders::PhongMaterialUniform{}
+ .setDiffuseColor(0xcd3431_rgbf),
+ Shaders::PhongMaterialUniform{}
+ .setDiffuseColor(0xc7cf2f_rgbf),
+});
+transformationUniform.setData({
+ Shaders::TransformationUniform3D{}
+ .setTransformationMatrix(redConeTransformation),
+ Shaders::TransformationUniform3D{}
+ .setTransformationMatrix(yellowCubeTransformation),
+ Shaders::TransformationUniform3D{}
+ .setTransformationMatrix(redSphereTransformation),
+});
+drawUniform.setData({
+ Shaders::PhongDrawUniform{}
+ .setNormalMatrix(redConeTransformation.normalMatrix())
+ .setMaterialId(0),
+ Shaders::PhongDrawUniform{}
+ .setNormalMatrix(yellowCubeTransformation.normalMatrix())
+ .setMaterialId(1),
+ Shaders::PhongDrawUniform{}
+ .setNormalMatrix(redSphereTransformation.normalMatrix())
+ .setMaterialId(0),
+});
+
+/* One light, two materials, three draws */
+Shaders::PhongGL shader{Shaders::PhongGL::Flag::UniformBuffers, 1, 2, 3};
+shader
+ .bindProjectionBuffer(projectionUniform)
+ .bindTransformationBuffer(transformationUniform)
+ .bindDrawBuffer(drawUniform)
+ .bindLightBuffer(lightUniform)
+ .bindMaterialBuffer(materialUniform)
+ .setDrawOffset(0)
+ .draw(redCone)
+ .setDrawOffset(1)
+ .draw(yellowCube)
+ .setDrawOffset(2)
+ .draw(redSphere);
+/* [shaders-multi] */
+}
+
+{
+GL::Mesh mesh;
+/* [shaders-multidraw] */
+GL::MeshView redConeView{DOXYGEN_IGNORE(mesh)}, yellowCubeView{DOXYGEN_IGNORE(mesh)}, redSphereView{DOXYGEN_IGNORE(mesh)};
+DOXYGEN_IGNORE()
+
+/* One light, two materials, three draws; with multidraw enabled */
+Shaders::PhongGL shader{Shaders::PhongGL::Flag::MultiDraw, 1, 2, 3};
+shader
+ DOXYGEN_IGNORE()
+ .draw({redConeView, yellowCubeView, redSphereView});
+/* [shaders-multidraw] */
+}
+#endif
+
+{
+Matrix4 projectionMatrix;
+/* [shaders-instancing] */
+Matrix4 redSphereTransformation{DOXYGEN_IGNORE()},
+ yellowSphereTransformation{DOXYGEN_IGNORE()},
+ greenSphereTransformation{DOXYGEN_IGNORE()};
+
+struct {
+ Matrix4 transformationMatrix;
+ Matrix3x3 normalMatrix;
+ Color3 color;
+} instanceData[]{
+ {redSphereTransformation,
+ redSphereTransformation.normalMatrix(),
+ 0xcd3431_rgbf},
+ {yellowSphereTransformation,
+ yellowSphereTransformation.normalMatrix(),
+ 0xc7cf2f_rgbf},
+ {greenSphereTransformation,
+ greenSphereTransformation.normalMatrix(),
+ 0x3bd267_rgbf},
+};
+
+GL::Mesh sphereInstanced{DOXYGEN_IGNORE()};
+sphereInstanced.addVertexBufferInstanced(GL::Buffer{instanceData}, 1, 0,
+ Shaders::PhongGL::TransformationMatrix{},
+ Shaders::PhongGL::NormalMatrix{},
+ Shaders::PhongGL::Color3{});
+sphereInstanced.setInstanceCount(3);
+
+Shaders::PhongGL shader{Shaders::PhongGL::Flag::InstancedTransformation|
+ Shaders::PhongGL::Flag::VertexColor};
+shader
.setProjectionMatrix(projectionMatrix)
+ DOXYGEN_IGNORE()
+ .draw(sphereInstanced);
+/* [shaders-instancing] */
+}
+
+{
+GL::Mesh mesh;
+/* [shaders-textures] */
+GL::Texture2D diffuseTexture;
+DOXYGEN_IGNORE()
+
+Shaders::PhongGL shader{Shaders::PhongGL::Flag::DiffuseTexture};
+shader.bindDiffuseTexture(diffuseTexture)
+ DOXYGEN_IGNORE()
.draw(mesh);
-/* [shaders-rendering] */
+/* [shaders-textures] */
+}
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+GL::MeshView redConeView{DOXYGEN_IGNORE(mesh)}, yellowCubeView{DOXYGEN_IGNORE(mesh)}, redSphereView{DOXYGEN_IGNORE(mesh)};
+/* [shaders-texture-arrays] */
+ImageView2D coneDiffuse{DOXYGEN_IGNORE({}, {})}, cubeDiffuse{DOXYGEN_IGNORE({}, {})}, sphereDiffuse{DOXYGEN_IGNORE({}, {})};
+
+GL::Texture2DArray diffuseTexture;
+diffuseTexture
+ DOXYGEN_IGNORE()
+ /* Assuming all iamges have the same format and size */
+ .setStorage(1, GL::textureFormat(coneDiffuse.format()),
+ {coneDiffuse.size(), 3})
+ .setSubImage(0, {}, coneDiffuse)
+ .setSubImage(1, {}, cubeDiffuse)
+ .setSubImage(2, {}, sphereDiffuse);
+
+GL::Buffer textureTransformationUniform;
+textureTransformationUniform.setData({
+ Shaders::TextureTransformationUniform{}
+ .setLayer(0),
+ Shaders::TextureTransformationUniform{}
+ .setLayer(1),
+ Shaders::TextureTransformationUniform{}
+ .setLayer(2),
+});
+
+Shaders::PhongGL shader{
+ Shaders::PhongGL::Flag::MultiDraw|
+ Shaders::PhongGL::Flag::DiffuseTexture|
+ Shaders::PhongGL::Flag::TextureArrays,
+ 1, 2, 3};
+shader
+ DOXYGEN_IGNORE()
+ .bindDiffuseTexture(diffuseTexture)
+ .bindTextureTransformationBuffer(textureTransformationUniform)
+ .draw({redConeView, yellowCubeView, redSphereView});
+/* [shaders-texture-arrays] */
+}
+#endif
+
+{
+GL::Buffer vertices;
+GL::Mesh mesh;
/* [shaders-generic] */
mesh.addVertexBuffer(vertices, 0,
Shaders::GenericGL3D::Position{},
Shaders::GenericGL3D::Normal{},
Shaders::GenericGL3D::TextureCoordinates{});
/* [shaders-generic] */
+}
+{
+GL::Mesh mesh;
+Matrix4 transformationMatrix, projectionMatrix;
/* [shaders-meshvisualizer] */
-Shaders::MeshVisualizerGL3D visualizerShader{Shaders::MeshVisualizerGL3D::Flag::Wireframe};
-visualizerShader
+Shaders::MeshVisualizerGL3D shader{Shaders::MeshVisualizerGL3D::Flag::Wireframe};
+shader
.setColor(0x2f83cc_rgbf)
.setWireframeColor(0xdcdcdc_rgbf)
.setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
@@ -118,6 +341,9 @@ visualizerShader
/* [shaders-meshvisualizer] */
}
+/* internal compiler error: in gimplify_init_constructor, at gimplify.c:4271
+ on GCC 4.8 in the [60] array */
+#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [DistanceFieldVectorGL-usage1] */
struct Vertex {
@@ -150,12 +376,51 @@ Shaders::DistanceFieldVectorGL2D shader;
shader.setColor(0x2f83cc_rgbf)
.setOutlineColor(0xdcdcdc_rgbf)
.setOutlineRange(0.6f, 0.4f)
- .bindVectorTexture(texture)
.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
+ .bindVectorTexture(texture)
.draw(mesh);
/* [DistanceFieldVectorGL-usage2] */
}
+#endif
+
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix3 transformationMatrix, projectionMatrix;
+GL::Texture2D texture;
+/* [DistanceFieldVectorGL-ubo] */
+GL::Buffer projectionTransformationUniform, materialUniform, drawUniform;
+projectionTransformationUniform.setData({
+ Shaders::TransformationProjectionUniform2D{}
+ .setTransformationProjectionMatrix(transformationMatrix*projectionMatrix)
+});
+materialUniform.setData({
+ Shaders::DistanceFieldVectorMaterialUniform{}
+ .setColor(0x2f83cc_rgbf)
+ .setOutlineColor(0xdcdcdc_rgbf)
+ .setOutlineRange(0.6f, 0.4f)
+});
+drawUniform.setData({
+ Shaders::DistanceFieldVectorDrawUniform{}
+ .setMaterialId(0)
+});
+
+Shaders::DistanceFieldVectorGL2D shader{
+ Shaders::DistanceFieldVectorGL2D::Flag::UniformBuffers
+};
+shader
+ .bindTransformationProjectionBuffer(projectionTransformationUniform)
+ .bindMaterialBuffer(materialUniform)
+ .bindDrawBuffer(drawUniform)
+ .bindVectorTexture(texture)
+ .draw(mesh);
+/* [DistanceFieldVectorGL-ubo] */
+}
+#endif
+/* internal compiler error: in gimplify_init_constructor, at gimplify.c:4271
+ on GCC 4.8 in the [60] array */
+#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [FlatGL-usage-colored1] */
struct Vertex {
@@ -217,6 +482,7 @@ shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
.draw(mesh);
/* [FlatGL-usage-textured2] */
}
+#endif
#ifndef MAGNUM_TARGET_GLES2
{
@@ -274,6 +540,35 @@ mesh.setInstanceCount(Containers::arraySize(instanceData))
/* [FlatGL-usage-instancing] */
}
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix4 transformationMatrix, projectionMatrix;
+/* [FlatGL-ubo] */
+GL::Buffer projectionTransformationUniform, materialUniform, drawUniform;
+projectionTransformationUniform.setData({
+ Shaders::TransformationProjectionUniform3D{}
+ .setTransformationProjectionMatrix(transformationMatrix*projectionMatrix)
+});
+materialUniform.setData({
+ Shaders::FlatMaterialUniform{}
+ .setColor(0x2f83cc_rgbf)
+});
+drawUniform.setData({
+ Shaders::FlatDrawUniform{}
+ .setMaterialId(0)
+});
+
+Shaders::FlatGL3D shader{Shaders::FlatGL3D::Flag::UniformBuffers};
+shader
+ .bindTransformationProjectionBuffer(projectionTransformationUniform)
+ .bindMaterialBuffer(materialUniform)
+ .bindDrawBuffer(drawUniform)
+ .draw(mesh);
+/* [FlatGL-ubo] */
+}
+#endif
+
{
struct: GL::AbstractShaderProgram {
void foo() {
@@ -320,6 +615,9 @@ mesh.setInstanceCount(Containers::arraySize(instanceData))
/* [PhongGL-usage-instancing] */
}
+/* internal compiler error: in gimplify_init_constructor, at gimplify.c:4271
+ on GCC 4.8 in the [60] array */
+#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [MeshVisualizerGL3D-usage-geom1] */
struct Vertex {
@@ -463,6 +761,47 @@ shader.setColorMapTransformation(0.0f, 1.0f/Math::max(objectIds))
}
#endif
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix4 transformationMatrix, projectionMatrix;
+GL::Texture2D texture;
+/* [MeshVisualizerGL3D-ubo] */
+GL::Buffer projectionUniform, materialUniform, transformationUniform,
+ drawUniform;
+projectionUniform.setData({
+ Shaders::ProjectionUniform3D{}
+ .setProjectionMatrix(projectionMatrix)
+});
+materialUniform.setData({
+ Shaders::MeshVisualizerMaterialUniform{}
+ .setColor(0x2f83cc_rgbf)
+ .setWireframeColor(0xdcdcdc_rgbf)
+});
+transformationUniform.setData({
+ Shaders::TransformationUniform3D{}
+ .setTransformationMatrix(transformationMatrix)
+});
+drawUniform.setData({
+ Shaders::MeshVisualizerDrawUniform3D{}
+ .setMaterialId(0)
+});
+
+Shaders::MeshVisualizerGL3D shader{
+ Shaders::MeshVisualizerGL3D::Flag::Wireframe|
+ Shaders::MeshVisualizerGL3D::Flag::UniformBuffers
+};
+shader
+ .setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
+ .bindProjectionBuffer(projectionUniform)
+ .bindMaterialBuffer(materialUniform)
+ .bindTransformationBuffer(transformationUniform)
+ .bindDrawBuffer(drawUniform)
+ .draw(mesh);
+/* [MeshVisualizerGL3D-ubo] */
+}
+#endif
+
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [PhongGL-usage-colored1] */
@@ -580,6 +919,48 @@ shader.bindTextures(&diffuseAlphaTexture, &diffuseAlphaTexture, nullptr, nullptr
/* [PhongGL-usage-alpha] */
}
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix4 transformationMatrix, projectionMatrix;
+GL::Texture2D texture;
+/* [PhongGL-ubo] */
+GL::Buffer projectionUniform, lightUniform, materialUniform,
+ transformationUniform, drawUniform;
+projectionUniform.setData({
+ Shaders::ProjectionUniform3D{}
+ .setProjectionMatrix(projectionMatrix)
+});
+lightUniform.setData({
+ Shaders::PhongLightUniform{}
+});
+materialUniform.setData({
+ Shaders::PhongMaterialUniform{}
+ .setDiffuseColor(0x2f83cc_rgbf)
+ .setShininess(200.0f)
+});
+transformationUniform.setData({
+ Shaders::TransformationUniform3D{}
+ .setTransformationMatrix(transformationMatrix)
+});
+drawUniform.setData({
+ Shaders::PhongDrawUniform{}
+ .setNormalMatrix(transformationMatrix.normalMatrix())
+ .setMaterialId(0)
+});
+
+Shaders::PhongGL shader{Shaders::PhongGL::Flag::UniformBuffers};
+shader
+ .bindProjectionBuffer(projectionUniform)
+ .bindLightBuffer(lightUniform)
+ .bindMaterialBuffer(materialUniform)
+ .bindTransformationBuffer(transformationUniform)
+ .bindDrawBuffer(drawUniform)
+ .draw(mesh);
+/* [PhongGL-ubo] */
+}
+#endif
+
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [VectorGL-usage1] */
@@ -611,7 +992,40 @@ shader.setColor(0x2f83cc_rgbf)
.draw(mesh);
/* [VectorGL-usage2] */
}
+#endif
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix3 transformationMatrix, projectionMatrix;
+GL::Texture2D texture;
+/* [VectorGL-ubo] */
+GL::Buffer projectionTransformationUniform, materialUniform, drawUniform;
+projectionTransformationUniform.setData({
+ Shaders::TransformationProjectionUniform2D{}
+ .setTransformationProjectionMatrix(transformationMatrix*projectionMatrix)
+});
+materialUniform.setData({
+ Shaders::VectorMaterialUniform{}
+ .setColor(0x2f83cc_rgbf)
+});
+drawUniform.setData({
+ Shaders::VectorDrawUniform{}
+ .setMaterialId(0)
+});
+
+Shaders::VectorGL2D shader{Shaders::VectorGL2D::Flag::UniformBuffers};
+shader
+ .bindTransformationProjectionBuffer(projectionTransformationUniform)
+ .bindMaterialBuffer(materialUniform)
+ .bindDrawBuffer(drawUniform)
+ .bindVectorTexture(texture)
+ .draw(mesh);
+/* [VectorGL-ubo] */
+}
+#endif
+
+#if !defined(__GNUC__) || defined(__clang__) || __GNUC__*100 + __GNUC_MINOR__ >= 500
{
/* [VertexColorGL-usage1] */
struct Vertex {
@@ -643,4 +1057,23 @@ shader.setTransformationProjectionMatrix(projectionMatrix*transformationMatrix)
}
#endif
+#ifndef MAGNUM_TARGET_GLES2
+{
+GL::Mesh mesh;
+Matrix4 transformationMatrix, projectionMatrix;
+/* [VertexColorGL-ubo] */
+GL::Buffer projectionTransformationUniform;
+projectionTransformationUniform.setData({
+ Shaders::TransformationProjectionUniform3D{}
+ .setTransformationProjectionMatrix(transformationMatrix*projectionMatrix)
+});
+
+Shaders::VertexColorGL3D shader{Shaders::VertexColorGL3D::Flag::UniformBuffers};
+shader
+ .bindTransformationProjectionBuffer(projectionTransformationUniform)
+ .draw(mesh);
+/* [VertexColorGL-ubo] */
+}
+#endif
+
}
diff --git a/src/Magnum/Shaders/DistanceFieldVectorGL.h b/src/Magnum/Shaders/DistanceFieldVectorGL.h
index abd2e926c..84e383bff 100644
--- a/src/Magnum/Shaders/DistanceFieldVectorGL.h
+++ b/src/Magnum/Shaders/DistanceFieldVectorGL.h
@@ -80,6 +80,39 @@ Common rendering setup:
@snippet MagnumShaders-gl.cpp DistanceFieldVectorGL-usage2
+@section Shaders-DistanceFieldVectorGL-ubo Uniform buffers
+
+See @ref shaders-usage-ubo for a high-level overview that applies to all
+shaders. In this particular case, because the shader doesn't need a separate
+projection and transformation matrix, a combined one is supplied via a
+@ref TransformationProjectionUniform2D / @ref TransformationProjectionUniform3D
+buffer. To maximize use of the limited uniform buffer memory, materials are
+supplied separately in a @ref DistanceFieldVectorMaterialUniform buffer and
+then referenced via @relativeref{DistanceFieldVectorDrawUniform,materialId}
+from a @ref DistanceFieldVectorDrawUniform; for optional texture transformation
+a per-draw @ref TextureTransformationUniform can be supplied as well. A uniform
+buffer setup equivalent to the above would look like this:
+
+@snippet MagnumShaders-gl.cpp DistanceFieldVectorGL-ubo
+
+For a multidraw workflow enable @ref Flag::MultiDraw, supply desired material
+and draw count in the @ref DistanceFieldVectorGL(Flags, UnsignedInt, UnsignedInt)
+constructor and specify material references and texture offsets for every draw.
+Texture arrays aren't currently supported for this shader. Besides that, the
+usage is similar for all shaders, see @ref shaders-usage-multidraw for an
+example.
+
+@requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} for uniform
+ buffers.
+@requires_gl46 Extension @gl_extension{ARB,shader_draw_parameters} for
+ multidraw.
+@requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
+@requires_webgl20 Uniform buffers are not available in WebGL 1.0.
+@requires_es_extension Extension @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
+ (unlisted) for multidraw.
+@requires_webgl_extension Extension @webgl_extension{ANGLE,multi_draw} for
+ multidraw.
+
@see @ref shaders, @ref DistanceFieldVectorGL2D, @ref DistanceFieldVectorGL3D
@todo Use fragment shader derivations to have proper smoothness in perspective/
large zoom levels, make it optional as it might have negative performance
diff --git a/src/Magnum/Shaders/FlatGL.h b/src/Magnum/Shaders/FlatGL.h
index d57785615..caf4dd6b0 100644
--- a/src/Magnum/Shaders/FlatGL.h
+++ b/src/Magnum/Shaders/FlatGL.h
@@ -156,6 +156,41 @@ color to a mesh:
@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL
1.0.
+@section Shaders-FlatGL-ubo Uniform buffers
+
+See @ref shaders-usage-ubo for a high-level overview that applies to all
+shaders. In this particular case, because the shader doesn't need a separate
+projection and transformation matrix, a combined one is supplied via a
+@ref TransformationProjectionUniform2D / @ref TransformationProjectionUniform3D
+buffer. To maximize use of the limited uniform buffer memory, materials are
+supplied separately in a @ref FlatMaterialUniform buffer and then referenced
+via @relativeref{FlatDrawUniform,materialId} from a @ref FlatDrawUniform; for
+optional texture transformation a per-draw @ref TextureTransformationUniform
+can be supplied as well. A uniform buffer setup equivalent to the
+@ref Shaders-FlatGL-colored "colored case at the top" would look like this:
+
+@snippet MagnumShaders-gl.cpp FlatGL-ubo
+
+For a multidraw workflow enable @ref Flag::MultiDraw (and possibly
+@ref Flag::TextureArrays), supply desired material and draw count in the
+@ref FlatGL(Flags, UnsignedInt, UnsignedInt) constructor and specify material
+references and texture offsets/layers for every draw. The usage is similar for
+all shaders, see @ref shaders-usage-multidraw for an example.
+
+@requires_gl30 Extension @gl_extension{EXT,texture_array} for texture arrays.
+@requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} for uniform
+ buffers.
+@requires_gl46 Extension @gl_extension{ARB,shader_draw_parameters} for
+ multidraw.
+@requires_gles30 Neither texture arrays nor uniform buffers are available in
+ OpenGL ES 2.0.
+@requires_webgl20 Neither texture arrays nor uniform buffers are available in
+ WebGL 1.0.
+@requires_es_extension Extension @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
+ (unlisted) for multidraw.
+@requires_webgl_extension Extension @webgl_extension{ANGLE,multi_draw} for
+ multidraw.
+
@see @ref shaders, @ref FlatGL2D, @ref FlatGL3D
*/
template class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram {
diff --git a/src/Magnum/Shaders/MeshVisualizerGL.h b/src/Magnum/Shaders/MeshVisualizerGL.h
index fccf0cd88..6d8967594 100644
--- a/src/Magnum/Shaders/MeshVisualizerGL.h
+++ b/src/Magnum/Shaders/MeshVisualizerGL.h
@@ -781,6 +781,37 @@ non-indexed @ref MeshPrimitive::Triangles.
@requires_gles `gl_PrimitiveID` is not available in WebGL.
@requires_webgl20 `gl_VertexID` is not available in WebGL 1.0.
+@section Shaders-MeshVisualizerGL3D-ubo Uniform buffers
+
+See @ref shaders-usage-ubo for a high-level overview that applies to all
+shaders. In this particular case, the shader needs a separate
+@ref ProjectionUniform3D and @ref TransformationUniform3D buffer. To maximize
+use of the limited uniform buffer memory, materials are supplied separately in
+a @ref MeshVisualizerMaterialUniform and then referenced via
+@relativeref{MeshVisualizerDrawUniform3D,materialId} from a
+@ref MeshVisualizerDrawUniform3D. A uniform buffer setup equivalent to the
+@ref Shaders-MeshVisualizerGL3D-wireframe "wireframe case at the top" would
+look like this --- note that @ref setViewportSize() is an immediate uniform
+here as well, as it's assumed to be set globally and rarely changed:
+
+@snippet MagnumShaders-gl.cpp MeshVisualizerGL3D-ubo
+
+For a multidraw workflow enable @ref Flag::MultiDraw, supply desired material
+and draw count in the @ref MeshVisualizerGL3D(Flags, UnsignedInt, UnsignedInt)
+constructor and specify material references for every draw. The usage is
+similar for all shaders, see @ref shaders-usage-multidraw for an example.
+
+@requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} for uniform
+ buffers.
+@requires_gl46 Extension @gl_extension{ARB,shader_draw_parameters} for
+ multidraw.
+@requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
+@requires_webgl20 Uniform buffers are not available in WebGL 1.0.
+@requires_es_extension Extension @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
+ (unlisted) for multidraw.
+@requires_webgl_extension Extension @webgl_extension{ANGLE,multi_draw} for
+ multidraw.
+
@see @ref shaders, @ref MeshVisualizerGL2D
@todo Understand and add support wireframe width/smoothness without GS
*/
diff --git a/src/Magnum/Shaders/PhongGL.h b/src/Magnum/Shaders/PhongGL.h
index 9c34a3b2d..89da15b7f 100644
--- a/src/Magnum/Shaders/PhongGL.h
+++ b/src/Magnum/Shaders/PhongGL.h
@@ -248,6 +248,44 @@ well to ensure lighting works:
@requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays} in WebGL
1.0.
+@section Shaders-PhongGL-ubo Uniform buffers
+
+See @ref shaders-usage-ubo for a high-level overview that applies to all
+shaders. In this particular case, the shader needs a separate
+@ref ProjectionUniform3D and @ref TransformationUniform3D buffer, lights are
+supplied via a @ref PhongLightUniform. To maximize use of the limited uniform
+buffer memory, materials are supplied separately in a @ref PhongMaterialUniform
+buffer and then referenced via @relativeref{PhongDrawUniform,materialId} from a
+@ref PhongDrawUniform; for optional texture transformation a per-draw
+@ref TextureTransformationUniform can be supplied as well. A uniform buffer
+setup equivalent to the @ref Shaders-PhongGL-colored "colored case at the top",
+with one default light, would look like this:
+
+@snippet MagnumShaders-gl.cpp PhongGL-ubo
+
+For a multidraw workflow enable @ref Flag::MultiDraw (and possibly
+@ref Flag::TextureArrays) and supply desired light, material and draw count in
+the @ref PhongGL(Flags, UnsignedInt, UnsignedInt, UnsignedInt) constructor. For
+every draw then specify material references and texture offsets/layers, it's
+also possible to perform per-draw light culling by supplying a subrange into
+the @ref PhongLightUniform array using @ref PhongDrawUniform::lightOffset and
+@relativeref{PhongDrawUniform,lightCount}. Besides that, the usage is similar
+for all shaders, see @ref shaders-usage-multidraw for an example.
+
+@requires_gl30 Extension @gl_extension{EXT,texture_array} for texture arrays.
+@requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} for uniform
+ buffers.
+@requires_gl46 Extension @gl_extension{ARB,shader_draw_parameters} for
+ multidraw.
+@requires_gles30 Neither texture arrays nor uniform buffers are available in
+ OpenGL ES 2.0.
+@requires_webgl20 Neither texture arrays nor uniform buffers are available in
+ WebGL 1.0.
+@requires_es_extension Extension @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
+ (unlisted) for multidraw.
+@requires_webgl_extension Extension @webgl_extension{ANGLE,multi_draw} for
+ multidraw.
+
@see @ref shaders
*/
class MAGNUM_SHADERS_EXPORT PhongGL: public GL::AbstractShaderProgram {
diff --git a/src/Magnum/Shaders/VectorGL.h b/src/Magnum/Shaders/VectorGL.h
index 977ec4a26..ad3160304 100644
--- a/src/Magnum/Shaders/VectorGL.h
+++ b/src/Magnum/Shaders/VectorGL.h
@@ -78,6 +78,39 @@ Common rendering setup:
@snippet MagnumShaders-gl.cpp VectorGL-usage2
+@section Shaders-VectorGL-ubo Uniform buffers
+
+See @ref shaders-usage-ubo for a high-level overview that applies to all
+shaders. In this particular case, because the shader doesn't need a separate
+projection and transformation matrix, a combined one is supplied via a
+@ref TransformationProjectionUniform2D / @ref TransformationProjectionUniform3D
+buffer. To maximize use of the limited uniform buffer memory, materials are
+supplied separately in a @ref VectorMaterialUniform buffer and then referenced
+via @relativeref{VectorDrawUniform,materialId} from a @ref VectorDrawUniform;
+for optional texture transformation a per-draw
+@ref TextureTransformationUniform can be supplied as well. A uniform buffer
+setup equivalent to the above would look like this:
+
+@snippet MagnumShaders-gl.cpp VectorGL-ubo
+
+For a multidraw workflow enable @ref Flag::MultiDraw, supply desired material
+and draw count in the @ref VectorGL(Flags, UnsignedInt, UnsignedInt)
+constructor and specify material references and texture offsets for every draw.
+Texture arrays aren't currently supported for this shader. Besides that, the
+usage is similar for all shaders, see @ref shaders-usage-multidraw for an
+example.
+
+@requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} for uniform
+ buffers.
+@requires_gl46 Extension @gl_extension{ARB,shader_draw_parameters} for
+ multidraw.
+@requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
+@requires_webgl20 Uniform buffers are not available in WebGL 1.0.
+@requires_es_extension Extension @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
+ (unlisted) for multidraw.
+@requires_webgl_extension Extension @webgl_extension{ANGLE,multi_draw} for
+ multidraw.
+
@see @ref shaders, @ref VectorGL2D, @ref VectorGL3D
*/
template class MAGNUM_SHADERS_EXPORT VectorGL: public GL::AbstractShaderProgram {
diff --git a/src/Magnum/Shaders/VertexColorGL.h b/src/Magnum/Shaders/VertexColorGL.h
index 4379062cd..c71c9688b 100644
--- a/src/Magnum/Shaders/VertexColorGL.h
+++ b/src/Magnum/Shaders/VertexColorGL.h
@@ -79,6 +79,33 @@ Common rendering setup:
@snippet MagnumShaders-gl.cpp VertexColorGL-usage2
+@section Shaders-VertexColorGL-ubo Uniform buffers
+
+See @ref shaders-usage-ubo for a high-level overview that applies to all
+shaders. In this particular case, because the shader doesn't need a separate
+projection and transformation matrix, a combined one is supplied via a
+@ref TransformationProjectionUniform2D / @ref TransformationProjectionUniform3D
+buffer. This is also the only buffer supplied, as there are no other draw
+parameters. A uniform buffer setup equivalent to the above would look like
+this:
+
+@snippet MagnumShaders-gl.cpp VectorGL-ubo
+
+For a multidraw workflow enable @ref Flag::MultiDraw and supply desired draw
+count in the @ref VertexColorGL(Flags, UnsignedInt) constructor. The usage is
+similar for all shaders, see @ref shaders-usage-multidraw for an example.
+
+@requires_gl31 Extension @gl_extension{ARB,uniform_buffer_object} for uniform
+ buffers.
+@requires_gl46 Extension @gl_extension{ARB,shader_draw_parameters} for
+ multidraw.
+@requires_gles30 Uniform buffers are not available in OpenGL ES 2.0.
+@requires_webgl20 Uniform buffers are not available in WebGL 1.0.
+@requires_es_extension Extension @m_class{m-doc-external} [ANGLE_multi_draw](https://chromium.googlesource.com/angle/angle/+/master/extensions/ANGLE_multi_draw.txt)
+ (unlisted) for multidraw.
+@requires_webgl_extension Extension @webgl_extension{ANGLE,multi_draw} for
+ multidraw.
+
@see @ref shaders, @ref VertexColorGL2D, @ref VertexColorGL3D
*/
template class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram {