Browse Source

First-class WebGL support, part 10: reduced mesh functionality.

Actually properly supporting ANGLE_instanced_arrays. Emscripten
currently has the functions without the ANGLE suffix. Only causes linker
warnings when not used, need to fill a bugreport and fix properly.
pull/107/head
Vladimír Vondruš 11 years ago
parent
commit
cab484050b
  1. 24
      src/Magnum/Implementation/MeshState.cpp
  2. 4
      src/Magnum/Implementation/MeshState.h
  3. 51
      src/Magnum/Mesh.cpp
  4. 93
      src/Magnum/Mesh.h
  5. 6
      src/Magnum/MeshView.cpp
  6. 12
      src/Magnum/MeshView.h

24
src/Magnum/Implementation/MeshState.cpp

@ -105,12 +105,16 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
#endif #endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
#ifndef MAGNUM_TARGET_WEBGL
/* Multi draw implementation on ES */ /* Multi draw implementation on ES */
if(context.isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) { if(context.isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) {
extensions.push_back(Extensions::GL::EXT::multi_draw_arrays::string()); extensions.push_back(Extensions::GL::EXT::multi_draw_arrays::string());
multiDrawImplementation = &MeshView::multiDrawImplementationDefault; multiDrawImplementation = &MeshView::multiDrawImplementationDefault;
} else multiDrawImplementation = &MeshView::multiDrawImplementationFallback; } else multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#else
multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#endif
#endif #endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
@ -120,8 +124,9 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationANGLE; drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationANGLE;
drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationANGLE; drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationANGLE;
}
} else if(context.isExtensionSupported<Extensions::GL::EXT::draw_instanced>()) { #ifndef MAGNUM_TARGET_WEBGL
else if(context.isExtensionSupported<Extensions::GL::EXT::draw_instanced>()) {
extensions.push_back(Extensions::GL::EXT::draw_instanced::string()); extensions.push_back(Extensions::GL::EXT::draw_instanced::string());
drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationEXT; drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationEXT;
@ -132,8 +137,9 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationNV; drawArraysInstancedImplementation = &Mesh::drawArraysInstancedImplementationNV;
drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationNV; drawElementsInstancedImplementation = &Mesh::drawElementsInstancedImplementationNV;
}
} else { #endif
else {
drawArraysInstancedImplementation = nullptr; drawArraysInstancedImplementation = nullptr;
drawElementsInstancedImplementation = nullptr; drawElementsInstancedImplementation = nullptr;
} }
@ -152,8 +158,9 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
/* Extension added above */ /* Extension added above */
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationANGLE; vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationANGLE;
}
} else if(context.isExtensionSupported<Extensions::GL::EXT::instanced_arrays>()) { #ifndef MAGNUM_TARGET_WEBGL
else if(context.isExtensionSupported<Extensions::GL::EXT::instanced_arrays>()) {
extensions.push_back(Extensions::GL::EXT::instanced_arrays::string()); extensions.push_back(Extensions::GL::EXT::instanced_arrays::string());
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationEXT; vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationEXT;
@ -162,8 +169,9 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
extensions.push_back(Extensions::GL::NV::instanced_arrays::string()); extensions.push_back(Extensions::GL::NV::instanced_arrays::string());
vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationNV; vertexAttribDivisorImplementation = &Mesh::vertexAttribDivisorImplementationNV;
}
} else vertexAttribDivisorImplementation = nullptr; #endif
else vertexAttribDivisorImplementation = nullptr;
#endif #endif
} }

4
src/Magnum/Implementation/MeshState.h

@ -64,7 +64,11 @@ struct MeshState {
GLuint currentVAO; GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
#ifndef MAGNUM_TARGET_WEBGL
GLint64 maxElementIndex; GLint64 maxElementIndex;
#else
GLint maxElementIndex;
#endif
GLint maxElementsIndices, maxElementsVertices; GLint maxElementsIndices, maxElementsVertices;
#endif #endif
}; };

51
src/Magnum/Mesh.cpp

@ -46,17 +46,32 @@ Int Mesh::maxVertexAttributes() { return AbstractShaderProgram::maxVertexAttribu
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
Long Mesh::maxElementIndex() { #ifndef MAGNUM_TARGET_WEBGL
Long Mesh::maxElementIndex()
#else
Int Mesh::maxElementIndex()
#endif
{
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::ES3_compatibility>()) if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::ES3_compatibility>())
return 0xFFFFFFFFl; return 0xFFFFFFFFl;
#endif #endif
GLint64& value = Context::current()->state().mesh->maxElementIndex; #ifndef MAGNUM_TARGET_WEBGL
GLint64& value =
#else
GLint& value =
#endif
Context::current()->state().mesh->maxElementIndex;
/* Get the value, if not already cached */ /* Get the value, if not already cached */
if(value == 0) if(value == 0) {
#ifndef MAGNUM_TARGET_WEBGL
glGetInteger64v(GL_MAX_ELEMENT_INDEX, &value); glGetInteger64v(GL_MAX_ELEMENT_INDEX, &value);
#else
glGetIntegerv(GL_MAX_ELEMENT_INDEX, &value);
#endif
}
return value; return value;
} }
@ -341,7 +356,7 @@ void Mesh::bindVAO() {
_created = true; _created = true;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glBindVertexArray(current = _id); glBindVertexArray(current = _id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glBindVertexArrayOES(current = _id); glBindVertexArrayOES(current = _id);
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
@ -357,7 +372,7 @@ void Mesh::createImplementationDefault() {
void Mesh::createImplementationVAO() { void Mesh::createImplementationVAO() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glGenVertexArrays(1, &_id); glGenVertexArrays(1, &_id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glGenVertexArraysOES(1, &_id); glGenVertexArraysOES(1, &_id);
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
@ -378,7 +393,7 @@ void Mesh::destroyImplementationDefault() {}
void Mesh::destroyImplementationVAO() { void Mesh::destroyImplementationVAO() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
glDeleteVertexArrays(1, &_id); glDeleteVertexArrays(1, &_id);
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glDeleteVertexArraysOES(1, &_id); glDeleteVertexArraysOES(1, &_id);
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
@ -503,7 +518,7 @@ void Mesh::vertexAttribDivisorImplementationDSAEXT(const GLuint index, const GLu
} }
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLuint divisor) { void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLuint divisor) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glVertexAttribDivisorANGLE(index, divisor); glVertexAttribDivisorANGLE(index, divisor);
#else #else
static_cast<void>(index); static_cast<void>(index);
@ -511,8 +526,9 @@ void Mesh::vertexAttribDivisorImplementationANGLE(const GLuint index, const GLui
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#ifndef MAGNUM_TARGET_WEBGL
void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint divisor) { void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint divisor) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glVertexAttribDivisorEXT(index, divisor); glVertexAttribDivisorEXT(index, divisor);
#else #else
static_cast<void>(index); static_cast<void>(index);
@ -521,7 +537,7 @@ void Mesh::vertexAttribDivisorImplementationEXT(const GLuint index, const GLuint
#endif #endif
} }
void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint divisor) { void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint divisor) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glVertexAttribDivisorNV(index, divisor); glVertexAttribDivisorNV(index, divisor);
#else #else
static_cast<void>(index); static_cast<void>(index);
@ -530,6 +546,7 @@ void Mesh::vertexAttribDivisorImplementationNV(const GLuint index, const GLuint
#endif #endif
} }
#endif #endif
#endif
void Mesh::bindIndexBufferImplementationDefault(Buffer&) {} void Mesh::bindIndexBufferImplementationDefault(Buffer&) {}
@ -585,7 +602,7 @@ void Mesh::unbindImplementationVAO() {}
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
void Mesh::drawArraysInstancedImplementationANGLE(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) { void Mesh::drawArraysInstancedImplementationANGLE(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawArraysInstancedANGLE(GLenum(_primitive), baseVertex, count, instanceCount); glDrawArraysInstancedANGLE(GLenum(_primitive), baseVertex, count, instanceCount);
#else #else
static_cast<void>(baseVertex); static_cast<void>(baseVertex);
@ -595,8 +612,9 @@ void Mesh::drawArraysInstancedImplementationANGLE(const GLint baseVertex, const
#endif #endif
} }
#ifndef MAGNUM_TARGET_WEBGL
void Mesh::drawArraysInstancedImplementationEXT(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) { void Mesh::drawArraysInstancedImplementationEXT(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawArraysInstancedEXT(GLenum(_primitive), baseVertex, count, instanceCount); glDrawArraysInstancedEXT(GLenum(_primitive), baseVertex, count, instanceCount);
#else #else
static_cast<void>(baseVertex); static_cast<void>(baseVertex);
@ -607,7 +625,7 @@ void Mesh::drawArraysInstancedImplementationEXT(const GLint baseVertex, const GL
} }
void Mesh::drawArraysInstancedImplementationNV(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) { void Mesh::drawArraysInstancedImplementationNV(const GLint baseVertex, const GLsizei count, const GLsizei instanceCount) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawArraysInstancedNV(GLenum(_primitive), baseVertex, count, instanceCount); glDrawArraysInstancedNV(GLenum(_primitive), baseVertex, count, instanceCount);
#else #else
static_cast<void>(baseVertex); static_cast<void>(baseVertex);
@ -616,9 +634,10 @@ void Mesh::drawArraysInstancedImplementationNV(const GLint baseVertex, const GLs
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
#endif #endif
} }
#endif
void Mesh::drawElementsInstancedImplementationANGLE(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) { void Mesh::drawElementsInstancedImplementationANGLE(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawElementsInstancedANGLE(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount); glDrawElementsInstancedANGLE(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
#else #else
static_cast<void>(count); static_cast<void>(count);
@ -628,8 +647,9 @@ void Mesh::drawElementsInstancedImplementationANGLE(const GLsizei count, const G
#endif #endif
} }
#ifndef MAGNUM_TARGET_WEBGL
void Mesh::drawElementsInstancedImplementationEXT(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) { void Mesh::drawElementsInstancedImplementationEXT(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawElementsInstancedEXT(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount); glDrawElementsInstancedEXT(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
#else #else
static_cast<void>(count); static_cast<void>(count);
@ -640,7 +660,7 @@ void Mesh::drawElementsInstancedImplementationEXT(const GLsizei count, const GLi
} }
void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) { void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLintptr indexOffset, const GLsizei instanceCount) {
#if !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #ifndef CORRADE_TARGET_NACL
glDrawElementsInstancedNV(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount); glDrawElementsInstancedNV(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset), instanceCount);
#else #else
static_cast<void>(count); static_cast<void>(count);
@ -650,6 +670,7 @@ void Mesh::drawElementsInstancedImplementationNV(const GLsizei count, const GLin
#endif #endif
} }
#endif #endif
#endif
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, MeshPrimitive value) { Debug operator<<(Debug debug, MeshPrimitive value) {

93
src/Magnum/Mesh.h

@ -70,14 +70,14 @@ enum class MeshPrimitive: GLenum {
/** /**
* Line strip with adjacency information. * Line strip with adjacency information.
* @requires_gl32 Extension @extension{ARB,geometry_shader4} * @requires_gl32 Extension @extension{ARB,geometry_shader4}
* @requires_gl Geometry shaders are not available in OpenGL ES. * @requires_gl Geometry shaders are not available in OpenGL ES or WebGL.
*/ */
LineStripAdjacency = GL_LINE_STRIP_ADJACENCY, LineStripAdjacency = GL_LINE_STRIP_ADJACENCY,
/** /**
* Lines with adjacency information. * Lines with adjacency information.
* @requires_gl32 Extension @extension{ARB,geometry_shader4} * @requires_gl32 Extension @extension{ARB,geometry_shader4}
* @requires_gl Geometry shaders are not available in OpenGL ES. * @requires_gl Geometry shaders are not available in OpenGL ES or WebGL.
*/ */
LinesAdjacency = GL_LINES_ADJACENCY, LinesAdjacency = GL_LINES_ADJACENCY,
#endif #endif
@ -101,21 +101,22 @@ enum class MeshPrimitive: GLenum {
/** /**
* Triangle strip with adjacency information. * Triangle strip with adjacency information.
* @requires_gl32 Extension @extension{ARB,geometry_shader4} * @requires_gl32 Extension @extension{ARB,geometry_shader4}
* @requires_gl Geometry shaders are not available in OpenGL ES. * @requires_gl Geometry shaders are not available in OpenGL ES or WebGL.
*/ */
TriangleStripAdjacency = GL_TRIANGLE_STRIP_ADJACENCY, TriangleStripAdjacency = GL_TRIANGLE_STRIP_ADJACENCY,
/** /**
* Triangles with adjacency information. * Triangles with adjacency information.
* @requires_gl32 Extension @extension{ARB,geometry_shader4} * @requires_gl32 Extension @extension{ARB,geometry_shader4}
* @requires_gl Geometry shaders are not available in OpenGL ES. * @requires_gl Geometry shaders are not available in OpenGL ES or WebGL.
*/ */
TrianglesAdjacency = GL_TRIANGLES_ADJACENCY, TrianglesAdjacency = GL_TRIANGLES_ADJACENCY,
/** /**
* Patches. * Patches.
* @requires_gl40 Extension @extension{ARB,tessellation_shader} * @requires_gl40 Extension @extension{ARB,tessellation_shader}
* @requires_gl Tessellation shaders are not available in OpenGL ES. * @requires_gl Tessellation shaders are not available in OpenGL ES or
* WebGL.
*/ */
Patches = GL_PATCHES Patches = GL_PATCHES
#endif #endif
@ -321,8 +322,9 @@ layout, see @ref addVertexBuffer() documentation for details.
@anchor Mesh-performance-optimization @anchor Mesh-performance-optimization
## Performance optimizations ## Performance optimizations
If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0 or If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL ES 3.0,
@es_extension{OES,vertex_array_object} on OpenGL ES 2.0 is supported, VAOs are WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 or
@webgl_extension{OES,vertex_array_object} in WebGL 1.0 is supported, VAOs are
used instead of binding the buffers and specifying vertex attribute pointers used instead of binding the buffers and specifying vertex attribute pointers
in each @ref draw() call. The engine tracks currently bound VAO and currently in each @ref draw() call. The engine tracks currently bound VAO and currently
active shader program to avoid unnecessary calls to @fn_gl{BindVertexArray} and active shader program to avoid unnecessary calls to @fn_gl{BindVertexArray} and
@ -330,10 +332,10 @@ active shader program to avoid unnecessary calls to @fn_gl{BindVertexArray} and
@ref maxElementIndex()) are cached, so repeated queries don't result in @ref maxElementIndex()) are cached, so repeated queries don't result in
repeated @fn_gl{Get} calls. repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} and VAOs are available, If @extension{EXT,direct_state_access} desktop extension and VAOs are
DSA functions are used for specifying attribute locations to avoid unnecessary available, DSA functions are used for specifying attribute locations to avoid
calls to @fn_gl{BindBuffer} and @fn_gl{BindVertexArray}. See documentation of unnecessary calls to @fn_gl{BindBuffer} and @fn_gl{BindVertexArray}. See
@ref addVertexBuffer() for more information. documentation of @ref addVertexBuffer() for more information.
If index range is specified in @ref setIndexBuffer(), range-based version of If index range is specified in @ref setIndexBuffer(), range-based version of
drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also
@ -356,7 +358,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
/** /**
* Unsigned int * Unsigned int
* @requires_gles30 Extension @es_extension{OES,element_index_uint} * @requires_gles30 Extension @es_extension{OES,element_index_uint}
* in OpenGL ES 2.0 * in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{OES,element_index_uint}
* in WebGL 1.0.
*/ */
UnsignedInt = GL_UNSIGNED_INT UnsignedInt = GL_UNSIGNED_INT
}; };
@ -379,9 +383,15 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* value (@f$ 2^32 - 1 @f$). * value (@f$ 2^32 - 1 @f$).
* @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENT_INDEX} * @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENT_INDEX}
* @requires_gles30 No upper limit is specified for index values in * @requires_gles30 No upper limit is specified for index values in
* OpenGL ES 2.0 * OpenGL ES 2.0.
* @requires_webgl20 No upper limit is specified for index values in
* WebGL 1.0.
*/ */
#ifndef MAGNUM_TARGET_WEBGL
static Long maxElementIndex(); static Long maxElementIndex();
#else
static Int maxElementIndex();
#endif
/** /**
* @brief Max recommended index count * @brief Max recommended index count
@ -391,6 +401,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENTS_INDICES} * @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENTS_INDICES}
* @requires_gles30 Ranged element draw is not supported in OpenGL ES * @requires_gles30 Ranged element draw is not supported in OpenGL ES
* 2.0. * 2.0.
* @requires_webgl20 Ranged element draw is not supported in WebGL 1.0.
*/ */
static Int maxElementsIndices(); static Int maxElementsIndices();
@ -402,6 +413,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENTS_VERTICES} * @see @ref setIndexBuffer(), @fn_gl{Get} with @def_gl{MAX_ELEMENTS_VERTICES}
* @requires_gles30 Ranged element draw is not supported in OpenGL ES * @requires_gles30 Ranged element draw is not supported in OpenGL ES
* 2.0. * 2.0.
* @requires_webgl20 Ranged element draw is not supported in WebGL 1.0.
*/ */
static Int maxElementsVertices(); static Int maxElementsVertices();
#endif #endif
@ -418,9 +430,10 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @param primitive Primitive type * @param primitive Primitive type
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is * ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL
* ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is
* available, vertex array object is created. If @extension{ARB,direct_state_access} * available, vertex array object is created. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the vertex array object is * (part of OpenGL 4.5) is not available, the vertex array object is
* created on first use. * created on first use.
* @see @ref setPrimitive(), @ref setCount(), @fn_gl{CreateVertexArrays}, * @see @ref setPrimitive(), @ref setCount(), @fn_gl{CreateVertexArrays},
* eventually @fn_gl{GenVertexArrays} * eventually @fn_gl{GenVertexArrays}
@ -437,7 +450,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @brief Destructor * @brief Destructor
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is * ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL
* ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is
* available, associated vertex array object is deleted. * available, associated vertex array object is deleted.
* @see @fn_gl{DeleteVertexArrays} * @see @fn_gl{DeleteVertexArrays}
*/ */
@ -453,8 +467,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @brief OpenGL mesh ID * @brief OpenGL mesh ID
* *
* If neither @extension{ARB,vertex_array_object} (part of OpenGL 3.0) * If neither @extension{ARB,vertex_array_object} (part of OpenGL 3.0)
* nor OpenGL ES 3.0 nor @es_extension{OES,vertex_array_object} in * nor OpenGL ES 3.0 / WebGL 2.0 nor @es_extension{OES,vertex_array_object}
* OpenGL ES 2.0 is available, returns `0`. * in OpenGL ES 2.0 / @webgl_extension{OES,vertex_array_object} in
* WebGL 1.0 is available, returns `0`.
*/ */
GLuint id() const { return _id; } GLuint id() const { return _id; }
@ -553,7 +568,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex}
* for indexed meshes * for indexed meshes
* @requires_gl Base vertex cannot be specified for indexed meshes in * @requires_gl Base vertex cannot be specified for indexed meshes in
* OpenGL ES. * OpenGL ES or WebGL.
*/ */
Mesh& setBaseVertex(Int baseVertex) { Mesh& setBaseVertex(Int baseVertex) {
_baseVertex = baseVertex; _baseVertex = baseVertex;
@ -609,6 +624,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension2{EXT,draw_instanced,draw_instanced} or * @es_extension2{EXT,draw_instanced,draw_instanced} or
* @es_extension{NV,draw_instanced} in OpenGL ES 2.0. * @es_extension{NV,draw_instanced} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
*/ */
Mesh& setInstanceCount(Int count) { Mesh& setInstanceCount(Int count) {
_instanceCount = count; _instanceCount = count;
@ -626,7 +643,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* Default is `0`. * Default is `0`.
* @see @ref setInstanceCount(), @ref setBaseVertex() * @see @ref setInstanceCount(), @ref setBaseVertex()
* @requires_gl42 Extension @extension{ARB,base_instance} * @requires_gl42 Extension @extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES. * @requires_gl Base instance cannot be specified in OpenGL ES or
* WebGL.
*/ */
Mesh& setBaseInstance(UnsignedInt baseInstance) { Mesh& setBaseInstance(UnsignedInt baseInstance) {
_baseInstance = baseInstance; _baseInstance = baseInstance;
@ -682,25 +700,25 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @endcode * @endcode
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is * ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL
* ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is
* available, the vertex array object is used to hold the parameters. * available, the vertex array object is used to hold the parameters.
* *
* @attention The buffer passed as parameter is not managed by the * @attention The buffer passed as parameter is not managed by the
* mesh, you must ensure it will exist for whole lifetime of the * mesh, you must ensure it will exist for whole lifetime of the
* mesh and delete it afterwards. * mesh and delete it afterwards.
* *
* @attention In @ref MAGNUM_TARGET_WEBGL "WebGL" the data must be
* properly aligned (e.g. all float data must start at addresses
* divisible by four). Also the maximum stride of attribute data
* must be at most 255 bytes. This is not required anywhere else,
* but doing so may have performance benefits.
*
* @see @ref addVertexBufferInstanced(), @ref setPrimitive(), * @see @ref addVertexBufferInstanced(), @ref setPrimitive(),
* @ref setCount(), @fn_gl{BindVertexArray}, * @ref setCount(), @fn_gl{BindVertexArray},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer} or * @fn_gl{VertexAttribPointer} or
* @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access}, * @fn_gl_extension{EnableVertexArrayAttrib,EXT,direct_state_access},
* @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access} * @fn_gl_extension{VertexArrayVertexAttribOffset,EXT,direct_state_access}
* @requires_gles In WebGL the data must be properly aligned (e.g. all
* float data must start at addresses divisible by four). Also the
* maximum stride of attribute data must be at most 255 bytes.
* This is not required anywhere else, but doing so may have
* performance benefits.
*/ */
template<class ...T> inline Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) { template<class ...T> inline Mesh& addVertexBuffer(Buffer& buffer, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...); addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), 0, attributes...);
@ -717,7 +735,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @ref addVertexBuffer(). * @ref addVertexBuffer().
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is * ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL
* ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is
* available, the vertex array object is used to hold the parameters. * available, the vertex array object is used to hold the parameters.
* *
* @see @ref setPrimitive(), @ref setCount(), @ref setInstanceCount(), * @see @ref setPrimitive(), @ref setCount(), @ref setInstanceCount(),
@ -732,6 +751,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension{EXT,instanced_arrays} or * @es_extension{EXT,instanced_arrays} or
* @es_extension{NV,instanced_arrays} in OpenGL ES 2.0. * @es_extension{NV,instanced_arrays} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
*/ */
template<class ...T> inline Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) { template<class ...T> inline Mesh& addVertexBufferInstanced(Buffer& buffer, UnsignedInt divisor, GLintptr offset, const T&... attributes) {
addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), divisor, attributes...); addVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), divisor, attributes...);
@ -756,7 +777,8 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* functionality is not available there. * functionality is not available there.
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is * ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL
* ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is
* available, the vertex array object is used to hold the parameters. * available, the vertex array object is used to hold the parameters.
* *
* @see @ref maxElementIndex(), @ref maxElementsIndices(), * @see @ref maxElementIndex(), @ref maxElementsIndices(),
@ -789,9 +811,10 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* commands are issued. See also * commands are issued. See also
* @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" * @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
* for more information. If @extension{ARB,vertex_array_object} (part * for more information. If @extension{ARB,vertex_array_object} (part
* of OpenGL 3.0), OpenGL ES 3.0 or @es_extension{OES,vertex_array_object} * of OpenGL 3.0), OpenGL ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object}
* in OpenGL ES 2.0 is available, the associated vertex array object is * in OpenGL ES 2.0 or @webgl_extension{OES,vertex_array_object} in
* bound instead of setting up the mesh from scratch. * WebGL 1.0 is available, the associated vertex array object is bound
* instead of setting up the mesh from scratch.
* @see @ref setCount(), @ref setInstanceCount(), * @see @ref setCount(), @ref setInstanceCount(),
* @ref MeshView::draw(AbstractShaderProgram&), * @ref MeshView::draw(AbstractShaderProgram&),
* @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>), * @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>),
@ -985,9 +1008,11 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
void MAGNUM_LOCAL vertexAttribDivisorImplementationDSAEXT(GLuint index, GLuint divisor); void MAGNUM_LOCAL vertexAttribDivisorImplementationDSAEXT(GLuint index, GLuint divisor);
#elif defined(MAGNUM_TARGET_GLES2) #elif defined(MAGNUM_TARGET_GLES2)
void MAGNUM_LOCAL vertexAttribDivisorImplementationANGLE(GLuint index, GLuint divisor); void MAGNUM_LOCAL vertexAttribDivisorImplementationANGLE(GLuint index, GLuint divisor);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL vertexAttribDivisorImplementationEXT(GLuint index, GLuint divisor); void MAGNUM_LOCAL vertexAttribDivisorImplementationEXT(GLuint index, GLuint divisor);
void MAGNUM_LOCAL vertexAttribDivisorImplementationNV(GLuint index, GLuint divisor); void MAGNUM_LOCAL vertexAttribDivisorImplementationNV(GLuint index, GLuint divisor);
#endif #endif
#endif
void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&); void MAGNUM_LOCAL bindIndexBufferImplementationDefault(Buffer&);
void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer); void MAGNUM_LOCAL bindIndexBufferImplementationVAO(Buffer& buffer);
@ -1000,13 +1025,17 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
void MAGNUM_LOCAL drawArraysInstancedImplementationANGLE(GLint baseVertex, GLsizei count, GLsizei instanceCount); void MAGNUM_LOCAL drawArraysInstancedImplementationANGLE(GLint baseVertex, GLsizei count, GLsizei instanceCount);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL drawArraysInstancedImplementationEXT(GLint baseVertex, GLsizei count, GLsizei instanceCount); void MAGNUM_LOCAL drawArraysInstancedImplementationEXT(GLint baseVertex, GLsizei count, GLsizei instanceCount);
void MAGNUM_LOCAL drawArraysInstancedImplementationNV(GLint baseVertex, GLsizei count, GLsizei instanceCount); void MAGNUM_LOCAL drawArraysInstancedImplementationNV(GLint baseVertex, GLsizei count, GLsizei instanceCount);
#endif
void MAGNUM_LOCAL drawElementsInstancedImplementationANGLE(GLsizei count, GLintptr indexOffset, GLsizei instanceCount); void MAGNUM_LOCAL drawElementsInstancedImplementationANGLE(GLsizei count, GLintptr indexOffset, GLsizei instanceCount);
#ifndef MAGNUM_TARGET_WEBGL
void MAGNUM_LOCAL drawElementsInstancedImplementationEXT(GLsizei count, GLintptr indexOffset, GLsizei instanceCount); void MAGNUM_LOCAL drawElementsInstancedImplementationEXT(GLsizei count, GLintptr indexOffset, GLsizei instanceCount);
void MAGNUM_LOCAL drawElementsInstancedImplementationNV(GLsizei count, GLintptr indexOffset, GLsizei instanceCount); void MAGNUM_LOCAL drawElementsInstancedImplementationNV(GLsizei count, GLintptr indexOffset, GLsizei instanceCount);
#endif #endif
#endif
GLuint _id; GLuint _id;
bool _created; /* see createIfNotAlready() for details */ bool _created; /* see createIfNotAlready() for details */

6
src/Magnum/MeshView.cpp

@ -56,6 +56,7 @@ void MeshView::draw(AbstractShaderProgram& shader, std::initializer_list<std::re
#endif #endif
} }
#ifndef MAGNUM_TARGET_WEBGL
void MeshView::multiDrawImplementationDefault(std::initializer_list<std::reference_wrapper<MeshView>> meshes) { void MeshView::multiDrawImplementationDefault(std::initializer_list<std::reference_wrapper<MeshView>> meshes) {
CORRADE_INTERNAL_ASSERT(meshes.size()); CORRADE_INTERNAL_ASSERT(meshes.size());
@ -95,7 +96,7 @@ void MeshView::multiDrawImplementationDefault(std::initializer_list<std::referen
if(!original._indexBuffer) { if(!original._indexBuffer) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glMultiDrawArrays(GLenum(original._primitive), baseVertex, count, meshes.size()); glMultiDrawArrays(GLenum(original._primitive), baseVertex, count, meshes.size());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glMultiDrawArraysEXT(GLenum(original._primitive), baseVertex, count, meshes.size()); glMultiDrawArraysEXT(GLenum(original._primitive), baseVertex, count, meshes.size());
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
@ -114,7 +115,7 @@ void MeshView::multiDrawImplementationDefault(std::initializer_list<std::referen
{ {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
glMultiDrawElements(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size()); glMultiDrawElements(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size());
#elif !defined(CORRADE_TARGET_EMSCRIPTEN) && !defined(CORRADE_TARGET_NACL) #elif !defined(CORRADE_TARGET_NACL)
glMultiDrawElementsEXT(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size()); glMultiDrawElementsEXT(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size());
#else #else
CORRADE_ASSERT_UNREACHABLE(); CORRADE_ASSERT_UNREACHABLE();
@ -124,6 +125,7 @@ void MeshView::multiDrawImplementationDefault(std::initializer_list<std::referen
(original.*state.unbindImplementation)(); (original.*state.unbindImplementation)();
} }
#endif
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
void MeshView::multiDrawImplementationFallback(std::initializer_list<std::reference_wrapper<MeshView>> meshes) { void MeshView::multiDrawImplementationFallback(std::initializer_list<std::reference_wrapper<MeshView>> meshes) {

12
src/Magnum/MeshView.h

@ -72,7 +72,8 @@ class MAGNUM_EXPORT MeshView {
* @ref draw(AbstractShaderProgram&) calls. * @ref draw(AbstractShaderProgram&) calls.
* *
* If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL * If @extension{ARB,vertex_array_object} (part of OpenGL 3.0), OpenGL
* ES 3.0 or @es_extension{OES,vertex_array_object} in OpenGL ES 2.0 is * ES 3.0, WebGL 2.0, @es_extension{OES,vertex_array_object} in OpenGL
* ES 2.0 or @webgl_extension{OES,vertex_array_object} in WebGL 1.0 is
* available, the associated vertex array object is bound instead of * available, the associated vertex array object is bound instead of
* setting up the mesh from scratch. * setting up the mesh from scratch.
* @attention All meshes must be views of the same original mesh and * @attention All meshes must be views of the same original mesh and
@ -128,7 +129,7 @@ class MAGNUM_EXPORT MeshView {
* @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex} * @requires_gl32 Extension @extension{ARB,draw_elements_base_vertex}
* for indexed meshes * for indexed meshes
* @requires_gl Base vertex cannot be specified for indexed meshes in * @requires_gl Base vertex cannot be specified for indexed meshes in
* OpenGL ES. * OpenGL ES or WebGL.
*/ */
MeshView& setBaseVertex(Int baseVertex) { MeshView& setBaseVertex(Int baseVertex) {
_baseVertex = baseVertex; _baseVertex = baseVertex;
@ -217,6 +218,8 @@ class MAGNUM_EXPORT MeshView {
* @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays}, * @requires_gles30 Extension @es_extension{ANGLE,instanced_arrays},
* @es_extension2{EXT,draw_instanced,draw_instanced} or * @es_extension2{EXT,draw_instanced,draw_instanced} or
* @es_extension{NV,draw_instanced} in OpenGL ES 2.0. * @es_extension{NV,draw_instanced} in OpenGL ES 2.0.
* @requires_webgl20 Extension @webgl_extension{ANGLE,instanced_arrays}
* in WebGL 1.0.
*/ */
MeshView& setInstanceCount(Int count) { MeshView& setInstanceCount(Int count) {
_instanceCount = count; _instanceCount = count;
@ -233,7 +236,8 @@ class MAGNUM_EXPORT MeshView {
* *
* Default is `0`. * Default is `0`.
* @requires_gl42 Extension @extension{ARB,base_instance} * @requires_gl42 Extension @extension{ARB,base_instance}
* @requires_gl Base instance cannot be specified in OpenGL ES. * @requires_gl Base instance cannot be specified in OpenGL ES or
* WebGL.
*/ */
MeshView& setBaseInstance(UnsignedInt baseInstance) { MeshView& setBaseInstance(UnsignedInt baseInstance) {
_baseInstance = baseInstance; _baseInstance = baseInstance;
@ -259,7 +263,9 @@ class MAGNUM_EXPORT MeshView {
#endif #endif
private: private:
#ifndef MAGNUM_TARGET_WEBGL
static MAGNUM_LOCAL void multiDrawImplementationDefault(std::initializer_list<std::reference_wrapper<MeshView>> meshes); static MAGNUM_LOCAL void multiDrawImplementationDefault(std::initializer_list<std::reference_wrapper<MeshView>> meshes);
#endif
static MAGNUM_LOCAL void multiDrawImplementationFallback(std::initializer_list<std::reference_wrapper<MeshView>> meshes); static MAGNUM_LOCAL void multiDrawImplementationFallback(std::initializer_list<std::reference_wrapper<MeshView>> meshes);
std::reference_wrapper<Mesh> _original; std::reference_wrapper<Mesh> _original;

Loading…
Cancel
Save