diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 5c2306051..bd0cdfaf9 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -44,12 +44,12 @@ class Shader; This class is designed to be used via subclassing. Subclasses define these functions and properties: - - %Attribute location typedefs defining locations and types - for attribute binding with Mesh::bindAttribute(), for example: + - %Attribute definitions with location and type for + configuring meshes, for example: @code -typedef Attribute<0, Point3D> Position; -typedef Attribute<1, Vector3> Normal; -typedef Attribute<2, Vector2> TextureCoords; +static const Attribute<0, Point3D> Position; +static const Attribute<1, Vector3> Normal; +static const Attribute<2, Vector2> TextureCoordinates; @endcode @todoc Output attribute location (for bindFragmentDataLocationIndexed(), referenced also from Framebuffer::mapDefaultForDraw() / Framebuffer::mapForDraw()) @@ -103,7 +103,7 @@ shader code, e.g.: // or #extension GL_ARB_explicit_attrib_location: enable layout(location = 0) in vec4 position; layout(location = 1) in vec3 normal; -layout(location = 2) in vec2 textureCoords; +layout(location = 2) in vec2 textureCoordinates; @endcode Similarly for ouput attributes, you can also specify blend equation color index for them (see Framebuffer::BlendFunction for more information about @@ -131,9 +131,9 @@ attaching the shaders and linking the program: @code // Shaders attached... -bindAttributeLocation(Position::Location, "position"); -bindAttributeLocation(Normal::Location, "normal"); -bindAttributeLocation(TextureCoords::Location, "textureCoords"); +bindAttributeLocation(Position.Location, "position"); +bindAttributeLocation(Normal.Location, "normal"); +bindAttributeLocation(TextureCoords.Location, "textureCoordinates"); bindFragmentDataLocationIndexed(0, 0, "color"); bindFragmentDataLocationIndexed(1, 1, "ambient"); @@ -185,10 +185,11 @@ setUniform(SpecularTextureUniform, SpecularTextureLayer); @section AbstractShaderProgram-rendering-workflow Rendering workflow -Basic workflow with %AbstractShaderProgram subclasses is: instancing the class -(once at the beginning), then in draw event setting uniforms and marking the -shader for use, binding required textures to their respective layers using -AbstractTexture::bind(GLint) and calling Mesh::draw(). For example: +Basic workflow with %AbstractShaderProgram subclasses is to instance the class +and configuring attribute binding in meshes (see @ref Mesh-configuration "Mesh documentation" +for more information) at the beginning, then in draw event setting uniforms +and marking the shader for use, binding required textures to their respective +layers using AbstractTexture::bind(GLint) and calling Mesh::draw(). Example: @code shader->setTransformation(transformation) ->setProjection(projection) @@ -205,9 +206,9 @@ The engine tracks currently used shader program to avoid unnecessary calls to @fn_gl{UseProgram}. If extension @extension{ARB,separate_shader_objects} or -@extension{EXT,direct_state_access} is available, uniform setting -functions use DSA functions to avoid unnecessary calls to @fn_gl{UseProgram}. -See setUniform(GLint, GLfloat) documentation for more information. +@extension{EXT,direct_state_access} is available, uniform setting functions +use DSA functions to avoid unnecessary calls to @fn_gl{UseProgram}. See +setUniform(GLint, GLfloat) documentation for more information. To achieve least state changes, set all uniforms in one run -- method chaining comes in handy. diff --git a/src/Mesh.cpp b/src/Mesh.cpp index bd763af43..9c91ff31b 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -27,7 +27,7 @@ Mesh::Mesh(Mesh&& other): #ifndef MAGNUM_TARGET_GLES vao(other.vao), #endif - _primitive(other._primitive), _vertexCount(other._vertexCount), finalized(other.finalized), _buffers(other._buffers), _attributes(other._attributes) + _primitive(other._primitive), _vertexCount(other._vertexCount), finalized(other.finalized), attributes(other.attributes) { #ifndef MAGNUM_TARGET_GLES other.vao = 0; @@ -35,9 +35,6 @@ Mesh::Mesh(Mesh&& other): } void Mesh::destroy() { - for(auto& it: _buffers) - delete it.first; - #ifndef MAGNUM_TARGET_GLES glDeleteVertexArrays(1, &vao); #endif @@ -52,8 +49,7 @@ Mesh& Mesh::operator=(Mesh&& other) { _primitive = other._primitive; _vertexCount = other._vertexCount; finalized = other.finalized; - _buffers = other._buffers; - _attributes = other._attributes; + attributes = other.attributes; #ifndef MAGNUM_TARGET_GLES other.vao = 0; @@ -62,13 +58,6 @@ Mesh& Mesh::operator=(Mesh&& other) { return *this; } -Buffer* Mesh::addBuffer(BufferType interleaved) { - Buffer* buffer = new Buffer(Buffer::Target::Array); - _buffers.insert(make_pair(buffer, make_pair(interleaved, vector()))); - - return buffer; -} - void Mesh::draw() { /* Vertex array must be bound before finalization */ #ifndef MAGNUM_TARGET_GLES @@ -102,8 +91,8 @@ void Mesh::unbind() { #ifndef MAGNUM_TARGET_GLES glBindVertexArray(0); #else - for(set::const_iterator it = _attributes.begin(); it != _attributes.end(); ++it) - glDisableVertexAttribArray(*it); + for(const Attribute& attribute: attributes) + glDisableVertexAttribArray(attribute.location); #endif } @@ -111,45 +100,8 @@ void Mesh::finalize() { /* Already finalized */ if(finalized) return; - CORRADE_ASSERT(_vertexCount, "Mesh: the mesh has zero vertex count!", ); - - /* Finalize attribute positions for every buffer */ - for(auto& it: _buffers) { - /* Avoid confustion */ - bool interleaved = it.second.first == BufferType::Interleaved; - vector& attributes = it.second.second; - - /* Interleaved buffer, set stride and position of first attribute */ - if(interleaved) { - /* Set attribute position and compute stride */ - GLsizei stride = 0; - for(vector::iterator ait = attributes.begin(); ait != attributes.end(); ++ait) { - /* The attribute is positioned at the end of previous */ - ait->pointer = reinterpret_cast(stride); - - /* Add attribute size (per vertex) to stride */ - stride += ait->size*TypeInfo::sizeOf(ait->type); - } - - /* Set computed stride for all attributes */ - for(vector::iterator ait = attributes.begin(); ait != attributes.end(); ++ait) - ait->stride = stride; - - /* Non-interleaved buffer, set position of every attribute */ - } else { - /* Set attribute position */ - GLsizei position = 0; - for(vector::iterator ait = attributes.begin(); ait != attributes.end(); ++ait) { - /* The attribute is positioned at the end of previous attribute array */ - ait->pointer = reinterpret_cast(position); - - /* Add attribute size (for all vertices) to position */ - position += ait->size*TypeInfo::sizeOf(ait->type)*_vertexCount; - } - } - } + CORRADE_ASSERT((_vertexCount == 0) == attributes.empty(), "Mesh: vertex count is non-zero, but no attributes are bound", ); - /* Mesh is now finalized, attribute binding is not allowed */ finalized = true; #ifndef MAGNUM_TARGET_GLES @@ -158,46 +110,33 @@ void Mesh::finalize() { } void Mesh::bindBuffers() { - /* Enable vertex arrays for all attributes */ - for(set::const_iterator it = _attributes.begin(); it != _attributes.end(); ++it) - glEnableVertexAttribArray(*it); - - for(auto& it: _buffers) { - /* Avoid confusion */ - vector& attributes = it.second.second; - - /* Bind buffer */ - it.first->bind(); - - /* Bind all attributes to this buffer */ - for(vector::const_iterator ait = attributes.begin(); ait != attributes.end(); ++ait) - #ifndef MAGNUM_TARGET_GLES - if(TypeInfo::isIntegral(ait->type)) - glVertexAttribIPointer(ait->attribute, ait->size, static_cast(ait->type), ait->stride, ait->pointer); - else - #endif - glVertexAttribPointer(ait->attribute, ait->size, static_cast(ait->type), GL_FALSE, ait->stride, ait->pointer); + /* Bind all attributes to this buffer */ + for(const Attribute& attribute: attributes) { + glEnableVertexAttribArray(attribute.location); + + attribute.buffer->bind(Buffer::Target::Array); + + #ifndef MAGNUM_TARGET_GLES + if(TypeInfo::isIntegral(attribute.type)) + glVertexAttribIPointer(attribute.location, attribute.count, static_cast(attribute.type), attribute.stride, reinterpret_cast(attribute.offset)); + else + #endif + glVertexAttribPointer(attribute.location, attribute.count, static_cast(attribute.type), GL_FALSE, attribute.stride, reinterpret_cast(attribute.offset)); } } #endif -void Mesh::bindAttribute(Buffer* buffer, GLuint attribute, GLint size, Type type) { - /* The mesh is finalized or attribute is already bound, nothing to do */ - if(finalized || _attributes.find(attribute) != _attributes.end()) return; - - /* If buffer is not managed by this mesh, nothing to do */ - auto found = _buffers.find(buffer); - if(found == _buffers.end()) return; - - Attribute a; - a.attribute = attribute; - a.size = size; - a.type = type; - a.stride = 0; - a.pointer = nullptr; - - found->second.second.push_back(a); - _attributes.insert(attribute); +void Mesh::addVertexAttribute(Buffer* buffer, GLuint location, GLint count, Type type, GLintptr offset, GLsizei stride) { + CORRADE_ASSERT(_vertexCount != 0, "Mesh: vertex count must be set before binding attributes", ); + + attributes.push_back({ + buffer, + location, + count, + type, + offset, + stride + }); } } diff --git a/src/Mesh.h b/src/Mesh.h index 284346110..2e8aee8d0 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -19,11 +19,9 @@ * @brief Class Magnum::Mesh */ -#include #include -#include -#include "Magnum.h" +#include "AbstractShaderProgram.h" #include "TypeTraits.h" namespace Magnum { @@ -33,6 +31,52 @@ class Buffer; /** @brief Base class for managing non-indexed meshes +@section Mesh-configuration Mesh configuration + +To properly configure mesh, you have to set primitive and vertex count, either +in constructor or using setPrimitive() and 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(). + VAOs are used for desktop OpenGL (not in OpenGL ES). @requires_gl30 Extension @extension{APPLE,vertex_array_object} @requires_gl30 Extension @extension{EXT,gpu_shader4} (for unsigned integer attributes) @@ -282,20 +326,6 @@ class MAGNUM_EXPORT Mesh { TriangleFan = GL_TRIANGLE_FAN }; - /** - * @brief %Buffer type - * - * If storing more than one attribute data in the buffer, the data of - * one attribute can be either kept together or interleaved with data - * for another attributes, so data for every vertex will be in one - * continuous place. - * @see addBuffer() - */ - enum class BufferType: bool { - Interleaved, /**< Interleaved buffer */ - NonInterleaved /**< Non-interleaved buffer */ - }; - /** * @brief Implicit constructor * @param primitive Primitive type @@ -330,7 +360,6 @@ class MAGNUM_EXPORT Mesh { /** * @brief Destructor * - * Deletes all associated buffers. * @see @fn_gl{DeleteVertexArrays} */ inline virtual ~Mesh() { destroy(); } @@ -364,52 +393,127 @@ class MAGNUM_EXPORT Mesh { * @brief Set vertex count * @return Pointer to self (for method chaining) * - * This forces recalculation of attribute positions upon next drawing. + * @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; finalized = false; + attributes.clear(); return this; } /** - * @brief Add buffer - * @param interleaved Whether the buffer is interleaved + * @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. * - * Adds new buffer to the mesh. The buffer can be then filled with - * Buffer::setData(). See also isInterleaved(). + * 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 * - * @todo Move interleaveability to Buffer itself? + * 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() */ - Buffer* addBuffer(BufferType interleaved); + template inline Mesh* addVertexBuffer(Buffer* buffer, const T&... attributes) { + addVertexBufferInternal(buffer, 0, attributes...); + return this; + } /** - * @brief Whether given buffer is interleaved - * @return True if the buffer belongs to the mesh and the buffer is - * interleaved, false otherwise. + * @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 also addBuffer(). + * @see addVertexBufferStride(), addVertexBuffer() */ - inline bool isInterleaved(Buffer* buffer) const { - auto found = _buffers.find(buffer); - return found != _buffers.end() && found->second.first == BufferType::Interleaved; + template inline Mesh* addInterleavedVertexBuffer(Buffer* buffer, GLintptr offset, const T&... attributes) { + addInterleavedVertexBufferInternal(buffer, offset, strideOfInterleaved(attributes...), attributes...); + return this; } /** - * @brief Bind attribute - * @tparam attribute Attribute, defined in the shader - * @param buffer Buffer where bind the attribute to (pointer - * returned by addBuffer()) - * @return Pointer to self (for method chaining) + * @brief Add buffer with interleaved vertex attributes for use with given shader * - * Binds attribute of given type with given buffer. If the attribute is - * already bound, given buffer isn't managed with this mesh (wasn't - * initialized with addBuffer) or the mesh was already drawn, the - * function does nothing. + * See addInterleavedVertexBuffer() for more information. */ - template inline Mesh* bindAttribute(Buffer* buffer) { - bindAttribute(buffer, Attribute::Location, TypeTraits::count(), TypeTraits::type()); + template inline Mesh* addVertexBufferStride(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute& attribute) { + addInterleavedVertexBufferInternal(buffer, offset, stride, attribute); return this; } @@ -453,15 +557,54 @@ class MAGNUM_EXPORT Mesh { MAGNUM_LOCAL void finalize(); private: - /** @brief Vertex attribute */ struct MAGNUM_LOCAL Attribute { - GLuint attribute; /**< @brief %Attribute ID */ - GLint size; /**< @brief How many items of `type` are in the attribute */ - Type type; /**< @brief %Attribute item type */ - GLsizei stride; /**< @brief Distance of two adjacent attributes of this type in interleaved buffer */ - const GLvoid* pointer; /**< @brief Pointer to first attribute of this type in the buffer */ + Buffer* buffer; + GLuint location; + GLint count; + Type type; + GLintptr offset; + GLsizei stride; }; + /* Adding non-interleaved vertex attributes */ + template inline void addVertexBufferInternal(Buffer* buffer, GLintptr offset, const AbstractShaderProgram::Attribute&, const U&... attributes) { + addVertexAttribute(buffer, location, TypeTraits::count(), TypeTraits::type(), offset, 0); + + /* Add size of this attribute array to offset for next attribute */ + addVertexBufferInternal(buffer, offset+TypeTraits::count()*TypeTraits::size()*_vertexCount, attributes...); + } + template 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 inline static GLsizei strideOfInterleaved(const AbstractShaderProgram::Attribute&, const U&... attributes) { + return TypeTraits::count()*TypeTraits::size() + strideOfInterleaved(attributes...); + } + template inline static GLsizei strideOfInterleaved(GLintptr gap, const T&... attributes) { + return gap + strideOfInterleaved(attributes...); + } + inline static GLsizei strideOfInterleaved() { return 0; } + + /* Adding interleaved vertex attributes */ + template inline void addInterleavedVertexBufferInternal(Buffer* buffer, GLintptr offset, GLsizei stride, const AbstractShaderProgram::Attribute&, const U&... attributes) { + addVertexAttribute(buffer, location, TypeTraits::count(), TypeTraits::type(), offset, stride); + + /* Add size of this attribute to offset for next attribute */ + addInterleavedVertexBufferInternal(buffer, offset+TypeTraits::count()*TypeTraits::size(), stride, attributes...); + } + template 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 destroy(); + #ifndef MAGNUM_TARGET_GLES GLuint vao; #endif @@ -469,25 +612,7 @@ class MAGNUM_EXPORT Mesh { GLsizei _vertexCount; bool finalized; - /** - * @brief Buffers with their attributes - * - * Map of associated buffers, evey buffer has: - * - boolean value which signalizes whether the buffer is interleaved - * - list of bound attributes - */ - std::map > > _buffers; - - /** - * @brief List of all bound attributes - * - * List of all bound attributes bound with bindAttribute(). - */ - std::set _attributes; - - MAGNUM_EXPORT void bindAttribute(Buffer* buffer, GLuint attribute, GLint size, Type type); - - void destroy(); + std::vector attributes; }; } diff --git a/src/MeshTools/Interleave.h b/src/MeshTools/Interleave.h index 44451174f..6f85ef2b2 100644 --- a/src/MeshTools/Interleave.h +++ b/src/MeshTools/Interleave.h @@ -53,8 +53,6 @@ class Interleave { } template void operator()(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const T&... attributes) { - CORRADE_ASSERT(mesh->isInterleaved(buffer), "MeshTools::interleave(): the buffer is not interleaved, nothing done", ); - operator()(attributes...); mesh->setVertexCount(_attributeCount); @@ -153,7 +151,7 @@ output to given array buffer and updates vertex count in the mesh accordingly, so you don't have to call Mesh::setVertexCount() on your own. @attention Setting primitive type and binding the attributes to shader is left - to user - see Mesh::setPrimitive() and Mesh::bindAttribute(). + to user - see @ref Mesh-configuration "Mesh documentation". For only one attribute array this function is convenient equivalent to the following, without any performance loss: @@ -162,10 +160,6 @@ buffer->setData(attribute, usage); mesh->setVertexCount(attribute.size()); @endcode -@attention If there is more than one attribute array, the buffer must be set - as interleaved (see Mesh::addBuffer()), otherwise this function does - nothing. - @see MeshTools::compressIndices() */ template inline void interleave(Mesh* mesh, Buffer* buffer, Buffer::Usage usage, const T&... attributes) { diff --git a/src/Physics/DebugDrawResourceManager.cpp b/src/Physics/DebugDrawResourceManager.cpp index 92f27730f..539e677f8 100644 --- a/src/Physics/DebugDrawResourceManager.cpp +++ b/src/Physics/DebugDrawResourceManager.cpp @@ -16,6 +16,7 @@ #include "DebugDrawResourceManager.h" #include "AbstractShaderProgram.h" +#include "Buffer.h" #include "Mesh.h" #include "AbstractShape.h" #include "Box.h" @@ -27,7 +28,7 @@ namespace Magnum { -template class ResourceManager; +template class ResourceManager; namespace Physics { diff --git a/src/Physics/DebugDrawResourceManager.h b/src/Physics/DebugDrawResourceManager.h index 92f292b70..8108e5af9 100644 --- a/src/Physics/DebugDrawResourceManager.h +++ b/src/Physics/DebugDrawResourceManager.h @@ -28,6 +28,7 @@ namespace Magnum { class AbstractShaderProgram; +class Buffer; class Mesh; #ifndef DOXYGEN_GENERATING_OUTPUT @@ -38,7 +39,7 @@ namespace Physics { namespace Implementation { template class AbstractDebugRenderer; }} -extern template class PHYSICS_EXPORT ResourceManager; +extern template class PHYSICS_EXPORT ResourceManager; #endif namespace SceneGraph { @@ -83,7 +84,7 @@ DebugDrawResourceManager::createDebugRenderer(object->shape(), "red") ->setParent(object); @endcode */ -class PHYSICS_EXPORT DebugDrawResourceManager: public ResourceManager { +class PHYSICS_EXPORT DebugDrawResourceManager: public ResourceManager { public: #ifdef DOXYGEN_GENERATING_OUTPUT /** @brief %Options */ diff --git a/src/Physics/Implementation/BoxRenderer.cpp b/src/Physics/Implementation/BoxRenderer.cpp index e93e2e6ae..c428335d2 100644 --- a/src/Physics/Implementation/BoxRenderer.cpp +++ b/src/Physics/Implementation/BoxRenderer.cpp @@ -31,14 +31,13 @@ namespace { constexpr static char shader[] = "shader2d"; constexpr static char key[] = "box2d"; - static Mesh* mesh() { + static Mesh* mesh(Buffer* buffer) { Primitives::Square square; Mesh* mesh = new Mesh; - Buffer* buffer = mesh->addBuffer(Mesh::BufferType::NonInterleaved); buffer->setData(*square.positions(0), Buffer::Usage::StaticDraw); return mesh->setPrimitive(square.primitive()) - ->bindAttribute::Position>(buffer) - ->setVertexCount(square.positions(0)->size()); + ->setVertexCount(square.positions(0)->size()) + ->addVertexBuffer(buffer, Implementation::ShapeShader<2>::Position()); } }; @@ -46,14 +45,13 @@ namespace { constexpr static char shader[] = "shader3d"; constexpr static char key[] = "box3d"; - static Mesh* mesh() { + static Mesh* mesh(Buffer* buffer) { Primitives::Cube cube; Mesh* mesh = new Mesh; - Buffer* buffer = mesh->addBuffer(Mesh::BufferType::NonInterleaved); buffer->setData(*cube.positions(0), Buffer::Usage::StaticDraw); return mesh->setPrimitive(cube.primitive()) - ->bindAttribute::Position>(buffer) - ->setVertexCount(cube.positions(0)->size()); + ->setVertexCount(cube.positions(0)->size()) + ->addVertexBuffer(buffer, Implementation::ShapeShader<2>::Position()); } }; } @@ -63,9 +61,11 @@ constexpr char BoxMesh<2>::key[]; constexpr char BoxMesh<3>::shader[]; constexpr char BoxMesh<3>::key[]; -template BoxRenderer::BoxRenderer(Box& box, ResourceKey options, typename SceneGraph::AbstractObject::ObjectType* parent): AbstractDebugRenderer(BoxMesh::shader, BoxMesh::key, options, parent), box(box) { - if(!this->mesh) - DebugDrawResourceManager::instance()->set(this->mesh.key(), BoxMesh::mesh(), ResourceDataState::Final, ResourcePolicy::Manual); +template BoxRenderer::BoxRenderer(Box& box, ResourceKey options, typename SceneGraph::AbstractObject::ObjectType* parent): AbstractDebugRenderer(BoxMesh::shader, BoxMesh::key, options, parent), buffer(DebugDrawResourceManager::instance()->get(BoxMesh::key)), box(box) { + if(!this->mesh) { + DebugDrawResourceManager::instance()->set(this->buffer.key(), new Buffer, ResourceDataState::Final, ResourcePolicy::Manual); + DebugDrawResourceManager::instance()->set(this->mesh.key(), BoxMesh::mesh(buffer), ResourceDataState::Final, ResourcePolicy::Manual); + } } template void BoxRenderer::draw(const typename DimensionTraits::MatrixType&, typename SceneGraph::AbstractObject::CameraType* camera) { diff --git a/src/Physics/Implementation/BoxRenderer.h b/src/Physics/Implementation/BoxRenderer.h index 1540c8347..a04683ee4 100644 --- a/src/Physics/Implementation/BoxRenderer.h +++ b/src/Physics/Implementation/BoxRenderer.h @@ -17,7 +17,11 @@ #include "AbstractDebugRenderer.h" -namespace Magnum { namespace Physics { +namespace Magnum { + +class Buffer; + +namespace Physics { template class Box; @@ -30,6 +34,7 @@ template class BoxRenderer: public AbstractDebugRendere void draw(const typename DimensionTraits::MatrixType& transformation, typename SceneGraph::AbstractObject::CameraType* camera); private: + Resource buffer; Box& box; }; diff --git a/src/Shaders/PhongShader.cpp b/src/Shaders/PhongShader.cpp index 8d79c69ba..260d291cd 100644 --- a/src/Shaders/PhongShader.cpp +++ b/src/Shaders/PhongShader.cpp @@ -22,6 +22,9 @@ namespace Magnum { namespace Shaders { +const PhongShader::Attribute<0, Point3D> PhongShader::Position; +const PhongShader::Attribute<1, Vector3> PhongShader::Normal; + PhongShader::PhongShader() { Corrade::Utility::Resource rs("MagnumShaders"); Version v = Context::current()->isVersionSupported(Version::GL320) ? Version::GL320 : Version::GL210; @@ -29,8 +32,8 @@ PhongShader::PhongShader() { attachShader(Shader::fromData(v, Shader::Type::Fragment, rs.get("PhongShader.frag"))); if(!Context::current()->isExtensionSupported()) { - bindAttributeLocation(Position::Location, "position"); - bindAttributeLocation(Normal::Location, "normal"); + bindAttributeLocation(Position.Location, "position"); + bindAttributeLocation(Normal.Location, "normal"); } link(); diff --git a/src/Shaders/PhongShader.h b/src/Shaders/PhongShader.h index d334133a9..478b7b45d 100644 --- a/src/Shaders/PhongShader.h +++ b/src/Shaders/PhongShader.h @@ -35,8 +35,8 @@ otherwise falls back to GLSL 1.20. */ class SHADERS_EXPORT PhongShader: public AbstractShaderProgram { public: - typedef Attribute<0, Point3D> Position; /**< @brief Vertex position */ - typedef Attribute<1, Vector3> Normal; /**< @brief Normal direction */ + static const Attribute<0, Point3D> Position; /**< @brief Vertex position */ + static const Attribute<1, Vector3> Normal; /**< @brief Normal direction */ PhongShader();