class
MeshMesh.
Contents
Mesh configuration
You have to specify at least primitive and vertex/index count using setPrimitive() and setCount(). Then fill your vertex buffers with data, add them to the mesh and specify shader attribute layout inside the buffers using addVertexBuffer(). You can also use MeshTools::
If you want indexed mesh, fill your index buffer with data and specify its layout using setIndexBuffer(). You can also use MeshTools::
There is also MeshTools::
Note that neither vertex buffers nor index buffer is managed (e.g. deleted on destruction) by the mesh, so you have to manage them on your own and ensure that they are available for whole mesh lifetime. On the other hand it allows you to use one buffer for more meshes (each mesh for example configured for different usage) or store data for more meshes in one buffer.
If vertex/index count or instance count is zero, the mesh is empty and no draw commands are issued when calling draw().
Example mesh configuration
Basic non-indexed mesh
/* Custom shader, needing only position data */ class MyShader: public GL::AbstractShaderProgram { public: typedef GL::Attribute<0, Vector3> Position; // ... }; /* Fill vertex buffer with position data */ Vector3 positions[30]{ // ... }; GL::Buffer vertexBuffer; vertexBuffer.setData(positions, GL::BufferUsage::StaticDraw); /* Configure the mesh, add vertex buffer */ GL::Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) .addVertexBuffer(vertexBuffer, 0, MyShader::Position{}) .setCount(30);
Interleaved vertex data
/* Non-indexed primitive with positions and normals */ Trade::MeshData3D plane = Primitives::planeSolid(); /* Fill a vertex buffer with interleaved position and normal data */ GL::Buffer buffer; buffer.setData(MeshTools::interleave(plane.positions(0), plane.normals(0)), GL::BufferUsage::StaticDraw); /* Configure the mesh, add the vertex buffer */ GL::Mesh mesh; mesh.setPrimitive(plane.primitive()) .setCount(plane.positions(0).size()) .addVertexBuffer(buffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{});
Indexed mesh
/* Custom shader */ class MyShader: public GL::AbstractShaderProgram { public: typedef GL::Attribute<0, Vector3> Position; // ... }; /* Fill vertex buffer with position data */ Vector3 positions[240]{ // ... }; GL::Buffer vertexBuffer; vertexBuffer.setData(positions, GL::BufferUsage::StaticDraw); /* Fill index buffer with index data */ UnsignedByte indices[75]{ // ... }; GL::Buffer indexBuffer; indexBuffer.setData(indices, GL::BufferUsage::StaticDraw); /* Configure the mesh, add both vertex and index buffer */ GL::Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) .setCount(75) .addVertexBuffer(vertexBuffer, 0, MyShader::Position{}) .setIndexBuffer(indexBuffer, 0, GL::MeshIndexType::UnsignedByte, 176, 229);
Or using MeshTools::
// Indexed primitive Trade::MeshData3D cube = Primitives::cubeSolid(); // Fill vertex buffer with interleaved position and normal data GL::Buffer vertexBuffer; vertexBuffer.setData(MeshTools::interleave(cube.positions(0), cube.normals(0)), GL::BufferUsage::StaticDraw); // Compress index data Containers::Array<char> indexData; MeshIndexType indexType; UnsignedInt indexStart, indexEnd; std::tie(indexData, indexType, indexStart, indexEnd) = MeshTools::compressIndices(cube.indices()); // Fill index buffer GL::Buffer indexBuffer; indexBuffer.setData(indexData, GL::BufferUsage::StaticDraw); // Configure the mesh, add both vertex and index buffer GL::Mesh mesh; mesh.setPrimitive(cube.primitive()) .setCount(cube.indices().size()) .addVertexBuffer(vertexBuffer, 0, Shaders::Phong::Position{}, Shaders::Phong::Normal{}) .setIndexBuffer(indexBuffer, 0, indexType, indexStart, indexEnd);
Or, if you plan to use the mesh with stock shaders, you can just use MeshTools::
Specific formats of vertex data
// Custom shader with colors specified as four floating-point values class MyShader: public GL::AbstractShaderProgram { public: typedef GL::Attribute<0, Vector3> Position; typedef GL::Attribute<1, Color4> Color; // ... }; /* Initial mesh configuration */ GL::Mesh mesh; mesh.setPrimitive(MeshPrimitive::Triangles) .setCount(30); /* Fill position buffer with positions specified as two-component XY (i.e., no Z component, which is meant to be always 0) */ Vector2 positions[30]{ // ... }; GL::Buffer positionBuffer; positionBuffer.setData(positions, GL::BufferUsage::StaticDraw); /* Specify layout of positions buffer -- only two components, unspecified Z component will be automatically set to 0 */ mesh.addVertexBuffer(positionBuffer, 0, MyShader::Position{MyShader::Position::Components::Two}); /* Fill color buffer with colors specified as four-byte BGRA (i.e., directly from a TGA file) */ UnsignedByte colors[4*30]{ // ... }; GL::Buffer colorBuffer; colorBuffer.setData(colors, GL::BufferUsage::StaticDraw); /* Specify color buffer layout -- BGRA, each component unsigned byte and we want to normalize them from [0, 255] to [0.0f, 1.0f] */ mesh.addVertexBuffer(colorBuffer, 0, MyShader::Color{ MyShader::Color::Components::BGRA, MyShader::Color::DataType::UnsignedByte, MyShader::Color::DataOption::Normalized});
Dynamically specified attributes
In some cases, for example when the shader code is fully generated at runtime, it's not possible to know attribute locations and types at compile time. In that case, there are overloads of addVertexBuffer() and addVertexBufferInstanced() that take DynamicAttribute instead of Attribute typedefs. Adding a RGB attribute at location 3 normalized from unsigned byte to float with one byte padding at the end could then look like this:
mesh.addVertexBuffer(colorBuffer, 0, 4, GL::DynamicAttribute{ GL::DynamicAttribute::Kind::GenericNormalized, 3, GL::DynamicAttribute::Components::Three, GL::DynamicAttribute::DataType::UnsignedByte});
Rendering meshes
Basic workflow is: bind specific framebuffer for drawing (if needed), set up respective shader (see AbstractShaderProgram documentation for more infromation) and call Mesh::
WebGL restrictions
WebGL puts some restrictions on vertex buffer layout, see addVertexBuffer() documentation for details.
Performance optimizations
If ARB_
If EXT_
If index range is specified in setIndexBuffer(), range-based version of drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also draw() for more information.
Base classes
- class AbstractObject
- Base for all OpenGL objects.
Public types
-
using IndexType = Magnum::
MeshIndexType deprecated - Index type.
Public static functions
- static auto maxElementIndex() -> Long
- Max supported index value.
- static auto maxElementsIndices() -> Int
- Max recommended index count.
- static auto maxElementsVertices() -> Int
- Max recommended vertex count.
-
static auto indexSize(Magnum::
MeshIndexType type) -> std:: size_t deprecated - Size of given mesh index type.
-
static auto wrap(GLuint id,
MeshPrimitive primitive = MeshPrimitive::
Triangles, ObjectFlags flags = {}) -> Mesh - Wrap existing OpenGL vertex array object.
- static auto wrap(GLuint id, ObjectFlags flags) -> Mesh
Constructors, destructors, conversion operators
-
Mesh(MeshPrimitive primitive = MeshPrimitive::
Triangles) explicit - Constructor.
-
Mesh(Magnum::
MeshPrimitive primitive) explicit - Mesh(NoCreateT) explicit noexcept
- Construct without creating the underlying OpenGL object.
- Mesh(const Mesh&) deleted
- Copying is not allowed.
- Mesh(Mesh&& other) noexcept
- Move constructor.
- ~Mesh()
- Destructor.
Public functions
- auto operator=(const Mesh&) -> Mesh& deleted
- Copying is not allowed.
- auto operator=(Mesh&& other) -> Mesh& noexcept
- Move assignment.
- auto id() const -> GLuint
- OpenGL vertex array ID.
- auto release() -> GLuint
- Release OpenGL object.
-
auto label() -> std::
string - Mesh label.
-
auto setLabel(const std::
string& label) -> Mesh& - Set mesh label.
-
template<std::auto setLabel(const char(&label)[size]) -> Mesh&
size_t size> - auto isIndexed() const -> bool
- Whether the mesh is indexed.
- auto indexType() const -> MeshIndexType
- Index type.
- auto indexTypeSize() const -> UnsignedInt
- Index type size.
-
auto indexSize() const -> std::
size_t deprecated - Index size.
- auto primitive() const -> MeshPrimitive
- Primitive type.
- auto setPrimitive(MeshPrimitive primitive) -> Mesh&
- Set primitive type.
-
auto setPrimitive(Magnum::
MeshPrimitive primitive) -> Mesh& - auto count() const -> Int
- Vertex/index count.
- auto setCount(Int count) -> Mesh&
- Set vertex/index count.
- auto baseVertex() const -> Int
- Base vertex.
- auto setBaseVertex(Int baseVertex) -> Mesh&
- Set base vertex.
- auto instanceCount() const -> Int
- Instance count.
- auto setInstanceCount(Int count) -> Mesh&
- Set instance count.
- auto baseInstance() const -> UnsignedInt
- Base instance.
- auto setBaseInstance(UnsignedInt baseInstance) -> Mesh&
- Set base instance.
-
template<class ... T>auto addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) -> Mesh&
- Add buffer with (interleaved) vertex attributes for use with given shader.
-
template<class ... T>auto addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) -> Mesh&
- Add instanced vertex buffer.
- auto addVertexBuffer(Buffer& buffer, GLintptr offset, GLsizei stride, const DynamicAttribute& attribute) -> Mesh&
- Add buffer with dynamic vertex attributes for use with given shader.
- auto addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, GLsizei stride, const DynamicAttribute& attribute) -> Mesh&
- Add buffer with dynamic vertex attributes for use with given shader.
- auto setIndexBuffer(Buffer& buffer, GLintptr offset, MeshIndexType type, UnsignedInt start, UnsignedInt end) -> Mesh&
- Set index buffer.
-
auto setIndexBuffer(Buffer& buffer,
GLintptr offset,
Magnum::
MeshIndexType type, UnsignedInt start, UnsignedInt end) -> Mesh& - auto setIndexBuffer(Buffer& buffer, GLintptr offset, MeshIndexType type) -> Mesh&
- Set index buffer.
-
auto setIndexBuffer(Buffer& buffer,
GLintptr offset,
Magnum::
MeshIndexType type) -> Mesh& - void draw(AbstractShaderProgram& shader)
- Draw the mesh.
- void draw(AbstractShaderProgram&& shader)
- void draw(AbstractShaderProgram& shader, TransformFeedback& xfb, UnsignedInt stream = 0)
- Draw the mesh with vertices coming out of transform feedback.
- void draw(AbstractShaderProgram&& shader, TransformFeedback& xfb, UnsignedInt stream = 0)
Typedef documentation
typedef Magnum:: MeshIndexType Magnum:: GL:: Mesh:: IndexType
Index type.
Function documentation
static Long Magnum:: GL:: Mesh:: maxElementIndex()
Max supported index value.
The result is cached, repeated queries don't result in repeated OpenGL calls. If extension ARB_0xffffffffu
).
static Int Magnum:: GL:: Mesh:: maxElementsIndices()
Max recommended index count.
The result is cached, repeated queries don't result in repeated OpenGL calls.
static Int Magnum:: GL:: Mesh:: maxElementsVertices()
Max recommended vertex count.
The result is cached, repeated queries don't result in repeated OpenGL calls.
static std:: size_t Magnum:: GL:: Mesh:: indexSize(Magnum:: MeshIndexType type)
Size of given mesh index type.
static Mesh Magnum:: GL:: Mesh:: wrap(GLuint id,
MeshPrimitive primitive = MeshPrimitive:: Triangles,
ObjectFlags flags = {})
Wrap existing OpenGL vertex array object.
Parameters | |
---|---|
id | OpenGL vertex array ID |
primitive | Primitive type |
flags | Object creation flags |
The id
is expected to be of an existing OpenGL vertex array object. Unlike vertex array created using constructor, the OpenGL object is by default not deleted on destruction, use flags
for different behavior.
static Mesh Magnum:: GL:: Mesh:: wrap(GLuint id,
ObjectFlags flags)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Magnum:: GL:: Mesh:: Mesh(MeshPrimitive primitive = MeshPrimitive:: Triangles) explicit
Constructor.
Parameters | |
---|---|
primitive | Primitive type |
If ARB_
Magnum:: GL:: Mesh:: Mesh(Magnum:: MeshPrimitive primitive) explicit
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Magnum:: GL:: Mesh:: Mesh(NoCreateT) explicit noexcept
Construct without creating the underlying OpenGL object.
The constructed instance is equivalent to moved-from state. Useful in cases where you will overwrite the instance later anyway. Move another object over it to make it useful.
This function can be safely used for constructing (and later destructing) objects even without any OpenGL context being active.
Magnum:: GL:: Mesh:: ~Mesh()
Destructor.
If ARB_
GLuint Magnum:: GL:: Mesh:: id() const
OpenGL vertex array ID.
If neither ARB_0
.
GLuint Magnum:: GL:: Mesh:: release()
Release OpenGL object.
Releases ownership of OpenGL vertex array object and returns its ID so it is not deleted on destruction. The internal state is then equivalent to moved-from state.
std:: string Magnum:: GL:: Mesh:: label()
Mesh label.
The result is not cached, repeated queries will result in repeated OpenGL calls. If OpenGL 4.3 / OpenGL ES 3.2 is not supported and neither KHR_
Mesh& Magnum:: GL:: Mesh:: setLabel(const std:: string& label)
Set mesh label.
Returns | Reference to self (for method chaining) |
---|
Default is empty string. If OpenGL 4.3 / OpenGL ES 3.2 is not supported and neither KHR_
template<std:: size_t size>
Mesh& Magnum:: GL:: Mesh:: setLabel(const char(&label)[size])
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
bool Magnum:: GL:: Mesh:: isIndexed() const
Whether the mesh is indexed.
UnsignedInt Magnum:: GL:: Mesh:: indexTypeSize() const
Index type size.
Expects that the mesh is indexed.
std:: size_t Magnum:: GL:: Mesh:: indexSize() const
Index size.
Mesh& Magnum:: GL:: Mesh:: setPrimitive(MeshPrimitive primitive)
Set primitive type.
Returns | Reference to self (for method chaining) |
---|
Default is MeshPrimitive::
Mesh& Magnum:: GL:: Mesh:: setPrimitive(Magnum:: MeshPrimitive primitive)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Mesh& Magnum:: GL:: Mesh:: setCount(Int count)
Set vertex/index count.
Returns | Reference to self (for method chaining) |
---|
If the mesh is indexed, the value is treated as index count, otherwise the value is vertex count. If set to 0
, no draw commands are issued when calling draw(AbstractShaderProgram&). Ignored when calling draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). Default is 0
.
Mesh& Magnum:: GL:: Mesh:: setBaseVertex(Int baseVertex)
Set base vertex.
Returns | Reference to self (for method chaining) |
---|
Sets number of vertices of which the vertex buffer will be offset when drawing. Ignored when calling draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). Default is 0
.
Mesh& Magnum:: GL:: Mesh:: setInstanceCount(Int count)
Set instance count.
Returns | Reference to self (for method chaining) |
---|
If set to 1
, non-instanced draw commands are issued when calling draw(AbstractShaderProgram&) or draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). If set to 0
, no draw commands are issued at all. Default is 1
.
Mesh& Magnum:: GL:: Mesh:: setBaseInstance(UnsignedInt baseInstance)
Set base instance.
Returns | Reference to self (for method chaining) |
---|
Ignored when calling draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt). Default is 0
.
template<class ... T>
Mesh& Magnum:: GL:: Mesh:: addVertexBuffer(Buffer& buffer,
GLintptr offset,
const T&... attributes)
Add buffer with (interleaved) vertex attributes for use with given shader.
Returns | Reference to self (for method chaining) |
---|
Parameter offset
is offset of the array from the beginning, attribute list is combination of attribute definitions (specified in implementation of given shader) and offsets between interleaved attributes.
See class documentation for simple usage example. For more involved example imagine that you have a buffer with 76 bytes of some other data at the beginning (possibly material configuration) and then the interleaved vertex array. Each vertex consists of a weight, position, texture coordinate and a normal. You want to draw it with Shaders::
GL::Buffer buffer; GL::Mesh mesh; mesh.addVertexBuffer(buffer, 76, /* initial array offset */ 4, /* skip vertex weight (Float) */ Shaders::Phong::Position(), /* vertex position */ 8, /* skip texture coordinates (Vector2) */ Shaders::Phong::Normal()); /* vertex normal */
You can also achieve the same effect by calling addVertexBuffer() more times with explicitly specified gaps before and after the attributes. This can be used for e.g. runtime-dependent configuration, as it isn't dependent on the variadic template:
mesh.addVertexBuffer(buffer, 76, 4, Shaders::Phong::Position{}, 20) .addVertexBuffer(buffer, 76, 24, Shaders::Phong::Normal{}, 0);
If specifying more than one attribute, the function assumes that the array is interleaved. Adding non-interleaved vertex buffer can be done by specifying one attribute at a time with specific offset. Above example with weight, position, texture coordinate and normal arrays one after another (non-interleaved):
Int vertexCount = 352; mesh.addVertexBuffer(buffer, 76 + 4*vertexCount, Shaders::Phong::Position{}) .addVertexBuffer(buffer, 76 + 24*vertexCount, Shaders::Phong::Normal{});
If ARB_
template<class ... T>
Mesh& Magnum:: GL:: Mesh:: addVertexBufferInstanced(Buffer& buffer,
UnsignedInt divisor,
GLintptr offset,
const T&... attributes)
Add instanced vertex buffer.
Returns | Reference to self (for method chaining) |
---|
Similar to the above function, the divisor
parameter specifies number of instances that will pass until new data are fetched from the buffer. Setting it to 0
is equivalent to calling addVertexBuffer().
If ARB_
Mesh& Magnum:: GL:: Mesh:: addVertexBuffer(Buffer& buffer,
GLintptr offset,
GLsizei stride,
const DynamicAttribute& attribute)
Add buffer with dynamic vertex attributes for use with given shader.
Returns | Reference to self (for method chaining) |
---|
Equivalent to addVertexBuffer(Buffer&, GLintptr, const T&... attributes) but with the possibility to fully specify the attribute properties at runtime, including base type and location. See class documentation for usage example.
Mesh& Magnum:: GL:: Mesh:: addVertexBufferInstanced(Buffer& buffer,
UnsignedInt divisor,
GLintptr offset,
GLsizei stride,
const DynamicAttribute& attribute)
Add buffer with dynamic vertex attributes for use with given shader.
Returns | Reference to self (for method chaining) |
---|
Equivalent to addVertexBufferInstanced(Buffer&, UnsignedInt, GLintptr, const T&... attributes) but with the possibility to fully specify the attribute properties at runtime, including base type and location. See class documentation for usage example.
Mesh& Magnum:: GL:: Mesh:: setIndexBuffer(Buffer& buffer,
GLintptr offset,
MeshIndexType type,
UnsignedInt start,
UnsignedInt end)
Set index buffer.
Parameters | |
---|---|
buffer | Index buffer |
offset | Offset into the buffer |
type | Index data type |
start | Minimum array index contained in the buffer |
end | Maximum array index contained in the buffer |
Returns | Reference to self (for method chaining) |
The smaller range is specified with start
and end
the less memory operations are needed (and possibly some optimizations), improving draw performance. Specifying 0
for both parameters behaves the same as setIndexBuffer(Buffer&, GLintptr, MeshIndexType). On OpenGL ES 2.0 this function behaves always as setIndexBuffer(Buffer&, GLintptr, MeshIndexType), as this functionality is not available there.
If ARB_
Ignored when calling draw(AbstractShaderProgram&, TransformFeedback&, UnsignedInt).
Mesh& Magnum:: GL:: Mesh:: setIndexBuffer(Buffer& buffer,
GLintptr offset,
Magnum:: MeshIndexType type,
UnsignedInt start,
UnsignedInt end)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
Mesh& Magnum:: GL:: Mesh:: setIndexBuffer(Buffer& buffer,
GLintptr offset,
MeshIndexType type)
Set index buffer.
Parameters | |
---|---|
buffer | Index buffer |
offset | Offset into the buffer |
type | Index data type |
Returns | Reference to self (for method chaining) |
Alternative to setIndexBuffer(Buffer&, GLintptr, MeshIndexType, UnsignedInt, UnsignedInt) with unspecified index limits, see its documentation for more information. Prefer to set index limits for better performance.
Mesh& Magnum:: GL:: Mesh:: setIndexBuffer(Buffer& buffer,
GLintptr offset,
Magnum:: MeshIndexType type)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
void Magnum:: GL:: Mesh:: draw(AbstractShaderProgram& shader)
Draw the mesh.
Parameters | |
---|---|
shader | Shader to use for drawing |
Expects that the shader is compatible with this mesh and is fully set up. If vertex/index count or instance count is 0
, no draw commands are issued. See also AbstractShaderProgram documentation for more information. If ARB_
void Magnum:: GL:: Mesh:: draw(AbstractShaderProgram&& shader)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
void Magnum:: GL:: Mesh:: draw(AbstractShaderProgram& shader,
TransformFeedback& xfb,
UnsignedInt stream = 0)
Draw the mesh with vertices coming out of transform feedback.
Parameters | |
---|---|
shader | Shader to use for drawing |
xfb | Transform feedback to use for vertex count |
stream | Transform feedback stream ID |
Expects that the shader
is compatible with this mesh, is fully set up and that the output buffer(s) from xfb
are used as vertex buffers in this mesh. Everything set by setCount(), setBaseInstance(), setBaseVertex() and setIndexBuffer() is ignored, the mesh is drawn as non-indexed and the vertex count is taken from the xfb
object. If stream
is 0
, non-stream draw command is used. If ARB_
void Magnum:: GL:: Mesh:: draw(AbstractShaderProgram&& shader,
TransformFeedback& xfb,
UnsignedInt stream = 0)
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.