diff --git a/resources/shaders/gouraud.fs b/resources/shaders/gouraud.fs index f6116eec7..5b4ef0480 100644 --- a/resources/shaders/gouraud.fs +++ b/resources/shaders/gouraud.fs @@ -8,16 +8,22 @@ varying vec2 intensity; varying vec3 delta_box_min; varying vec3 delta_box_max; -varying float world_z; +varying vec3 world_pos; uniform vec4 uniform_color; // x = min z, y = max z; uniform vec2 z_range; +// clipping plane (general orientation): +uniform vec4 clipping_plane; + void main() { - if ((world_z < z_range.x) || (z_range.y < world_z)) + if ((world_pos.z < z_range.x) || (z_range.y < world_pos.z)) + discard; + + if (world_pos.x*clipping_plane.x + world_pos.y*clipping_plane.y + world_pos.z*clipping_plane.z + clipping_plane.w < 0.f ) discard; // if the fragment is outside the print volume -> use darker color diff --git a/resources/shaders/gouraud.vs b/resources/shaders/gouraud.vs index 84ae51391..a226cf312 100644 --- a/resources/shaders/gouraud.vs +++ b/resources/shaders/gouraud.vs @@ -34,7 +34,7 @@ varying vec2 intensity; varying vec3 delta_box_min; varying vec3 delta_box_max; -varying float world_z; +varying vec3 world_pos; void main() { @@ -69,5 +69,5 @@ void main() } gl_Position = ftransform(); - world_z = vec3(print_box.volume_world_matrix * gl_Vertex).z; + world_pos = vec3(print_box.volume_world_matrix * gl_Vertex); } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 7ba61bdb6..57c227e07 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -785,6 +785,7 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id)); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; GLint z_range_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "z_range") : -1; + GLint clipping_plane_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "clipping_plane") : -1; GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1; GLint print_box_max_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.max") : -1; GLint print_box_detection_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1; @@ -799,6 +800,9 @@ void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool if (z_range_id != -1) glsafe(::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range)); + if (clipping_plane_id != -1) + glsafe(::glUniform4fv(clipping_plane_id, 1, (const GLfloat*)clipping_plane)); + GLVolumesWithZList to_render = volumes_to_render(this->volumes, type, filter_func); for (GLVolumeWithZ& volume : to_render) { volume.first->set_render_color(); diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 5cc301a39..0ed8d2e6b 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -427,6 +427,9 @@ private: // z range for clipping in shaders float z_range[2]; + // plane coeffs for clipping in shaders + float clipping_plane[4]; + public: GLVolumePtrs volumes; @@ -485,6 +488,7 @@ public: } void set_z_range(float min_z, float max_z) { z_range[0] = min_z; z_range[1] = max_z; } + void set_clipping_plane(const double* coeffs) { clipping_plane[0] = coeffs[0]; clipping_plane[1] = coeffs[1]; clipping_plane[2] = coeffs[2]; clipping_plane[3] = coeffs[3]; } // returns true if all the volumes are completely contained in the print volume // returns the containment state in the given out_state, if non-null diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3e4824cde..4214abc60 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1321,14 +1321,14 @@ bool GLCanvas3D::Gizmos::gizmo_event(SLAGizmoEventType action, const Vec2d& mous GLCanvas3D::ClippingPlane GLCanvas3D::Gizmos::get_sla_clipping_plane() const { - if (!m_enabled) - return ClippingPlane(); + if (!m_enabled || m_current != SlaSupports) + return ClippingPlane::ClipsNothing(); GizmosMap::const_iterator it = m_gizmos.find(SlaSupports); if (it != m_gizmos.end()) return reinterpret_cast(it->second)->get_sla_clipping_plane(); - return ClippingPlane(); + return ClippingPlane::ClipsNothing(); } @@ -4602,7 +4602,12 @@ void GLCanvas3D::_picking_pass() const ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_camera_clipping_plane = m_gizmos.get_sla_clipping_plane(); + ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data()); + ::glEnable(GL_CLIP_PLANE0); _render_volumes(true); + ::glDisable(GL_CLIP_PLANE0); + m_gizmos.render_current_gizmo_for_picking_pass(m_selection); if (m_multisample_allowed) @@ -4700,25 +4705,6 @@ void GLCanvas3D::set_ortho_projection(float w, float h, float near, float far) c } -void GLCanvas3D::set_sla_clipping(bool enable) const -{ - if (m_gizmos.get_current_type() != Gizmos::SlaSupports) - return; - - if (enable) { - ClippingPlane gizmo_clipping_plane; - try { - gizmo_clipping_plane = m_gizmos.get_sla_clipping_plane(); - } - catch (...) { return; } - - ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)gizmo_clipping_plane.get_data()); - ::glEnable(GL_CLIP_PLANE0); - } - else - ::glDisable(GL_CLIP_PLANE0); -} - void GLCanvas3D::_render_objects() const { @@ -4728,7 +4714,7 @@ void GLCanvas3D::_render_objects() const ::glEnable(GL_LIGHTING); ::glEnable(GL_DEPTH_TEST); - set_sla_clipping(true); + m_camera_clipping_plane = m_gizmos.get_sla_clipping_plane(); if (m_use_VBOs) { @@ -4750,6 +4736,8 @@ void GLCanvas3D::_render_objects() const else m_volumes.set_z_range(-FLT_MAX, FLT_MAX); + m_volumes.set_clipping_plane(m_camera_clipping_plane.get_data()); + m_shader.start_using(); if (m_picking_enabled && m_layers_editing.is_enabled() && m_layers_editing.last_object_id != -1) { int object_id = m_layers_editing.last_object_id; @@ -4770,6 +4758,9 @@ void GLCanvas3D::_render_objects() const } else { + ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_camera_clipping_plane.get_data()); + ::glEnable(GL_CLIP_PLANE0); + if (m_use_clipping_planes) { ::glClipPlane(GL_CLIP_PLANE1, (GLdouble*)m_clipping_planes[0].get_data()); @@ -4777,6 +4768,7 @@ void GLCanvas3D::_render_objects() const ::glClipPlane(GL_CLIP_PLANE2, (GLdouble*)m_clipping_planes[1].get_data()); ::glEnable(GL_CLIP_PLANE2); } + // do not cull backfaces to show broken geometry, if any m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled, [this](const GLVolume& volume) { @@ -4784,15 +4776,16 @@ void GLCanvas3D::_render_objects() const }); m_volumes.render_legacy(GLVolumeCollection::Transparent, false); + ::glDisable(GL_CLIP_PLANE0); + if (m_use_clipping_planes) { ::glDisable(GL_CLIP_PLANE1); ::glDisable(GL_CLIP_PLANE2); } } - - set_sla_clipping(false); - + + m_camera_clipping_plane = ClippingPlane::ClipsNothing(); ::glDisable(GL_LIGHTING); } @@ -4835,8 +4828,6 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const if (!fake_colors) ::glEnable(GL_LIGHTING); - set_sla_clipping(true); - // do not cull backfaces to show broken geometry, if any ::glDisable(GL_CULL_FACE); @@ -4875,8 +4866,6 @@ void GLCanvas3D::_render_volumes(bool fake_colors) const ::glEnable(GL_CULL_FACE); - set_sla_clipping(false); - if (!fake_colors) ::glDisable(GL_LIGHTING); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index b09f3746f..0245b8d6c 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -354,6 +354,8 @@ public: m_data[3] = offset; } + static ClippingPlane ClipsNothing() { return ClippingPlane(Vec3d(0., 0., 1.), DBL_MAX); } + const double* get_data() const { return m_data; } }; @@ -561,6 +563,7 @@ private: mutable Gizmos m_gizmos; mutable GLToolbar m_toolbar; ClippingPlane m_clipping_planes[2]; + mutable ClippingPlane m_camera_clipping_plane; bool m_use_clipping_planes; mutable SlaCap m_sla_caps[2]; std::string m_sidebar_field; @@ -778,9 +781,6 @@ private: // Sets current projection matrix to ortho, accounting for current camera zoom. void set_ortho_projection(float w, float h, float near, float far) const; - // Set/unset near clipping plane according to SLA gizmo requirements. - void set_sla_clipping(bool enable) const; - void _start_timer(); void _stop_timer(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 65be22b44..dce7f64dc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -615,7 +615,7 @@ void GLGizmoSlaSupports::update_cache_entry_normal(unsigned int i) const GLCanvas3D::ClippingPlane GLGizmoSlaSupports::get_sla_clipping_plane() const { if (!m_model_object) - throw std::invalid_argument("GLGizmoSlaSupports::get_sla_clipping_plane() has no model object pointer."); + return GLCanvas3D::ClippingPlane::ClipsNothing(); Eigen::Matrix modelview_matrix; ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data());