Browse Source

Ability to specify base vertex in Mesh.

The well-known issue is that gl*DrawElements*BaseVertex() is not
supported in OpenGL ES. It is possible to work around it by
reconfiguring whole VAO, but that seems to be a bit overkill. Currently
the draw() function just asserts that base vertex is not specified for
indexed meshes.
pull/51/head
Vladimír Vondruš 12 years ago
parent
commit
7c2ef76048
  1. 3
      doc/opengl-mapping.dox
  2. 44
      src/Magnum/Mesh.cpp
  3. 34
      src/Magnum/Mesh.h

3
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()

44
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<GLvoid*>(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<GLvoid*>(indexOffset), baseVertex);
/* Indexed mesh without specified range */
} else glDrawElementsBaseVertex(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(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<GLvoid*>(indexOffset));
/* Indexed mesh without specified range */
else
glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
/* Indexed mesh without specified range */
} else
#endif
{
glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
}
}
(this->*Context::current()->state().mesh->unbindImplementation)();
}

34
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

Loading…
Cancel
Save