mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
626 lines
24 KiB
626 lines
24 KiB
#ifndef Magnum_Mesh_h |
|
#define Magnum_Mesh_h |
|
/* |
|
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
This file is part of Magnum. |
|
|
|
Magnum is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU Lesser General Public License version 3 |
|
only, as published by the Free Software Foundation. |
|
|
|
Magnum is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU Lesser General Public License version 3 for more details. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class Magnum::Mesh |
|
*/ |
|
|
|
#include <vector> |
|
|
|
#include "AbstractShaderProgram.h" |
|
#include "TypeTraits.h" |
|
|
|
namespace Magnum { |
|
|
|
class Buffer; |
|
class Context; |
|
|
|
/** |
|
@brief Base class for managing non-indexed meshes |
|
|
|
@section Mesh-configuration Mesh configuration |
|
|
|
To properly configure mesh, you have to set primitive either in constructor or |
|
using setPrimitive() and call setVertexCount(). Then create vertex buffers, |
|
fill them with vertex data and assign them to mesh and given shader locations |
|
using addVertexBuffer() or addInterleavedVertexBuffer(). You can also use |
|
MeshTools::interleave() to conveniently set vertex count and buffer data. |
|
|
|
Note that the buffer is not managed (e.g. deleted on destruction) by the mesh, |
|
so you have to manage it on your own. On the other hand it allows you to use |
|
one buffer for more meshes (each mesh for example configured for different |
|
shader) or store more than only vertex data in one buffer. |
|
|
|
Example usage -- filling buffer with position data, configuring the mesh and |
|
assigning the buffer to mesh to use with custom shader: |
|
@code |
|
Buffer* buffer; |
|
Mesh* mesh; |
|
|
|
static constexpr Point3D positions[30] = { |
|
// ... |
|
}; |
|
buffer->setData(positions, Buffer::Usage::StaticDraw); |
|
|
|
mesh->setPrimitve(Mesh::Primitive::Triangles) |
|
->setVertexCount(30) |
|
->addVertexBuffer(buffer, MyShader::Position); |
|
@endcode |
|
|
|
Example usage -- creating a plane mesh and assigning buffer with interleaved |
|
vertex attributes for use with phong shader: |
|
@code |
|
Buffer* buffer; |
|
Mesh* mesh; |
|
|
|
Primitives::Plane plane; |
|
MeshTools::interleave(mesh, buffer, Buffer::Usage::StaticDraw, *plane.positions(0), *plane.normals(0)); |
|
mesh->setPrimitive(plane.primitive()) |
|
->addInterleavedVertexBuffer(buffer, 0, Shaders::PhongShader::Position, Shaders::PhongShader::Normal); |
|
@endcode |
|
|
|
@section Mesh-drawing Rendering meshes |
|
|
|
Basic workflow is to set up respective shader (see @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" for more infromation) and call Mesh::draw(). |
|
|
|
@section Mesh-performance-optimization Performance optimizations |
|
|
|
If @extension{APPLE,vertex_array_object} is supported, VAOs are used instead |
|
of binding the buffers and specifying vertex attribute pointers in each |
|
draw() call. |
|
|
|
@requires_gl30 Extension @extension{EXT,gpu_shader4} (for unsigned integer attributes) |
|
|
|
@todo Support for normalized values (e.g. for color as char[4] passed to |
|
shader as floating-point vec4) |
|
@todo Support for packed unsigned integer types for attributes (OpenGL 3.3, @extension{ARB,vertex_type_2_10_10_10_rev}) |
|
@todo Support for fixed precision type for attributes (OpenGL 4.1, @extension{ARB,ES2_compatibility}) |
|
@todo Support for double type for attributes (OpenGL 4.1, @extension{ARB,vertex_attrib_64bit}) |
|
@todo Support for indirect draw buffer (OpenGL 4.0, @extension{ARB,draw_indirect}) |
|
@todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. |
|
*/ |
|
class MAGNUM_EXPORT Mesh { |
|
friend class IndexedMesh; |
|
friend class Context; |
|
|
|
Mesh(const Mesh& other) = delete; |
|
Mesh& operator=(const Mesh& other) = delete; |
|
|
|
public: |
|
/** @name Polygon drawing settings */ |
|
|
|
/** |
|
* @brief Front facing polygon winding |
|
* |
|
* @see setFrontFace() |
|
*/ |
|
enum FrontFace: GLenum { |
|
/** @brief Counterclockwise polygons are front facing (default). */ |
|
CounterClockWise = GL_CCW, |
|
|
|
/** @brief Clockwise polygons are front facing. */ |
|
ClockWise = GL_CW |
|
}; |
|
|
|
/** |
|
* @brief Set front-facing polygon winding |
|
* |
|
* Initial value is `FrontFace::%CounterClockWise`. |
|
* @see @fn_gl{FrontFace} |
|
*/ |
|
inline static void setFrontFace(FrontFace mode) { |
|
glFrontFace(static_cast<GLenum>(mode)); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
/** |
|
* @brief Provoking vertex |
|
* |
|
* @see setProvokingVertex() |
|
* @requires_gl OpenGL ES behaves always like |
|
* <tt>ProvokingMode::%LastVertexConvention</tt>. |
|
* @requires_gl32 Extension @extension{ARB,provoking_vertex}. Older |
|
* versions behave always like |
|
* <tt>ProvokingMode::%LastVertexConvention</tt>. |
|
*/ |
|
enum class ProvokingVertex: GLenum { |
|
/** @brief Use first vertex of each polygon. */ |
|
FirstVertexConvention = GL_FIRST_VERTEX_CONVENTION, |
|
|
|
/** @brief Use last vertex of each polygon (default). */ |
|
LastVertexConvention = GL_LAST_VERTEX_CONVENTION |
|
}; |
|
|
|
/** |
|
* @brief Set provoking vertex |
|
* |
|
* Initial value is <tt>ProvokingMode::%LastVertexConvention</tt>. |
|
* @see @fn_gl{ProvokingVertex} |
|
* @requires_gl OpenGL ES behaves always like the default. |
|
* @requires_gl32 Extension @extension{ARB,provoking_vertex}. Older |
|
* versions behave always like the default. |
|
*/ |
|
inline static void setProvokingVertex(ProvokingVertex mode) { |
|
glProvokingVertex(static_cast<GLenum>(mode)); |
|
} |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
/** |
|
* @brief Polygon mode |
|
* |
|
* @see setPolygonMode() |
|
* @requires_gl OpenGL ES behaves always like |
|
* <tt>PolygonMode::%Fill</tt>. See setPrimitive() for possible |
|
* workaround. |
|
*/ |
|
enum class PolygonMode: GLenum { |
|
/** |
|
* Interior of the polygon is filled (default). |
|
*/ |
|
Fill = GL_FILL, |
|
|
|
/** |
|
* Boundary edges are filled. See also setLineWidth(). |
|
*/ |
|
Line = GL_LINE, |
|
|
|
/** |
|
* Starts of boundary edges are drawn as points. See also |
|
* setPointSize(). |
|
*/ |
|
Point = GL_POINT |
|
}; |
|
#endif |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
/** |
|
* @brief Set polygon drawing mode |
|
* |
|
* Initial value is `PolygonMode::%Fill`. |
|
* @see @fn_gl{PolygonMode} |
|
* @requires_gl OpenGL ES behaves always like the default. See |
|
* setPrimitive() for possible workaround. |
|
*/ |
|
inline static void setPolygonMode(PolygonMode mode) { |
|
glPolygonMode(GL_FRONT_AND_BACK, static_cast<GLenum>(mode)); |
|
} |
|
#endif |
|
|
|
/** |
|
* @brief Mode affected by polygon offset |
|
* |
|
* @see setPolygonOffsetMode(), setPolygonOffset() |
|
*/ |
|
enum class PolygonOffsetMode: GLenum { |
|
/** Offset filled polygons. */ |
|
Fill = GL_POLYGON_OFFSET_FILL |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
, |
|
|
|
/** |
|
* Offset lines. |
|
* @requires_gl Only <tt>PolygonOffset::%Fill</tt> is supported. |
|
*/ |
|
Line = GL_POLYGON_OFFSET_LINE, |
|
|
|
/** |
|
* Offset points. |
|
* @requires_gl Only <tt>PolygonOffset::%Fill</tt> is supported. |
|
*/ |
|
Point = GL_POLYGON_OFFSET_POINT |
|
#endif |
|
}; |
|
|
|
/** |
|
* @brief Enable/disable polygon offset for given mode |
|
* |
|
* Initially disabled for all modes. |
|
* @see setPolygonOffset(), @fn_gl{Enable}/@fn_gl{Disable} |
|
*/ |
|
inline static void setPolygonOffsetMode(PolygonOffsetMode mode, bool enabled) { |
|
enabled ? glEnable(static_cast<GLenum>(mode)) : glDisable(static_cast<GLenum>(mode)); |
|
} |
|
|
|
/** |
|
* @brief Set polygon offset |
|
* @param factor Scale factor |
|
* @param units Offset units |
|
* |
|
* @attention You have to call setPolygonOffsetMode() to enable |
|
* polygon offset for desired polygon modes. |
|
* @see @fn_gl{PolygonOffset} |
|
*/ |
|
inline static void setPolygonOffset(GLfloat factor, GLfloat units) { |
|
glPolygonOffset(factor, units); |
|
} |
|
|
|
/** |
|
* @brief Set line width |
|
* |
|
* Initial value is `1.0f`. |
|
* @see @fn_gl{LineWidth} |
|
*/ |
|
inline static void setLineWidth(GLfloat width) { |
|
glLineWidth(width); |
|
} |
|
|
|
#ifndef MAGNUM_TARGET_GLES |
|
/** |
|
* @brief Set point size |
|
* |
|
* Initial value is `1.0f`. |
|
* @see setProgramPointSize(), @fn_gl{PointSize} |
|
* @requires_gl Set directly in vertex shader using @c gl_PointSize |
|
* builtin variable. |
|
*/ |
|
inline static void setPointSize(GLfloat size) { |
|
glPointSize(size); |
|
} |
|
|
|
/** |
|
* @brief Enable/disable programmable point size |
|
* |
|
* If enabled, the point size is taken from vertex/geometry shader |
|
* builtin `gl_PointSize`. Initially disabled on desktop OpenGL. |
|
* @see setPointSize(), @fn_gl{Enable}/@fn_gl{Disable} with @def_gl{PROGRAM_POINT_SIZE} |
|
* @requires_gl Always enabled on OpenGL ES. |
|
*/ |
|
inline static void setProgramPointSize(bool enabled) { |
|
enabled ? glEnable(GL_PROGRAM_POINT_SIZE) : glDisable(GL_PROGRAM_POINT_SIZE); |
|
} |
|
#endif |
|
|
|
/*@}*/ |
|
|
|
/** |
|
* @brief Primitive type |
|
* |
|
* @see primitive(), setPrimitive() |
|
*/ |
|
enum class Primitive: GLenum { |
|
/** |
|
* Single points |
|
*/ |
|
Points = GL_POINTS, |
|
|
|
/** |
|
* Each pair of vertices defines a single line, lines aren't |
|
* connected together. |
|
*/ |
|
Lines = GL_LINES, |
|
|
|
/** |
|
* Polyline |
|
*/ |
|
LineStrip = GL_LINE_STRIP, |
|
|
|
/** |
|
* Polyline, last vertex is connected to first. |
|
*/ |
|
LineLoop = GL_LINE_LOOP, |
|
|
|
/** |
|
* Each three vertices define one triangle. |
|
*/ |
|
Triangles = GL_TRIANGLES, |
|
|
|
/** |
|
* First three vertices define first triangle, each following |
|
* vertex defines another triangle. |
|
*/ |
|
TriangleStrip = GL_TRIANGLE_STRIP, |
|
|
|
/** |
|
* First vertex is center, each following vertex is connected to |
|
* previous and center vertex. |
|
*/ |
|
TriangleFan = GL_TRIANGLE_FAN |
|
}; |
|
|
|
/** |
|
* @brief Constructor |
|
* @param primitive Primitive type |
|
* |
|
* Creates mesh with no vertex buffers and zero vertex count. |
|
* @see setPrimitive(), setVertexCount(), @fn_gl{GenVertexArrays} (if |
|
* @extension{APPLE,vertex_array_object} is available) |
|
*/ |
|
inline Mesh(Primitive primitive = Primitive::Triangles): _primitive(primitive), _vertexCount(0) { |
|
(this->*createImplementation)(); |
|
} |
|
|
|
/** @brief Move constructor */ |
|
Mesh(Mesh&& other); |
|
|
|
/** |
|
* @brief Destructor |
|
* |
|
* @see @fn_gl{DeleteVertexArrays} (if |
|
* @extension{APPLE,vertex_array_object} is available) |
|
*/ |
|
inline virtual ~Mesh() { |
|
(this->*destroyImplementation)(); |
|
} |
|
|
|
/** @brief Move assignment */ |
|
Mesh& operator=(Mesh&& other); |
|
|
|
/** @brief Primitive type */ |
|
inline Primitive primitive() const { return _primitive; } |
|
|
|
/** |
|
* @brief Set primitive type |
|
* @return Pointer to self (for method chaining) |
|
*/ |
|
inline Mesh* setPrimitive(Primitive primitive) { |
|
_primitive = primitive; |
|
return this; |
|
} |
|
|
|
/** @brief Vertex count */ |
|
inline GLsizei vertexCount() const { return _vertexCount; } |
|
|
|
/** |
|
* @brief Set vertex count |
|
* @return Pointer to self (for method chaining) |
|
* |
|
* @attention All bound attributes are reset after calling this |
|
* function, so you must call |
|
* addVertexBuffer()/addInterleavedVertexBuffer() afterwards. |
|
* @see MeshTools::interleave() |
|
*/ |
|
inline Mesh* setVertexCount(GLsizei vertexCount) { |
|
_vertexCount = vertexCount; |
|
attributes.clear(); |
|
return this; |
|
} |
|
|
|
/** |
|
* @brief Add buffer with non-interleaved vertex attributes for use with given shader |
|
* |
|
* Attribute list is combination of attribute definitions (specified |
|
* in implementation of given shader) and offsets between attribute |
|
* arrays. |
|
* |
|
* See @ref Mesh-configuration "class documentation" for simple usage |
|
* example. For more involved example imagine that you have buffer |
|
* with 35 bytes of some other data at the beginning (possibly material |
|
* configuration), then position array, then texture coordinate array |
|
* and then normal array. You want to draw it with Shaders::PhongShader, |
|
* but it accepts only position and normal, so you have to skip the |
|
* texture coordinate array: |
|
* @code |
|
* Mesh* mesh; |
|
* Buffer* buffer; |
|
* mesh->addVertexBuffer(buffer, |
|
* 35, // skip other data |
|
* Shaders::PhongShader::Position, // position array |
|
* sizeof(Vector2)*mesh->vertexCount(), // skip texture coordinate array |
|
* Shaders::PhongShader::Normal); // normal array |
|
* @endcode |
|
* |
|
* Vou can also achieve the same effect by calling this function more |
|
* times with absolute offsets: |
|
* @code |
|
* mesh->addVertexBuffer(buffer, 35, Shaders::PhongShader::Position); |
|
* ->addVertexBuffer(buffer, 35 + (sizeof(Shaders::PhongShader::Position::Type) + sizeof(Vector2))* |
|
* mesh->vertexCount(), Shaders::PhongShader::Normal); |
|
* @endcode |
|
* |
|
* @attention Non-zero vertex count must be set before calling this |
|
* function. |
|
* @attention The buffer passed as parameter is not managed by the |
|
* mesh, you must ensure it will exist for whole lifetime of the |
|
* mesh and delete it afterwards. |
|
* |
|
* @see addInterleavedVertexBuffer(), @fn_gl{BindVertexArray}, |
|
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, |
|
* @fn_gl{VertexAttribPointer} (if |
|
* @extension{APPLE,vertex_array_object} is available) |
|
*/ |
|
template<class ...T> inline Mesh* addVertexBuffer(Buffer* buffer, const T&... attributes) { |
|
addVertexBufferInternal(buffer, 0, attributes...); |
|
return this; |
|
} |
|
|
|
/** |
|
* @brief Add buffer with interleaved vertex attributes for use with given shader |
|
* |
|
* Parameter @p offset is offset of the interleaved array from the |
|
* beginning, attribute list is combination of attribute definitions |
|
* (specified in implementation of given shader) and offsets between |
|
* attributes. |
|
* |
|
* See @ref Mesh-configuration "class documentation" for simple usage |
|
* example. For more involved example imagine that you have buffer |
|
* with 35 bytes of some other data at the beginning (possibly material |
|
* configuration) and then the interleaved vertex array. Each vertex |
|
* consists of weight, position, texture coordinate and normal. You |
|
* want to draw it with Shaders::PhongShader, but it accepts only |
|
* position and normal, so you have to skip weight and texture |
|
* coordinate in each vertex: |
|
* @code |
|
* Mesh* mesh; |
|
* Buffer* buffer; |
|
* mesh->addInterleavedVertexBuffer(buffer, |
|
* 35, // skip other data |
|
* sizeof(GLfloat), // skip vertex weight |
|
* Shaders::PhongShader::Position, // vertex position |
|
* sizeof(Vector2), // skip texture coordinates |
|
* Shaders::PhongShader::Normal); // vertex normal |
|
* @endcode |
|
* |
|
* You can also achieve the same effect by calling addVertexBufferStride() |
|
* more times with absolute offset from the beginning and stride |
|
* between vertex attributes: |
|
* @code |
|
* GLsizei stride = // size of one vertex |
|
* sizeof(GLfloat) + |
|
* sizeof(Shaders::PhongShader::Position::Type) + |
|
* sizeof(Vector2) + |
|
* sizeof(Shaders::PhongShader::Normal::Type); |
|
* |
|
* mesh->addVertexBufferStride(buffer, 35 + sizeof(GLfloat), |
|
* stride, Shaders::PhongShader::Position); |
|
* ->addVertexBufferStride(buffer, 35 + sizeof(GLfloat) + |
|
* sizeof(Shaders::PhongShader::Position::Type) + sizeof(Vector2), |
|
* stride, Shaders::PhongShader::Normal); |
|
* @endcode |
|
* |
|
* @attention Non-zero vertex count must be set before calling this |
|
* function. |
|
* @attention The buffer passed as parameter is not managed by the |
|
* mesh, you must ensure it will exist for whole lifetime of the |
|
* mesh and delete it afterwards. |
|
* |
|
* @see addVertexBufferStride(), addVertexBuffer(), |
|
* @fn_gl{BindVertexArray}, @fn_gl{EnableVertexAttribArray}, |
|
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer} (if |
|
* @extension{APPLE,vertex_array_object} is available) |
|
*/ |
|
template<class ...T> inline Mesh* addInterleavedVertexBuffer(Buffer* buffer, GLintptr offset, const T&... attributes) { |
|
addInterleavedVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), attributes...); |
|
return this; |
|
} |
|
|
|
/** |
|
* @brief Add buffer with interleaved vertex attributes for use with given shader |
|
* |
|
* See addInterleavedVertexBuffer() for more information. |
|
*/ |
|
template<GLuint location, class T> inline Mesh* addVertexBufferStride(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>& attribute) { |
|
addInterleavedVertexBufferInternal(buffer, offset, stride, attribute); |
|
return this; |
|
} |
|
|
|
/** |
|
* @brief Draw the mesh |
|
* |
|
* Expects an active shader with all uniforms set. See |
|
* @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" |
|
* for more information. |
|
* @see @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, |
|
* @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray} |
|
* or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object} |
|
* is available), @fn_gl{DrawArrays} |
|
*/ |
|
virtual void draw(); |
|
|
|
private: |
|
struct MAGNUM_LOCAL Attribute { |
|
Buffer* buffer; |
|
GLuint location; |
|
GLint count; |
|
Type type; |
|
GLintptr offset; |
|
GLsizei stride; |
|
}; |
|
|
|
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context); |
|
|
|
/* Adding non-interleaved vertex attributes */ |
|
template<GLuint location, class T, class ...U> inline void addVertexBufferInternal(Buffer* buffer, GLintptr offset, const AbstractShaderProgram::Attribute<location, T>&, const U&... attributes) { |
|
addVertexAttribute(buffer, location, TypeTraits<T>::count(), TypeTraits<T>::type(), offset, 0); |
|
|
|
/* Add size of this attribute array to offset for next attribute */ |
|
addVertexBufferInternal(buffer, offset+TypeTraits<T>::count()*TypeTraits<T>::size()*_vertexCount, attributes...); |
|
} |
|
template<class ...T> inline void addVertexBufferInternal(Buffer* buffer, GLintptr offset, GLintptr gap, const T&... attributes) { |
|
/* Add the gap to offset for next attribute */ |
|
addVertexBufferInternal(buffer, offset+gap, attributes...); |
|
} |
|
inline void addVertexBufferInternal(Buffer*, GLintptr) {} |
|
|
|
/* Computing stride of interleaved vertex attributes */ |
|
template<GLuint location, class T, class ...U> inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute<location, T>&, const U&... attributes) { |
|
return TypeTraits<T>::count()*TypeTraits<T>::size() + strideOfInterleaved(attributes...); |
|
} |
|
template<class ...T> inline static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { |
|
return gap + strideOfInterleaved(attributes...); |
|
} |
|
inline static GLsizei strideOfInterleaved() { return 0; } |
|
|
|
/* Adding interleaved vertex attributes */ |
|
template<GLuint location, class T, class ...U> inline void addInterleavedVertexBufferInternal(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute<location, T>&, const U&... attributes) { |
|
addVertexAttribute(buffer, location, TypeTraits<T>::count(), TypeTraits<T>::type(), offset, stride); |
|
|
|
/* Add size of this attribute to offset for next attribute */ |
|
addInterleavedVertexBufferInternal(buffer, offset+TypeTraits<T>::count()*TypeTraits<T>::size(), stride, attributes...); |
|
} |
|
template<class ...T> inline void addInterleavedVertexBufferInternal(Buffer* buffer, GLintptr offset, GLsizei stride, GLintptr gap, const T&... attributes) { |
|
/* Add the gap to offset for next attribute */ |
|
addInterleavedVertexBufferInternal(buffer, offset+gap, stride, attributes...); |
|
} |
|
inline void addInterleavedVertexBufferInternal(Buffer*, GLsizei, GLintptr) {} |
|
|
|
void MAGNUM_EXPORT addVertexAttribute(Buffer* buffer, GLuint location, GLint count, Type type, GLintptr offset, GLsizei stride); |
|
|
|
void MAGNUM_LOCAL bind(); |
|
|
|
inline void unbind() { |
|
(this->*unbindImplementation)(); |
|
} |
|
|
|
void MAGNUM_LOCAL vertexAttribPointer(const Attribute& attribute); |
|
|
|
typedef void(Mesh::*CreateImplementation)(); |
|
void MAGNUM_LOCAL createImplementationDefault(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void MAGNUM_LOCAL createImplementationVAO(); |
|
#endif |
|
static CreateImplementation createImplementation; |
|
|
|
typedef void(Mesh::*DestroyImplementation)(); |
|
void MAGNUM_LOCAL destroyImplementationDefault(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void MAGNUM_LOCAL destroyImplementationVAO(); |
|
#endif |
|
static DestroyImplementation destroyImplementation; |
|
|
|
typedef void(Mesh::*BindAttributeImplementation)(const Attribute&); |
|
void MAGNUM_LOCAL bindAttributeImplementationDefault(const Attribute& attribute); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void MAGNUM_LOCAL bindAttributeImplementationVAO(const Attribute& attribute); |
|
#endif |
|
static MAGNUM_LOCAL BindAttributeImplementation bindAttributeImplementation; |
|
|
|
typedef void(Mesh::*BindImplementation)(); |
|
void MAGNUM_LOCAL bindImplementationDefault(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void MAGNUM_LOCAL bindImplementationVAO(); |
|
#endif |
|
static MAGNUM_LOCAL BindImplementation bindImplementation; |
|
|
|
typedef void(Mesh::*UnbindImplementation)(); |
|
void MAGNUM_LOCAL unbindImplementationDefault(); |
|
#ifndef MAGNUM_TARGET_GLES |
|
void MAGNUM_LOCAL unbindImplementationVAO(); |
|
#endif |
|
static MAGNUM_LOCAL UnbindImplementation unbindImplementation; |
|
|
|
GLuint vao; |
|
Primitive _primitive; |
|
GLsizei _vertexCount; |
|
|
|
std::vector<Attribute> attributes; |
|
}; |
|
|
|
} |
|
|
|
#endif
|
|
|