diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index b35ccbc6d..c210461b2 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -68,6 +68,8 @@ #define DISABLE_ALLOW_NEGATIVE_Z_FOR_SLA (1 && ENABLE_ALLOW_NEGATIVE_Z) // Enable visualization of objects clearance for sequential prints #define ENABLE_SEQUENTIAL_LIMITS (1 && ENABLE_2_4_0_ALPHA0) +// Enable delayed rendering of transparent volumes +#define ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_2_4_0_ALPHA0) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 61b7e34fc..2463ae709 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -752,17 +752,15 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo { GLVolume* volume = volumes[i]; bool is_transparent = (volume->render_color[3] < 1.0f); - if ((((type == GLVolumeCollection::Opaque) && !is_transparent) || - ((type == GLVolumeCollection::Transparent) && is_transparent) || - (type == GLVolumeCollection::All)) && + if ((((type == GLVolumeCollection::ERenderType::Opaque) && !is_transparent) || + ((type == GLVolumeCollection::ERenderType::Transparent) && is_transparent) || + (type == GLVolumeCollection::ERenderType::All)) && (! filter_func || filter_func(*volume))) list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0))); } - if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) - { - for (GLVolumeWithIdAndZ& volume : list) - { + if (type == GLVolumeCollection::ERenderType::Transparent && list.size() > 1) { + for (GLVolumeWithIdAndZ& volume : list) { volume.second.second = volume.first->bounding_box().transformed(view_matrix * volume.first->world_matrix()).max(2); } @@ -770,8 +768,7 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.second.second < v2.second.second; } ); } - else if ((type == GLVolumeCollection::Opaque) && (list.size() > 1)) - { + else if (type == GLVolumeCollection::ERenderType::Opaque && list.size() > 1) { std::sort(list.begin(), list.end(), [](const GLVolumeWithIdAndZ& v1, const GLVolumeWithIdAndZ& v2) -> bool { return v1.first->selected && !v2.first->selected; } ); diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index b3c112f39..c7984fc61 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -480,7 +480,7 @@ typedef std::vector GLVolumeWithIdAndZList; class GLVolumeCollection { public: - enum ERenderType : unsigned char + enum class ERenderType : unsigned char { Opaque, Transparent, diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 610259a8b..08389a258 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2593,7 +2593,7 @@ void GCodeViewer::render_shells() const // glsafe(::glDepthMask(GL_FALSE)); shader->start_using(); - m_shells.volumes.render(GLVolumeCollection::Transparent, true, wxGetApp().plater()->get_camera().get_view_matrix()); + m_shells.volumes.render(GLVolumeCollection::ERenderType::Transparent, true, wxGetApp().plater()->get_camera().get_view_matrix()); shader->stop_using(); // glsafe(::glDepthMask(GL_TRUE)); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a1e9ed30a..ba9944483 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1475,12 +1475,20 @@ void GLCanvas3D::render() glsafe(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); _render_background(); +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + _render_objects(GLVolumeCollection::ERenderType::Opaque); +#else _render_objects(); +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING if (!m_main_toolbar.is_enabled()) _render_gcode(); _render_sla_slices(); _render_selection(); _render_bed(!camera.is_looking_downward(), true); +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + _render_objects(GLVolumeCollection::ERenderType::Transparent); +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + #if ENABLE_SEQUENTIAL_LIMITS _render_sequential_clearance(); #endif // ENABLE_SEQUENTIAL_LIMITS @@ -5036,7 +5044,11 @@ void GLCanvas3D::_render_bed(bool bottom, bool show_axes) wxGetApp().plater()->get_bed().render(*this, bottom, scale_factor, show_axes, show_texture); } +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING +void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type) +#else void GLCanvas3D::_render_objects() +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING { if (m_volumes.empty()) return; @@ -5067,37 +5079,63 @@ void GLCanvas3D::_render_objects() if (shader != nullptr) { shader->start_using(); - if (m_picking_enabled && !m_gizmos.is_dragging() && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) { - int object_id = m_layers_editing.last_object_id; - m_volumes.render(GLVolumeCollection::Opaque, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) { - // Which volume to paint without the layer height profile shader? - return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); - }); - // Let LayersEditing handle rendering of the active object using the layer height profile shader. - m_layers_editing.render_volumes(*this, m_volumes); - } else { - // do not cull backfaces to show broken geometry, if any - m_volumes.render(GLVolumeCollection::Opaque, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this](const GLVolume& volume) { - return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0); - }); - } - - // In case a painting gizmo is open, it should render the painted triangles - // before transparent objects are rendered. Otherwise they would not be - // visible when inside modifier meshes etc. +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + switch (type) { - const GLGizmosManager& gm = get_gizmos_manager(); - GLGizmosManager::EType type = gm.get_current_type(); - if (type == GLGizmosManager::FdmSupports - || type == GLGizmosManager::Seam - || type == GLGizmosManager::MmuSegmentation) { - shader->stop_using(); - gm.render_painter_gizmo(); - shader->start_using(); + default: + case GLVolumeCollection::ERenderType::Opaque: + { +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + if (m_picking_enabled && !m_gizmos.is_dragging() && m_layers_editing.is_enabled() && (m_layers_editing.last_object_id != -1) && (m_layers_editing.object_max_z() > 0.0f)) { + int object_id = m_layers_editing.last_object_id; +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) { +#else + m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, wxGetApp().plater()->get_camera().get_view_matrix(), [object_id](const GLVolume& volume) { +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + // Which volume to paint without the layer height profile shader? + return volume.is_active && (volume.is_modifier || volume.composite_id.object_id != object_id); + }); + // Let LayersEditing handle rendering of the active object using the layer height profile shader. + m_layers_editing.render_volumes(*this, m_volumes); + } + else { + // do not cull backfaces to show broken geometry, if any +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + m_volumes.render(type, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this](const GLVolume& volume) { +#else + m_volumes.render(GLVolumeCollection::ERenderType::Opaque, m_picking_enabled, wxGetApp().plater()->get_camera().get_view_matrix(), [this](const GLVolume& volume) { +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + return (m_render_sla_auxiliaries || volume.composite_id.volume_id >= 0); + }); } - } - m_volumes.render(GLVolumeCollection::Transparent, false, wxGetApp().plater()->get_camera().get_view_matrix()); + // In case a painting gizmo is open, it should render the painted triangles + // before transparent objects are rendered. Otherwise they would not be + // visible when inside modifier meshes etc. + { + const GLGizmosManager& gm = get_gizmos_manager(); + GLGizmosManager::EType type = gm.get_current_type(); + if (type == GLGizmosManager::FdmSupports + || type == GLGizmosManager::Seam + || type == GLGizmosManager::MmuSegmentation) { + shader->stop_using(); + gm.render_painter_gizmo(); + shader->start_using(); + } + } +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + break; + } + case GLVolumeCollection::ERenderType::Transparent: + { + m_volumes.render(type, false, wxGetApp().plater()->get_camera().get_view_matrix()); + break; + } + } +#else + m_volumes.render(GLVolumeCollection::ERenderType::Transparent, false, wxGetApp().plater()->get_camera().get_view_matrix()); +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING shader->stop_using(); } @@ -5258,8 +5296,8 @@ void GLCanvas3D::_render_volumes_for_picking() const const Transform3d& view_matrix = wxGetApp().plater()->get_camera().get_view_matrix(); for (size_t type = 0; type < 2; ++ type) { - GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::Opaque : GLVolumeCollection::Transparent, view_matrix); - for (const GLVolumeWithIdAndZ& volume : to_render) + GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::ERenderType::Opaque : GLVolumeCollection::ERenderType::Transparent, view_matrix); + for (const GLVolumeWithIdAndZ& volume : to_render) if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) { // Object picking mode. Render the object with a color encoding the object index. unsigned int id = volume.second.first; diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 2c2489b96..aa999a409 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -822,7 +822,11 @@ private: void _rectangular_selection_picking_pass(); void _render_background() const; void _render_bed(bool bottom, bool show_axes); +#if ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING + void _render_objects(GLVolumeCollection::ERenderType type); +#else void _render_objects(); +#endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING void _render_gcode() const; void _render_selection() const; #if ENABLE_SEQUENTIAL_LIMITS