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{DetachShader} | |
@fn_gl{DispatchCompute} | | @fn_gl{DispatchCompute} | |
@fn_gl{DispatchComputeIndirect} | | @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{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{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{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{DrawTransformFeedback}, \n @fn_gl{DrawTransformFeedbackInstanced}, \n @fn_gl{DrawTransformFeedbackStream}, \n @fn_gl{DrawTransformFeedbackStreamInstanced} | |
@fn_gl{Enable}, `glDisable()` | @ref Renderer::setFeature() @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(); 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 #ifndef MAGNUM_TARGET_GLES2
, _indexStart(0), _indexEnd(0) , _indexStart(0), _indexEnd(0)
#endif #endif
@ -167,9 +167,9 @@ Mesh& Mesh::setIndexBuffer(Buffer& buffer, GLintptr offset, IndexType type, Unsi
} }
#ifndef MAGNUM_TARGET_GLES2 #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 #else
void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset) void Mesh::drawInternal(Int count, Int baseVertex, GLintptr indexOffset)
#endif #endif
{ {
/* Nothing to draw */ /* Nothing to draw */
@ -178,18 +178,36 @@ void Mesh::drawInternal(Int count, Int firstVertex, GLintptr indexOffset)
(this->*Context::current()->state().mesh->bindImplementation)(); (this->*Context::current()->state().mesh->bindImplementation)();
/* Non-indexed mesh */ /* Non-indexed mesh */
if(!_indexBuffer) if(!_indexBuffer) {
glDrawArrays(GLenum(_primitive), firstVertex, count); glDrawArrays(GLenum(_primitive), baseVertex, count);
#ifndef MAGNUM_TARGET_GLES2 /* Indexed mesh with base vertex */
/* Indexed mesh with specified range */ } else if(baseVertex) {
else if(indexEnd) #ifndef MAGNUM_TARGET_GLES
glDrawRangeElements(GLenum(_primitive), indexStart, indexEnd, count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset)); /* Indexed mesh with specified range */
#endif 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 */ /* Indexed mesh without specified range */
else } else
glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset)); #endif
{
glDrawElements(GLenum(_primitive), count, GLenum(_indexType), reinterpret_cast<GLvoid*>(indexOffset));
}
}
(this->*Context::current()->state().mesh->unbindImplementation)(); (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. @ref draw() for more information.
@todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc. @todo Redo in a way that allows glMultiDrawArrays, glDrawArraysInstanced etc.
@todo How to glDrawElementsBaseVertex()/vertex offset -- in draw()?
*/ */
class MAGNUM_EXPORT Mesh: public AbstractObject { class MAGNUM_EXPORT Mesh: public AbstractObject {
friend class MeshView; friend class MeshView;
@ -501,6 +500,22 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
return *this; 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 #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @copybrief count() * @copybrief count()
@ -655,15 +670,16 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
* @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer}, * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if * @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if
* @extension{APPLE,vertex_array_object} is available), @fn_gl{DrawArrays} * @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) { void draw(AbstractShaderProgram& shader) {
shader.use(); shader.use();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd);
#else #else
drawInternal(_count, 0, _indexOffset); drawInternal(_count, _baseVertex, _indexOffset);
#endif #endif
} }
@ -677,9 +693,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
*/ */
CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() { CORRADE_DEPRECATED("use draw(AbstractShaderProgram&) instead") void draw() {
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
drawInternal(_count, 0, _indexOffset, _indexStart, _indexEnd); drawInternal(_count, _baseVertex, _indexOffset, _indexStart, _indexEnd);
#else #else
drawInternal(_count, 0, _indexOffset); drawInternal(_count, _baseVertex, _indexOffset);
#endif #endif
} }
#endif #endif
@ -800,9 +816,9 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
#ifndef MAGNUM_TARGET_GLES2 #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 #else
void drawInternal(Int count, Int firstVertex, GLintptr indexOffset); void drawInternal(Int count, Int baseVertex, GLintptr indexOffset);
#endif #endif
void MAGNUM_LOCAL createImplementationDefault(); void MAGNUM_LOCAL createImplementationDefault();
@ -842,7 +858,7 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
GLuint _id; GLuint _id;
MeshPrimitive _primitive; MeshPrimitive _primitive;
Int _count; Int _count, _baseVertex;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
UnsignedInt _indexStart, _indexEnd; UnsignedInt _indexStart, _indexEnd;
#endif #endif

Loading…
Cancel
Save