Commit 551932af authored by Martin Heistermann's avatar Martin Heistermann
Browse files

Bugfix: Colored edge rendering in core profile, fixes OpenFlipper-Free#167 .

This is a minimally invasive change, leaving the old code intact, as it
is shared with the other renderers.

Instead of creating render objects as it should, the previous
implementation called glDraw itself and used host-memory ("sysmem")
buffers for it, which are not supported in core OpenGL.

In the new implementation, edge coordinates and colors are uploaded to
a common VBO and rendered using proper render objects.

Having two VBOs for coordinates and colors respectively is advantageous
for better performance when rendering non-colored edges and could be
achieved by packing both in a VAO, which this implementation does not
yet do. However it's better to have something working than to have something
more efficient but broken.

NB Colored edge rendering in classic renderer was also(!) broken before and
is not fixed by this commit, crashes can be provoked by setting edge
colors, switching the drawmode to colored edges and emitting an
updatedObject with the UPDATE_COLORS flag.

I have not run any tests, but I suspect the colored halfedge drawmode to
be similarly broken. A big refactoring / rewrite might be a good idea.
parent d0c30421
...@@ -140,9 +140,12 @@ class ACGDLLEXPORT DrawMeshBase { ...@@ -140,9 +140,12 @@ class ACGDLLEXPORT DrawMeshBase {
/// vertex buffer layout declaration with per vertex colors /// vertex buffer layout declaration with per vertex colors
VertexDeclaration* vertexDecl_; VertexDeclaration* vertexDecl_;
/// vertex buffer layout declaration with per edge colors /// vertex buffer layout declaration with per edge colors, legacy path
VertexDeclaration* vertexDeclEdgeCol_; VertexDeclaration* vertexDeclEdgeCol_;
/// vertex buffer layout declaration with per edge colors
VertexDeclaration vertexDeclEdgeNew_;
/// vertex buffer layout declaration with per halfedge colors /// vertex buffer layout declaration with per halfedge colors
VertexDeclaration* vertexDeclHalfedgeCol_; VertexDeclaration* vertexDeclHalfedgeCol_;
...@@ -974,8 +977,8 @@ private: ...@@ -974,8 +977,8 @@ private:
// full vbo has been invalidated // full vbo has been invalidated
bool updateFullVBO_; bool updateFullVBO_;
// (colored) edges
GeometryBuffer vboEdges_;
public: public:
//======================================================================== //========================================================================
...@@ -990,10 +993,15 @@ public: ...@@ -990,10 +993,15 @@ public:
/** \brief Update all per edge drawing buffers /** \brief Update all per edge drawing buffers
* *
* The updated buffers are: vertex buffer ( 2 vertices per edge ), color buffer * The updated buffers are: vertex buffer ( 2 vertices per edge ), color buffer.
* Only used in legacy rendering
*/ */
void updatePerEdgeBuffers(); void updatePerEdgeBuffers();
/** \brief Update the combined position + color buffer for edge rendering
*/
void updatePerEdgeBuffersNew();
/** \brief get a pointer to the per edge vertex buffer /** \brief get a pointer to the per edge vertex buffer
* *
* This function will return a pointer to the first element of the vertex buffer. * This function will return a pointer to the first element of the vertex buffer.
...@@ -1056,6 +1064,8 @@ private: ...@@ -1056,6 +1064,8 @@ private:
std::vector<ACG::Vec3f> perEdgeVertexBuf_; std::vector<ACG::Vec3f> perEdgeVertexBuf_;
std::vector<ACG::Vec4f> perEdgeColorBuf_; std::vector<ACG::Vec4f> perEdgeColorBuf_;
std::vector<float> perEdgeBuf_; // vertex vec3f + color vec4f
int updatePerHalfedgeBuffers_; int updatePerHalfedgeBuffers_;
std::vector<ACG::Vec3f> perHalfedgeVertexBuf_; std::vector<ACG::Vec3f> perHalfedgeVertexBuf_;
std::vector<ACG::Vec4f> perHalfedgeColorBuf_; std::vector<ACG::Vec4f> perHalfedgeColorBuf_;
......
...@@ -99,6 +99,10 @@ DrawMeshT<Mesh>::DrawMeshT(Mesh& _mesh) ...@@ -99,6 +99,10 @@ DrawMeshT<Mesh>::DrawMeshT(Mesh& _mesh)
pickEdgeShader_ = 0; pickEdgeShader_ = 0;
createVertexDeclaration(); createVertexDeclaration();
vertexDeclEdgeNew_.addElement(GL_FLOAT, 3, VERTEX_USAGE_POSITION);
vertexDeclEdgeNew_.addElement(GL_FLOAT, 4, VERTEX_USAGE_COLOR);
} }
template<class Mesh> template<class Mesh>
...@@ -1496,16 +1500,14 @@ void DrawMeshT<Mesh>::drawLines() ...@@ -1496,16 +1500,14 @@ void DrawMeshT<Mesh>::drawLines()
template <class Mesh> template <class Mesh>
void DrawMeshT<Mesh>::addLineRenderObjects(IRenderer* _renderer, const RenderObject* _baseObj) void DrawMeshT<Mesh>::addLineRenderObjects(IRenderer* _renderer, const RenderObject* _baseObj)
{ {
updatePerEdgeBuffersNew();
if (!mesh_.n_edges())
return;
RenderObject ro = *_baseObj; RenderObject ro = *_baseObj;
bindBuffersToRenderObject(&ro); ro.vertexBuffer = vboEdges_.id();
ro.vertexDecl = &vertexDeclEdgeNew_;
if (mesh_.n_edges()) ro.glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(mesh_.n_edges() * 2));
{ _renderer->addRenderObject(&ro);
ro.indexBuffer = lineIBO_;
ro.glDrawElements(GL_LINES, static_cast<GLsizei>(mesh_.n_edges() * 2), indexType_, 0);
_renderer->addRenderObject(&ro);
}
} }
template <class Mesh> template <class Mesh>
...@@ -1783,6 +1785,48 @@ void DrawMeshT<Mesh>::updatePerEdgeBuffers() ...@@ -1783,6 +1785,48 @@ void DrawMeshT<Mesh>::updatePerEdgeBuffers()
updateEdgeHalfedgeVertexDeclarations(); updateEdgeHalfedgeVertexDeclarations();
} }
template <class Mesh>
void DrawMeshT<Mesh>::updatePerEdgeBuffersNew()
{
if (!updatePerEdgeBuffers_)
return;
perEdgeBuf_.clear();
perEdgeBuf_.reserve(mesh_.n_edges() * 2 * (3 + 4));
auto push_vec4 = [this](const Vec4f &v) {
perEdgeBuf_.push_back(v[0]);
perEdgeBuf_.push_back(v[1]);
perEdgeBuf_.push_back(v[2]);
perEdgeBuf_.push_back(v[3]);
};
auto push_vec3 = [this](const Vec3d &v) {
perEdgeBuf_.push_back(v[0]);
perEdgeBuf_.push_back(v[1]);
perEdgeBuf_.push_back(v[2]);
};
bool have_edge_colors = mesh_.has_edge_colors();
Vec4f color {0.f, 1.f, 0.f, 1.f}; // dummy color, should never be rendered
for (const auto &eh: mesh_.edges()) {
if (have_edge_colors) {
color = OpenMesh::color_cast<Vec4f>(mesh_.color(eh));
}
auto heh = mesh_.halfedge_handle(eh, 0);
ACG::Vec3d pos_from = mesh_.point(mesh_.from_vertex_handle(heh));
ACG::Vec3d pos_to = mesh_.point(mesh_.to_vertex_handle(heh));
push_vec3(pos_from);
push_vec4(color);
push_vec3(pos_to);
push_vec4(color);
}
vboEdges_.upload(
perEdgeBuf_.size() * sizeof(perEdgeBuf_[0]),
static_cast<GLvoid*>(perEdgeBuf_.data()),
GL_STATIC_DRAW);
updatePerEdgeBuffers_ = 0;
}
template <class Mesh> template <class Mesh>
template<typename Mesh::Normal (DrawMeshT<Mesh>::*NormalLookup)(typename Mesh::FaceHandle)> template<typename Mesh::Normal (DrawMeshT<Mesh>::*NormalLookup)(typename Mesh::FaceHandle)>
void DrawMeshT<Mesh>::updatePerHalfedgeBuffers() void DrawMeshT<Mesh>::updatePerHalfedgeBuffers()
...@@ -1828,12 +1872,7 @@ void DrawMeshT<Mesh>::updatePerHalfedgeBuffers() ...@@ -1828,12 +1872,7 @@ void DrawMeshT<Mesh>::updatePerHalfedgeBuffers()
if(perHalfedgeVertexBuf_.size() > 0) if(perHalfedgeVertexBuf_.size() > 0)
{ {
//create buffers if necessary and bind them
bindHEVbo();
//fill buffer with data
fillHEVBO(perHalfedgeVertexBuf_.size(), sizeof(perHalfedgeVertexBuf_[0]), perHalfedgeVertexBuf_.data()); fillHEVBO(perHalfedgeVertexBuf_.size(), sizeof(perHalfedgeVertexBuf_[0]), perHalfedgeVertexBuf_.data());
// rebind the previous buffers
unbindHEVbo();
} }
updatePerHalfedgeBuffers_ = 0; updatePerHalfedgeBuffers_ = 0;
......
...@@ -322,9 +322,6 @@ private: ...@@ -322,9 +322,6 @@ private:
*/ */
inline void draw_lines(); inline void draw_lines();
inline void add_line_RenderObjects(IRenderer* _renderer, const RenderObject* _baseObj);
/** \brief draws all halfedges of the mesh /** \brief draws all halfedges of the mesh
* *
*/ */
......
...@@ -797,7 +797,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G ...@@ -797,7 +797,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G
ro.setupLineRendering(_state.line_width(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height())); ro.setupLineRendering(_state.line_width(), Vec2f((float)_state.viewport_width(), (float)_state.viewport_height()));
applyRenderObjectSettings(props->primitive(), &ro); applyRenderObjectSettings(props->primitive(), &ro);
add_line_RenderObjects(_renderer, &ro); drawMesh_->addLineRenderObjects(_renderer, &ro);
} }
if (props->primitive() == DrawModes::PRIMITIVE_HIDDENLINE) if (props->primitive() == DrawModes::PRIMITIVE_HIDDENLINE)
...@@ -837,7 +837,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G ...@@ -837,7 +837,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G
applyRenderObjectSettings(DrawModes::PRIMITIVE_HIDDENLINE, &ro); applyRenderObjectSettings(DrawModes::PRIMITIVE_HIDDENLINE, &ro);
ro.debugName = "MeshNode.HiddenLine.lines"; ro.debugName = "MeshNode.HiddenLine.lines";
add_line_RenderObjects(_renderer, &ro); drawMesh_->addLineRenderObjects(_renderer, &ro);
} }
if (props->colored() && props->primitive() == DrawModes::PRIMITIVE_EDGE) if (props->colored() && props->primitive() == DrawModes::PRIMITIVE_EDGE)
...@@ -845,11 +845,6 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G ...@@ -845,11 +845,6 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G
ro.shaderDesc.shadeMode = SG_SHADE_UNLIT; ro.shaderDesc.shadeMode = SG_SHADE_UNLIT;
ro.shaderDesc.vertexColors = true; ro.shaderDesc.vertexColors = true;
// note: colored edges are in sysmem, so they are directly bound to the VertexDeclaration
drawMesh_->updateEdgeHalfedgeVertexDeclarations();
ro.vertexDecl = drawMesh_->getEdgeColoredVertexDeclaration();
ro.glDrawArrays(GL_LINES, 0, int(mesh_.n_edges() * 2));
// use specular color for lines // use specular color for lines
ro.emissive = ro.specular; ro.emissive = ro.specular;
...@@ -858,7 +853,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G ...@@ -858,7 +853,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G
applyRenderObjectSettings(props->primitive(), &ro); applyRenderObjectSettings(props->primitive(), &ro);
ro.debugName = "MeshNode.Edges"; ro.debugName = "MeshNode.Edges";
add_line_RenderObjects(_renderer, &ro); drawMesh_->addLineRenderObjects(_renderer, &ro);
// skip other edge primitives for this drawmode layer // skip other edge primitives for this drawmode layer
continue; continue;
...@@ -920,7 +915,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G ...@@ -920,7 +915,7 @@ void ACG::SceneGraph::MeshNodeT<Mesh>::getRenderObjects( IRenderer* _renderer, G
applyRenderObjectSettings(props->primitive(), &ro); applyRenderObjectSettings(props->primitive(), &ro);
ro.debugName = "MeshNode.Edges"; ro.debugName = "MeshNode.Edges";
add_line_RenderObjects(_renderer, &ro); drawMesh_->addLineRenderObjects(_renderer, &ro);
} break; } break;
case DrawModes::PRIMITIVE_POLYGON: case DrawModes::PRIMITIVE_POLYGON:
{ {
...@@ -973,20 +968,6 @@ draw_lines() { ...@@ -973,20 +968,6 @@ draw_lines() {
drawMesh_->drawLines(); drawMesh_->drawLines();
} }
template<class Mesh>
void
MeshNodeT<Mesh>::
add_line_RenderObjects(IRenderer* _renderer, const RenderObject* _baseObj) {
if ((enabled_arrays_ & PER_EDGE_COLOR_ARRAY) && (enabled_arrays_ & PER_EDGE_VERTEX_ARRAY))
{
// colored edges still slow
glDrawArrays(GL_LINES, 0, int(mesh_.n_edges() * 2));
}
else
drawMesh_->addLineRenderObjects(_renderer, _baseObj);
}
template<class Mesh> template<class Mesh>
void void
MeshNodeT<Mesh>:: MeshNodeT<Mesh>::
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment