diff --git a/resources/shaders/110/flat_clip.fs b/resources/shaders/110/flat_clip.fs new file mode 100644 index 0000000000..ececb8eb1a --- /dev/null +++ b/resources/shaders/110/flat_clip.fs @@ -0,0 +1,15 @@ +#version 110 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +uniform vec4 uniform_color; + +varying vec3 clipping_planes_dots; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + + gl_FragColor = uniform_color; +} diff --git a/resources/shaders/110/flat_clip.vs b/resources/shaders/110/flat_clip.vs new file mode 100644 index 0000000000..cdf7d4b3b2 --- /dev/null +++ b/resources/shaders/110/flat_clip.vs @@ -0,0 +1,23 @@ +#version 110 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat4 volume_world_matrix; + +// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. +uniform vec2 z_range; +// Clipping plane - general orientation. Used by the SLA gizmo. +uniform vec4 clipping_plane; + +attribute vec3 v_position; + +varying vec3 clipping_planes_dots; + +void main() +{ + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + vec4 world_pos = volume_world_matrix * vec4(v_position, 1.0); + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs index 9513dbb9e9..fce2a6f39f 100644 --- a/resources/shaders/110/gouraud.fs +++ b/resources/shaders/110/gouraud.fs @@ -34,8 +34,6 @@ uniform SlopeDetection slope; //BBS: add outline_color uniform bool is_outline; -uniform bool offset_depth_buffer; - #ifdef ENABLE_ENVIRONMENT_MAP uniform sampler2D environment_tex; uniform bool use_environment_tex; @@ -97,9 +95,4 @@ void main() #endif else gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); - - // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already - // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values - // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos. - gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0); } \ No newline at end of file diff --git a/resources/shaders/110/mm_contour.fs b/resources/shaders/110/mm_contour.fs index 14477a59e6..ab656998df 100644 --- a/resources/shaders/110/mm_contour.fs +++ b/resources/shaders/110/mm_contour.fs @@ -1,13 +1,8 @@ #version 110 -const float EPSILON = 0.0001; - uniform vec4 uniform_color; void main() { gl_FragColor = uniform_color; - // Values inside depth buffer for fragments of the contour of a selected area are offset - // by small epsilon to solve z-fighting between painted triangles and contour lines. - gl_FragDepth = gl_FragCoord.z - EPSILON; } diff --git a/resources/shaders/110/mm_contour.vs b/resources/shaders/110/mm_contour.vs index d9063f0c70..b37394b619 100644 --- a/resources/shaders/110/mm_contour.vs +++ b/resources/shaders/110/mm_contour.vs @@ -2,10 +2,14 @@ uniform mat4 view_model_matrix; uniform mat4 projection_matrix; +uniform float offset; attribute vec3 v_position; void main() { - gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + // Add small epsilon to z to solve z-fighting between painted triangles and contour lines. + vec4 clip_position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + clip_position.z -= offset * abs(clip_position.w); + gl_Position = clip_position; } diff --git a/resources/shaders/140/flat_clip.fs b/resources/shaders/140/flat_clip.fs new file mode 100644 index 0000000000..b77e0bfaa6 --- /dev/null +++ b/resources/shaders/140/flat_clip.fs @@ -0,0 +1,17 @@ +#version 140 + +const vec3 ZERO = vec3(0.0, 0.0, 0.0); + +uniform vec4 uniform_color; + +in vec3 clipping_planes_dots; + +out vec4 out_color; + +void main() +{ + if (any(lessThan(clipping_planes_dots, ZERO))) + discard; + + out_color = uniform_color; +} diff --git a/resources/shaders/140/flat_clip.vs b/resources/shaders/140/flat_clip.vs new file mode 100644 index 0000000000..40cddf1e5a --- /dev/null +++ b/resources/shaders/140/flat_clip.vs @@ -0,0 +1,23 @@ +#version 140 + +uniform mat4 view_model_matrix; +uniform mat4 projection_matrix; +uniform mat4 volume_world_matrix; + +// Clipping plane, x = min z, y = max z. Used by the FFF and SLA previews to clip with a top / bottom plane. +uniform vec2 z_range; +// Clipping plane - general orientation. Used by the SLA gizmo. +uniform vec4 clipping_plane; + +in vec3 v_position; + +out vec3 clipping_planes_dots; + +void main() +{ + // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded. + vec4 world_pos = volume_world_matrix * vec4(v_position, 1.0); + clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z); + + gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); +} diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs index 6e8c63e0c5..bff8434aa9 100644 --- a/resources/shaders/140/gouraud.fs +++ b/resources/shaders/140/gouraud.fs @@ -34,8 +34,6 @@ uniform SlopeDetection slope; //BBS: add outline_color uniform bool is_outline; -uniform bool offset_depth_buffer; - #ifdef ENABLE_ENVIRONMENT_MAP uniform sampler2D environment_tex; uniform bool use_environment_tex; @@ -97,9 +95,4 @@ void main() #endif else gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha); - - // In the support painting gizmo and the seam painting gizmo are painted triangles rendered over the already - // rendered object. To resolved z-fighting between previously rendered object and painted triangles, values - // inside the depth buffer are offset by small epsilon for painted triangles inside those gizmos. - gl_FragDepth = gl_FragCoord.z - (offset_depth_buffer ? EPSILON : 0.0); } \ No newline at end of file diff --git a/resources/shaders/140/mm_contour.fs b/resources/shaders/140/mm_contour.fs index 3681d76c18..e74124dcae 100644 --- a/resources/shaders/140/mm_contour.fs +++ b/resources/shaders/140/mm_contour.fs @@ -1,13 +1,8 @@ #version 140 -const float EPSILON = 0.0001; - uniform vec4 uniform_color; void main() { gl_FragColor = uniform_color; - // Values inside depth buffer for fragments of the contour of a selected area are offset - // by small epsilon to solve z-fighting between painted triangles and contour lines. - gl_FragDepth = gl_FragCoord.z - EPSILON; } diff --git a/resources/shaders/140/mm_contour.vs b/resources/shaders/140/mm_contour.vs index 7042671de2..679291ba6d 100644 --- a/resources/shaders/140/mm_contour.vs +++ b/resources/shaders/140/mm_contour.vs @@ -2,10 +2,14 @@ uniform mat4 view_model_matrix; uniform mat4 projection_matrix; +uniform float offset; in vec3 v_position; void main() { - gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + // Add small epsilon to z to solve z-fighting between painted triangles and contour lines. + vec4 clip_position = projection_matrix * view_model_matrix * vec4(v_position, 1.0); + clip_position.z -= offset * abs(clip_position.w); + gl_Position = clip_position; } diff --git a/src/libslic3r/Color.cpp b/src/libslic3r/Color.cpp index b911d170e3..c282e307ed 100644 --- a/src/libslic3r/Color.cpp +++ b/src/libslic3r/Color.cpp @@ -130,6 +130,8 @@ bool ColorRGB::operator < (const ColorRGB& other) const for (size_t i = 0; i < 3; ++i) { if (m_data[i] < other.m_data[i]) return true; + else if (m_data[i] > other.m_data[i]) + return false; } return false; @@ -140,6 +142,8 @@ bool ColorRGB::operator > (const ColorRGB& other) const for (size_t i = 0; i < 3; ++i) { if (m_data[i] > other.m_data[i]) return true; + else if (m_data[i] < other.m_data[i]) + return false; } return false; @@ -179,6 +183,8 @@ bool ColorRGBA::operator < (const ColorRGBA& other) const for (size_t i = 0; i < 3; ++i) { if (m_data[i] < other.m_data[i]) return true; + else if (m_data[i] > other.m_data[i]) + return false; } return false; @@ -189,6 +195,8 @@ bool ColorRGBA::operator > (const ColorRGBA& other) const for (size_t i = 0; i < 3; ++i) { if (m_data[i] > other.m_data[i]) return true; + else if (m_data[i] < other.m_data[i]) + return false; } return false; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index c84c56952b..7d35500d34 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -870,8 +870,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab if (!volume.first->model.is_initialized()) shader->set_uniform("uniform_color", volume.first->render_color); - shader->set_uniform("z_range", m_z_range, 2); - shader->set_uniform("clipping_plane", m_clipping_plane, 4); + shader->set_uniform("z_range", m_z_range); + shader->set_uniform("clipping_plane", m_clipping_plane); //BOOST_LOG_TRIVIAL(info) << boost::format("set uniform_color to {%1%, %2%, %3%, %4%}, with_outline=%5%, selected %6%") // %volume.first->render_color[0]%volume.first->render_color[1]%volume.first->render_color[2]%volume.first->render_color[3] // %with_outline%volume.first->selected; diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 0352d2990b..4dce685753 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -392,10 +392,10 @@ private: PrintVolume m_render_volume; // z range for clipping in shaders - float m_z_range[2]; + std::array m_z_range; // plane coeffs for clipping in shaders - float m_clipping_plane[4]; + std::array m_clipping_plane; struct Slope { @@ -463,7 +463,10 @@ public: void set_print_volume(const PrintVolume& print_volume) { m_print_volume = print_volume; } void set_z_range(float min_z, float max_z) { m_z_range[0] = min_z; m_z_range[1] = max_z; } - void set_clipping_plane(const double* coeffs) { m_clipping_plane[0] = coeffs[0]; m_clipping_plane[1] = coeffs[1]; m_clipping_plane[2] = coeffs[2]; m_clipping_plane[3] = coeffs[3]; } + void set_clipping_plane(const std::array& coeffs) { m_clipping_plane = coeffs; } + + const std::array& get_z_range() const { return m_z_range; } + const std::array& get_clipping_plane() const { return m_clipping_plane; } bool is_slope_GlobalActive() const { return m_slope.isGlobalActive; } bool is_slope_active() const { return m_slope.active; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f2e4269965..074ccb8157 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -6417,14 +6417,7 @@ void GLCanvas3D::_picking_pass() _render_plates_for_picking(camera.get_view_matrix(), camera.get_projection_matrix()); } - m_camera_clipping_plane = m_gizmos.get_clipping_plane(); - if (m_camera_clipping_plane.is_active()) { - ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data()); - ::glEnable(GL_CLIP_PLANE0); - } _render_volumes_for_picking(); - if (m_camera_clipping_plane.is_active()) - ::glDisable(GL_CLIP_PLANE0); //BBS: remove the bed picking logic //_render_bed_for_picking(!wxGetApp().plater()->get_camera().is_looking_downward()); @@ -7163,7 +7156,7 @@ void GLCanvas3D::_render_style_editor() void GLCanvas3D::_render_volumes_for_picking() const { - GLShaderProgram* shader = wxGetApp().get_shader("flat"); + GLShaderProgram* shader = wxGetApp().get_shader("flat_clip"); if (shader == nullptr) return; @@ -7186,6 +7179,9 @@ void GLCanvas3D::_render_volumes_for_picking() const const Camera& camera = wxGetApp().plater()->get_camera(); shader->set_uniform("view_model_matrix", camera.get_view_matrix() * volume.first->world_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + shader->set_uniform("volume_world_matrix", volume.first->world_matrix()); + shader->set_uniform("z_range", m_volumes.get_z_range()); + shader->set_uniform("clipping_plane", m_volumes.get_clipping_plane()); volume.first->picking = true; volume.first->render(); volume.first->picking = false; diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 28485cd40e..e2a3e75daf 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -63,8 +63,7 @@ namespace GUI { ColorRGBA color{ ColorRGBA::BLACK() }; void reserve_vertices(size_t vertices_count) { vertices.reserve(vertices_count * vertex_stride_floats(format)); } - void reserve_indices(size_t indices_count) { indices.reserve(indices_count * index_stride_bytes(*this)); } - + void reserve_indices(size_t indices_count) { indices.reserve(indices_count); } void add_vertex(const Vec2f& position); // EVertexLayout::P2 void add_vertex(const Vec2f& position, const Vec2f& tex_coord); // EVertexLayout::P2T2 diff --git a/src/slic3r/GUI/GLShader.cpp b/src/slic3r/GUI/GLShader.cpp index d510a81b40..9f13269c8d 100644 --- a/src/slic3r/GUI/GLShader.cpp +++ b/src/slic3r/GUI/GLShader.cpp @@ -264,6 +264,12 @@ void GLShaderProgram::set_uniform(int id, const std::array& value) con glsafe(::glUniform4fv(id, 1, static_cast(value.data()))); } +void GLShaderProgram::set_uniform(int id, const std::array& value) const +{ + const std::array f_value = { float(value[0]), float(value[1]), float(value[2]), float(value[3]) }; + set_uniform(id, f_value); +} + void GLShaderProgram::set_uniform(int id, const float* value, size_t size) const { if (id >= 0) { diff --git a/src/slic3r/GUI/GLShader.hpp b/src/slic3r/GUI/GLShader.hpp index fd30b3750d..e1b2915e0d 100644 --- a/src/slic3r/GUI/GLShader.hpp +++ b/src/slic3r/GUI/GLShader.hpp @@ -57,6 +57,7 @@ public: void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } + void set_uniform(const char* name, const std::array& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const float* value, size_t size) const { set_uniform(get_uniform_location(name), value, size); } void set_uniform(const char* name, const Transform3f& value) const { set_uniform(get_uniform_location(name), value); } void set_uniform(const char* name, const Transform3d& value) const { set_uniform(get_uniform_location(name), value); } @@ -79,6 +80,7 @@ public: void set_uniform(int id, const std::array& value) const; void set_uniform(int id, const std::array& value) const; void set_uniform(int id, const std::array& value) const; + void set_uniform(int id, const std::array& value) const; void set_uniform(int id, const float* value, size_t size) const; void set_uniform(int id, const Transform3f& value) const; void set_uniform(int id, const Transform3d& value) const; diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 3c874526be..d525ce272e 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -38,6 +38,8 @@ std::pair GLShadersManager::init() valid &= append_shader("imgui", { prefix + "imgui.vs", prefix + "imgui.fs" }); // basic shader, used to render all what was previously rendered using the immediate mode valid &= append_shader("flat", { prefix + "flat.vs", prefix + "flat.fs" }); + // basic shader with plane clipping, used to render volumes in picking pass + valid &= append_shader("flat_clip", { prefix + "flat_clip.vs", prefix + "flat_clip.fs" }); // basic shader for textures, used to render textures valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" }); // used to render 3D scene background diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 8fba22870e..c1aed1867e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -908,6 +908,11 @@ void GLMmSegmentationGizmo3DScene::release_geometry() { glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); triangle_indices_VBO_id = 0; } + if (this->vertices_VAO_id) { + glsafe(::glDeleteVertexArrays(1, &this->vertices_VAO_id)); + this->vertices_VAO_id = 0; + } + this->clear(); } @@ -915,6 +920,7 @@ void GLMmSegmentationGizmo3DScene::render(size_t triangle_indices_idx) const { assert(triangle_indices_idx < this->triangle_indices_VBO_ids.size()); assert(this->triangle_patches.size() == this->triangle_indices_VBO_ids.size()); + assert(this->vertices_VAO_id != 0); assert(this->vertices_VBO_id != 0); assert(this->triangle_indices_VBO_ids[triangle_indices_idx] != 0); @@ -922,6 +928,8 @@ void GLMmSegmentationGizmo3DScene::render(size_t triangle_indices_idx) const if (shader == nullptr) return; + glsafe(::glBindVertexArray(this->vertices_VAO_id)); + // the following binding is needed to set the vertex attributes glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_VBO_id)); const GLint position_id = shader->get_attrib_location("v_position"); if (position_id != -1) { @@ -941,17 +949,24 @@ void GLMmSegmentationGizmo3DScene::render(size_t triangle_indices_idx) const glsafe(::glDisableVertexAttribArray(position_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindVertexArray(0)); } void GLMmSegmentationGizmo3DScene::finalize_vertices() { + assert(this->vertices_VAO_id == 0); assert(this->vertices_VBO_id == 0); if (!this->vertices.empty()) { + glsafe(::glGenVertexArrays(1, &this->vertices_VAO_id)); + glsafe(::glBindVertexArray(this->vertices_VAO_id)); + glsafe(::glGenBuffers(1, &this->vertices_VBO_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->vertices_VBO_id)); glsafe(::glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(float), this->vertices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); this->vertices.clear(); + + glsafe(::glBindVertexArray(0)); } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 7457d97101..ac8238e911 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -57,6 +57,7 @@ public: // IDs of the Vertex Array Objects, into which the geometry has been loaded. // Zero if the VBOs are not sent to GPU yet. + unsigned int vertices_VAO_id{ 0 }; unsigned int vertices_VBO_id{0}; std::vector triangle_indices_VBO_ids; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 2afcb119bf..1d577a45b4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -8,6 +8,7 @@ #include "slic3r/GUI/GUI_App.hpp" #include "slic3r/GUI/Camera.hpp" #include "slic3r/GUI/Plater.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "slic3r/Utils/UndoRedo.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/PresetBundle.hpp" @@ -1071,8 +1072,7 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui, const Transform3d& matrix) if (! shader) return; assert(shader->get_name() == "gouraud" || shader->get_name() == "mm_gouraud"); - ScopeGuard guard([shader]() { if (shader) shader->set_uniform("offset_depth_buffer", false);}); - shader->set_uniform("offset_depth_buffer", true); + for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color), std::make_pair(&m_iva_blockers, blockers_color)}) { iva.first->set_color(iva.second); @@ -1120,6 +1120,9 @@ void TriangleSelectorGUI::update_render_data() for (auto& data : iva_seed_fills_data) data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + // small value used to offset triangles along their normal to avoid z-fighting + static const float offset = 0.001f; + for (const Triangle &tr : m_triangles) { bool is_valid = tr.valid(); bool is_split = tr.is_split(); @@ -1141,9 +1144,11 @@ void TriangleSelectorGUI::update_render_data() //FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort // or the current implementation may be more cache friendly. const Vec3f n = (v1 - v0).cross(v2 - v1).normalized(); - iva.add_vertex(v0, n); - iva.add_vertex(v1, n); - iva.add_vertex(v2, n); + // small value used to offset triangles along their normal to avoid z-fighting + const Vec3f offset_n = offset * n; + iva.add_vertex(v0 + offset_n, n); + iva.add_vertex(v1 + offset_n, n); + iva.add_vertex(v2 + offset_n, n); iva.add_triangle((unsigned int)cnt, (unsigned int)cnt + 1, (unsigned int)cnt + 2); cnt += 3; } @@ -1433,6 +1438,7 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) assert(this->m_triangle_patches.size() == this->m_triangle_indices_VBO_ids.size()); //assert(this->m_vertices_VBO_id != 0); assert(this->m_triangle_patches.size() == this->m_vertices_VBO_ids.size()); + assert(this->m_vertices_VAO_ids[triangle_indices_idx] != 0); assert(this->m_vertices_VBO_ids[triangle_indices_idx] != 0); assert(this->m_triangle_indices_VBO_ids[triangle_indices_idx] != 0); @@ -1440,6 +1446,8 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) if (shader == nullptr) return; + glsafe(::glBindVertexArray(this->m_vertices_VAO_ids[triangle_indices_idx])); + // the following binding is needed to set the vertex attributes glsafe(::glBindBuffer(GL_ARRAY_BUFFER, this->m_vertices_VBO_ids[triangle_indices_idx])); const GLint position_id = shader->get_attrib_location("v_position"); if (position_id != -1) { @@ -1459,6 +1467,7 @@ void TriangleSelectorPatch::render(int triangle_indices_idx) glsafe(::glDisableVertexAttribArray(position_id)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindVertexArray(0)); } void TriangleSelectorPatch::release_geometry() @@ -1471,6 +1480,10 @@ void TriangleSelectorPatch::release_geometry() glsafe(::glDeleteBuffers(1, &vertice_VBO_id)); vertice_VBO_id = 0; } + for (auto &vertice_VAO_id : m_vertices_VAO_ids) { + glsafe(::glDeleteVertexArrays(1, &vertice_VAO_id)); + vertice_VAO_id = 0; + } for (auto& triangle_indices_VBO_id : m_triangle_indices_VBO_ids) { glsafe(::glDeleteBuffers(1, &triangle_indices_VBO_id)); triangle_indices_VBO_id = 0; @@ -1495,6 +1508,7 @@ void TriangleSelectorPatch::finalize_vertices() void TriangleSelectorPatch::finalize_triangle_indices() { m_vertices_VBO_ids.resize(m_triangle_patches.size()); + m_vertices_VAO_ids.resize(m_triangle_patches.size()); m_triangle_indices_VBO_ids.resize(m_triangle_patches.size()); m_triangle_indices_sizes.resize(m_triangle_patches.size()); assert(std::all_of(m_triangle_indices_VBO_ids.cbegin(), m_triangle_indices_VBO_ids.cend(), [](const auto& ti_VBO_id) { return ti_VBO_id == 0; })); @@ -1502,6 +1516,9 @@ void TriangleSelectorPatch::finalize_triangle_indices() for (size_t buffer_idx = 0; buffer_idx < m_triangle_patches.size(); ++buffer_idx) { std::vector& patch_vertices = m_triangle_patches[buffer_idx].patch_vertices; if (!patch_vertices.empty()) { + glsafe(::glGenVertexArrays(1, &m_vertices_VAO_ids[buffer_idx])); + glsafe(::glBindVertexArray(m_vertices_VAO_ids[buffer_idx])); + glsafe(::glGenBuffers(1, &m_vertices_VBO_ids[buffer_idx])); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices_VBO_ids[buffer_idx])); glsafe(::glBufferData(GL_ARRAY_BUFFER, patch_vertices.size() * sizeof(float), patch_vertices.data(), GL_STATIC_DRAW)); @@ -1520,6 +1537,7 @@ void TriangleSelectorPatch::finalize_triangle_indices() //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", Line %1%: buffer_idx %2%, vertices size %3%, buffer id %4%")%__LINE__%buffer_idx%triangle_indices.size()%m_triangle_indices_VBO_ids[buffer_idx]; triangle_indices.clear(); } + glsafe(::glBindVertexArray(0)); } } @@ -1665,13 +1683,12 @@ void TriangleSelectorGUI::render_paint_contour(const Transform3d& matrix) if (contour_shader != nullptr) { contour_shader->start_using(); + contour_shader->set_uniform("offset", OpenGLManager::get_gl_info().is_mesa() ? 0.0005 : 0.00001); const Camera& camera = wxGetApp().plater()->get_camera(); contour_shader->set_uniform("view_model_matrix", camera.get_view_matrix() * matrix); contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); - glsafe(::glDepthFunc(GL_LEQUAL)); m_paint_contour.render(); - glsafe(::glDepthFunc(GL_LESS)); contour_shader->stop_using(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index afba98fd7e..8e0fc1f756 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -133,6 +133,7 @@ protected: void clear() { // BBS + this->m_vertices_VAO_ids.clear(); this->m_vertices_VBO_ids.clear(); this->m_triangle_indices_VBO_ids.clear(); this->m_triangle_indices_sizes.clear(); @@ -161,6 +162,7 @@ protected: // IDs of the Vertex Array Objects, into which the geometry has been loaded. // Zero if the VBOs are not sent to GPU yet. //unsigned int m_vertices_VBO_id{ 0 }; + std::vector m_vertices_VAO_ids; std::vector m_vertices_VBO_ids; std::vector m_triangle_indices_VBO_ids; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 951cd43657..c8397049bc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -6,6 +6,7 @@ #include "slic3r/GUI/NotificationManager.hpp" #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/format.hpp" +#include "slic3r/GUI/OpenGLManager.hpp" #include "libslic3r/AppConfig.hpp" #include "libslic3r/Model.hpp" #include "libslic3r/QuadricEdgeCollapse.hpp" @@ -656,6 +657,7 @@ void GLGizmoSimplify::on_render() if (m_show_wireframe) { auto* contour_shader = wxGetApp().get_shader("mm_contour"); contour_shader->start_using(); + contour_shader->set_uniform("offset", OpenGLManager::get_gl_info().is_mesa() ? 0.0005 : 0.00001); contour_shader->set_uniform("view_model_matrix", view_model_matrix); contour_shader->set_uniform("projection_matrix", camera.get_projection_matrix()); const ColorRGBA color = m_glmodel.get_color(); diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index db0bf1c0aa..4f0210b355 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -20,16 +20,14 @@ struct Camera; // lm_FIXME: Following class might possibly be replaced by Eigen::Hyperplane class ClippingPlane { - double m_data[4]; + std::array m_data; public: - ClippingPlane() - { + ClippingPlane() { *this = ClipsNothing(); } - ClippingPlane(const Vec3d& direction, double offset) - { + ClippingPlane(const Vec3d& direction, double offset) { set_normal(direction); set_offset(offset); } @@ -45,8 +43,7 @@ public: } bool is_point_clipped(const Vec3d& point) const { return distance(point) < 0.; } - void set_normal(const Vec3d& normal) - { + void set_normal(const Vec3d& normal) { const Vec3d norm_dir = normal.normalized(); m_data[0] = norm_dir.x(); m_data[1] = norm_dir.y(); @@ -57,12 +54,11 @@ public: Vec3d get_normal() const { return Vec3d(m_data[0], m_data[1], m_data[2]); } bool is_active() const { return m_data[3] != DBL_MAX; } static ClippingPlane ClipsNothing() { return ClippingPlane(Vec3d(0., 0., 1.), DBL_MAX); } - const double* get_data() const { return m_data; } + const std::array& get_data() const { return m_data; } // Serialization through cereal library template - void serialize( Archive & ar ) - { + void serialize( Archive & ar ) { ar( m_data[0], m_data[1], m_data[2], m_data[3] ); } }; diff --git a/src/slic3r/GUI/OpenGLManager.cpp b/src/slic3r/GUI/OpenGLManager.cpp index 3f38e15bc3..d5781d52d8 100644 --- a/src/slic3r/GUI/OpenGLManager.cpp +++ b/src/slic3r/GUI/OpenGLManager.cpp @@ -65,6 +65,11 @@ const std::string& OpenGLManager::GLInfo::get_renderer() const return m_renderer; } +bool OpenGLManager::GLInfo::is_mesa() const +{ + return boost::icontains(m_version, "mesa"); +} + int OpenGLManager::GLInfo::get_max_tex_size() const { if (!m_detected) diff --git a/src/slic3r/GUI/OpenGLManager.hpp b/src/slic3r/GUI/OpenGLManager.hpp index f2670f8af0..28af5946f9 100644 --- a/src/slic3r/GUI/OpenGLManager.hpp +++ b/src/slic3r/GUI/OpenGLManager.hpp @@ -40,6 +40,8 @@ public: const std::string& get_vendor() const; const std::string& get_renderer() const; + bool is_mesa() const; + int get_max_tex_size() const; float get_max_anisotropy() const;