diff --git a/doc/opengl-mapping.dox b/doc/opengl-mapping.dox index 2f5ad439d..2014e2859 100644 --- a/doc/opengl-mapping.dox +++ b/doc/opengl-mapping.dox @@ -103,10 +103,9 @@ OpenGL function | Matching API @fn_gl{DetachShader} | | @fn_gl{DispatchCompute} | | @fn_gl{DispatchComputeIndirect} | | -@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements} | @ref Mesh::draw() +@fn_gl{DrawArrays}, \n @fn_gl{DrawElements}, \n @fn_gl{DrawRangeElements}, \n @fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex} | @ref Mesh::draw(), \n @ref MeshView::draw() @fn_gl{DrawArraysIndirect}, \n @fn_gl{DrawElementsIndirect}, \n @fn_gl{MultiDrawArraysIndirect}, \n @fn_gl{MultiDrawElementsIndirect} | | @fn_gl{DrawArraysInstanced}, \n @fn_gl{DrawArraysInstancedBaseInstance}, \n @fn_gl{DrawElementsInstanced}, \n @fn_gl{DrawElementsInstancedBaseInstance}, \n @fn_gl{DrawElementsInstancedBaseVertex}, \n @fn_gl{DrawElementsInstancedBaseVertexBaseInstance} | | -@fn_gl{DrawElementsBaseVertex}, \n @fn_gl{DrawRangeElementsBaseVertex} | | @fn_gl{DrawBuffer}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access}, \n @fn_gl{DrawBuffers}, \n @fn_gl_extension{FramebufferDrawBuffers,EXT,direct_state_access} | @ref DefaultFramebuffer::mapForDraw(), \n @ref Framebuffer::mapForDraw() @fn_gl{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | | @fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature() diff --git a/src/Magnum/Mesh.cpp b/src/Magnum/Mesh.cpp index cc5bbc0ec..e31755309 100644 --- a/src/Magnum/Mesh.cpp +++ b/src/Magnum/Mesh.cpp @@ -72,7 +72,7 @@ std::size_t Mesh::indexSize(IndexType type) { CORRADE_ASSERT_UNREACHABLE(); } -Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0) +Mesh::Mesh(MeshPrimitive primitive): _primitive(primitive), _count(0), _baseVertex(0) #ifndef MAGNUM_TARGET_GLES2 , _indexStart(0), _indexEnd(0) #endif @@ -167,9 +167,9 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi } #ifndef MAGNUM_TARGET_GLES2 -void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset, Int indexStart, Int indexEnd) +void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset, Int indexStart, Int indexEnd) #else -void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset) +void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset) #endif { /* Nothing to draw */ @@ -178,18 +178,36 @@ void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset) (this->*Context::current()->state().mesh->bindImplementation)(); /* Non-indexed mesh */ - if(!_indexBuffer) - glDrawArrays(GLenum(_primitive), firstVertex, count); + if(!_indexBuffer) { + glDrawArrays(GLenum(_primitive), baseVertex, count); - #ifndef MAGNUM_TARGET_GLES2 - /* Indexed mesh with specified range */ - else if(indexEnd) - glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); - #endif + /* Indexed mesh with base vertex */ + } else if(baseVertex) { + #ifndef MAGNUM_TARGET_GLES + /* Indexed mesh with specified range */ + if(indexEnd) { + glDrawRangeElementsBaseVertex(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); + + /* Indexed mesh without specified range */ + } else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset), baseVertex); + #else + CORRADE_ASSERT(false, "Mesh::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", ); + #endif + + /* Indexed mesh without base vertex */ + } else { + /* Indexed mesh with specified range */ + #ifndef MAGNUM_TARGET_GLES2 + if(indexEnd) { + glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast(indexOffset)); - /* Indexed mesh without specified range */ - else - glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); + /* Indexed mesh without specified range */ + } else + #endif + { + glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast(indexOffset)); + } + } (this->*Context::current()->state().mesh->unbindImplementation)(); } diff --git a/src/Magnum/Mesh.h b/src/Magnum/Mesh.h index c731de8a4..6487fa391 100644 --- a/src/Magnum/Mesh.h +++ b/src/Magnum/Mesh.h @@ -318,7 +318,6 @@ drawing commands are used on desktop OpenGL and OpenGL ES 3.0. See also @ref draw() for more information. @todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. -@todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()? */ class MAGNUM_EXPORT Mesh: public AbstractObject { friend class MeshView; @@ -501,6 +500,22 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { return *this; } + /** @brief Base vertex */ + Int baseVertex() const { return _baseVertex; } + + /** + * @brief Set base vertex + * + * Sets number of vertices of which the vertex buffer will be offset + * when drawing. + * @requires_gl Desktop OpenGL is required for base vertex + * specification in indexed meshes. + */ + Mesh& setBaseVertex(Int baseVertex) { + _baseVertex = baseVertex; + return *this; + } + #ifdef MAGNUM_BUILD_DEPRECATED /** * @copybrief count() @@ -655,15 +670,16 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if * @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} - * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements} + * or @fn_gl{DrawElements}/@fn_gl{DrawRangeElements}/ + * @fn_gl{DrawElementsBaseVertex}/@fn_gl{DrawRangeElementsBaseVertex} */ void draw(AbstractShaderProgram& shader) { shader.use(); #ifndef MAGNUM_TARGET_GLES2 - drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); + drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(_count, 0, _indexOffset); + drawInternal(_count, _baseVertex, _indexOffset); #endif } @@ -677,9 +693,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { */ CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() { #ifndef MAGNUM_TARGET_GLES2 - drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); + drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd); #else - drawInternal(_count, 0, _indexOffset); + drawInternal(_count, _baseVertex, _indexOffset); #endif } #endif @@ -800,9 +816,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { #endif #ifndef MAGNUM_TARGET_GLES2 - void drawInternal(Int count, Int firstVertex, GLintptr indexOffset, Int indexStart, Int indexEnd); + void drawInternal(Int count, Int baseVertex, GLintptr indexOffset, Int indexStart, Int indexEnd); #else - void drawInternal(Int count, Int firstVertex, GLintptr indexOffset); + void drawInternal(Int count, Int baseVertex, GLintptr indexOffset); #endif void MAGNUM_LOCAL createImplementationDefault(); @@ -842,7 +858,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject { GLuint _id; MeshPrimitive _primitive; - Int _count; + Int _count, _baseVertex; #ifndef MAGNUM_TARGET_GLES2 UnsignedInt _indexStart, _indexEnd; #endif