Browse Source

doc: document uniform buffer and multidraw support in builtin shaders.

pull/518/head
Vladimír Vondruš 5 years ago
parent
commit
1f2eef7b6a
  1. 3
      doc/changelog.dox
  2. 273
      doc/shaders.dox
  3. 451
      doc/snippets/MagnumShaders-gl.cpp
  4. 33
      src/Magnum/Shaders/DistanceFieldVectorGL.h
  5. 35
      src/Magnum/Shaders/FlatGL.h
  6. 31
      src/Magnum/Shaders/MeshVisualizerGL.h
  7. 38
      src/Magnum/Shaders/PhongGL.h
  8. 33
      src/Magnum/Shaders/VectorGL.h
  9. 27
      src/Magnum/Shaders/VertexColorGL.h

3
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

273
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
<b></b>
@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
*/

451
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
}

33
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

35
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<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT FlatGL: public GL::AbstractShaderProgram {

31
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
*/

38
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 {

33
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<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VectorGL: public GL::AbstractShaderProgram {

27
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<UnsignedInt dimensions> class MAGNUM_SHADERS_EXPORT VertexColorGL: public GL::AbstractShaderProgram {

Loading…
Cancel
Save