diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 5d49c3675..aa1e49e83 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -44,6 +44,8 @@ #define ENABLE_RENDER_SELECTION_CENTER (0 && ENABLE_1_42_0) // Show visual hints in the 3D scene when sidebar matrix fields have focus #define ENABLE_SIDEBAR_VISUAL_HINTS (1 && ENABLE_1_42_0) +// Separate rendering for opaque and transparent volumes +#define ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING (1 && ENABLE_1_42_0) #endif // _technologies_h_ diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 961d4822a..139672d08 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -797,6 +797,9 @@ int GLVolumeCollection::load_object_volume( color[2] = 1.0f; } color[3] = model_volume->is_model_part() ? 1.f : 0.5f; */ +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + color[3] = model_volume->is_model_part() ? 1.f : 0.5f; +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING this->volumes.emplace_back(new GLVolume(color)); GLVolume &v = *this->volumes.back(); v.set_color_from_model_volume(model_volume); @@ -953,12 +956,54 @@ int GLVolumeCollection::load_wipe_tower_preview( return int(this->volumes.size() - 1); } +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +typedef std::pair GLVolumeWithZ; +typedef std::vector GLVolumesWithZList; +GLVolumesWithZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCollection::ERenderType type) +{ + GLVolumesWithZList list; + + for (GLVolume* volume : volumes) + { + bool is_transparent = (volume->render_color[3] < 1.0f); + if (((type == GLVolumeCollection::Opaque) && !is_transparent) || + ((type == GLVolumeCollection::Transparent) && is_transparent) || + (type == GLVolumeCollection::All)) + list.push_back(std::make_pair(volume, 0.0)); + } + + if ((type == GLVolumeCollection::Transparent) && (list.size() > 1)) + { + Transform3d modelview_matrix; + ::glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix.data()); + + for (GLVolumeWithZ& volume : list) + { + volume.second = volume.first->bounding_box.transformed(modelview_matrix * volume.first->world_matrix()).max(2); + } + + std::sort(list.begin(), list.end(), + [](const GLVolumeWithZ& v1, const GLVolumeWithZ& v2) -> bool { return v1.second < v2.second; } + ); + } + + return list; +} + +void GLVolumeCollection::render_VBOs(GLVolumeCollection::ERenderType type, bool disable_cullface) const +#else void GLVolumeCollection::render_VBOs() const +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING { ::glEnable(GL_BLEND); ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ::glCullFace(GL_BACK); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glDisable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + ::glEnableClientState(GL_VERTEX_ARRAY); ::glEnableClientState(GL_NORMAL_ARRAY); @@ -980,6 +1025,18 @@ void GLVolumeCollection::render_VBOs() const if (z_range_id != -1) ::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + GLVolumesWithZList to_render = volumes_to_render(this->volumes, type); + for (GLVolumeWithZ& volume : to_render) + { + if (volume.first->layer_height_texture_data.can_use()) + volume.first->generate_layer_height_texture(volume.first->layer_height_texture_data.print_object, false); + else + volume.first->set_render_color(); + + volume.first->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); + } +#else for (GLVolume *volume : this->volumes) { if (volume->layer_height_texture_data.can_use()) @@ -989,6 +1046,7 @@ void GLVolumeCollection::render_VBOs() const volume->render_VBOs(color_id, print_box_detection_id, print_box_worldmatrix_id); } +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING ::glBindBuffer(GL_ARRAY_BUFFER, 0); ::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -996,27 +1054,55 @@ void GLVolumeCollection::render_VBOs() const ::glDisableClientState(GL_VERTEX_ARRAY); ::glDisableClientState(GL_NORMAL_ARRAY); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glEnable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + ::glDisable(GL_BLEND); } +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +void GLVolumeCollection::render_legacy(ERenderType type, bool disable_cullface) const +#else void GLVolumeCollection::render_legacy() const +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glCullFace(GL_BACK); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glDisable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + GLVolumesWithZList to_render = volumes_to_render(this->volumes, type); + for (GLVolumeWithZ& volume : to_render) + { + volume.first->set_render_color(); + volume.first->render_legacy(); + } +#else for (GLVolume *volume : this->volumes) { volume->set_render_color(); volume->render_legacy(); } +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (disable_cullface) + ::glEnable(GL_CULL_FACE); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + glDisable(GL_BLEND); } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 76cacabbd..b5ae5b965 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -500,6 +500,17 @@ typedef std::vector GLVolumePtrs; class GLVolumeCollection { +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +public: + enum ERenderType : unsigned char + { + Opaque, + Transparent, + All + }; + +private: +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // min and max vertex of the print box volume float print_box_min[3]; float print_box_max[3]; @@ -544,8 +555,13 @@ public: int obj_idx, float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool use_VBOs, bool size_unknown, float brim_width); // Render the volumes by OpenGL. +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + void render_VBOs(ERenderType type, bool disable_cullface) const; + void render_legacy(ERenderType type, bool disable_cullface) const; +#else void render_VBOs() const; void render_legacy() const; +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 66d4622fe..c650db329 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4313,7 +4313,13 @@ void GLCanvas3D::render() ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); _render_background(); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + // textured bed needs to be rendered after objects if the texture is transparent + bool early_bed_render = is_custom_bed || (theta <= 90.0f); + if (early_bed_render) +#else if (is_custom_bed) // untextured bed needs to be rendered before objects +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING _render_bed(theta); _render_objects(); @@ -4322,7 +4328,11 @@ void GLCanvas3D::render() _render_axes(); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + if (!early_bed_render) +#else if (!is_custom_bed) // textured bed needs to be rendered after objects +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING _render_bed(theta); #if ENABLE_RENDER_SELECTION_CENTER @@ -6119,7 +6129,7 @@ float GLCanvas3D::_get_zoom_to_bounding_box_factor(const BoundingBoxf3& bbox) co // margin factor to give some empty space around the bbox double margin_factor = 1.25; - for (const Vec3d v : vertices) + for (const Vec3d& v : vertices) { // project vertex on the plane perpendicular to camera forward axis Vec3d pos(v(0) - bb_center(0), v(1) - bb_center(1), v(2) - bb_center(2)); @@ -6328,8 +6338,10 @@ void GLCanvas3D::_render_objects() const m_volumes.set_print_box((float)bed_bb.min(0), (float)bed_bb.min(1), 0.0f, (float)bed_bb.max(0), (float)bed_bb.max(1), (float)m_config->opt_float("max_print_height")); m_volumes.check_outside_state(m_config, nullptr); } +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // do not cull backfaces to show broken geometry, if any ::glDisable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING } if (m_use_clipping_planes) @@ -6338,11 +6350,19 @@ void GLCanvas3D::_render_objects() const m_volumes.set_z_range(-FLT_MAX, FLT_MAX); m_shader.start_using(); +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + // do not cull backfaces to show broken geometry, if any + m_volumes.render_VBOs(GLVolumeCollection::Opaque, m_picking_enabled); + m_volumes.render_VBOs(GLVolumeCollection::Transparent, false); +#else m_volumes.render_VBOs(); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING m_shader.stop_using(); +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING if (m_picking_enabled) ::glEnable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING } else { @@ -6354,14 +6374,24 @@ void GLCanvas3D::_render_objects() const ::glEnable(GL_CLIP_PLANE1); } +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING // do not cull backfaces to show broken geometry, if any if (m_picking_enabled) ::glDisable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +#if ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING + // do not cull backfaces to show broken geometry, if any + m_volumes.render_legacy(GLVolumeCollection::Opaque, m_picking_enabled); + m_volumes.render_legacy(GLVolumeCollection::Transparent, false); +#else m_volumes.render_legacy(); +#endif // ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING +#if !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING if (m_picking_enabled) ::glEnable(GL_CULL_FACE); +#endif // !ENABLE_IMPROVED_TRANSPARENT_VOLUMES_RENDERING if (m_use_clipping_planes) {