From 8c8e908325adb2c7f97bb4eaf5e6c9567530fa09 Mon Sep 17 00:00:00 2001
From: enricoturri1966 <enricoturri@seznam.cz>
Date: Fri, 18 Mar 2022 13:34:53 +0100
Subject: [PATCH 1/6] Tech ENABLE_PROCESS_G2_G3_LINES - Processing of gcode G2
 and G3 lines

---
 src/libslic3r/GCode/GCodeProcessor.cpp | 286 +++++++++++++++++++++++--
 src/libslic3r/GCode/GCodeProcessor.hpp |   9 +
 src/libslic3r/Technologies.hpp         |   2 +
 src/slic3r/GUI/GUI_Preview.cpp         |  31 +++
 4 files changed, 311 insertions(+), 17 deletions(-)

diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp
index 3bf7c4ffd..9e98e4da4 100644
--- a/src/libslic3r/GCode/GCodeProcessor.cpp
+++ b/src/libslic3r/GCode/GCodeProcessor.cpp
@@ -36,6 +36,10 @@ static const float DEFAULT_FILAMENT_DIAMETER = 1.75f;
 static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
 static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
 
+#if ENABLE_PROCESS_G2_G3_LINES
+static const std::string INTERNAL_G2G3_TAG = "!#!#! from G2/G3 expansion !#!#!";
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
 namespace Slic3r {
 
 const std::vector<std::string> GCodeProcessor::Reserved_Tags = {
@@ -1596,6 +1600,10 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line, bool
                 switch (cmd[1]) {
                 case '0': { process_G0(line); break; }  // Move
                 case '1': { process_G1(line); break; }  // Move
+#if ENABLE_PROCESS_G2_G3_LINES
+                case '2': { process_G2_G3(line, true); break; }   // CW Arc Move
+                case '3': { process_G2_G3(line, false); break; }  // CCW Arc Move
+#endif // ENABLE_PROCESS_G2_G3_LINES
                 default: break;
                 }
                 break;
@@ -2453,9 +2461,10 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line)
 
 void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
 {
-    float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
-    float filament_radius = 0.5f * filament_diameter;
-    float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
+    const float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
+    const float filament_radius = 0.5f * filament_diameter;
+    const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
+#if !ENABLE_PROCESS_G2_G3_LINES
     auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
         bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
         if (axis == E)
@@ -2471,6 +2480,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
         else
             return m_start_position[axis];
     };
+#endif // !ENABLE_PROCESS_G2_G3_LINES
 
     auto move_type = [this](const AxisCoords& delta_pos) {
         EMoveType type = EMoveType::Noop;
@@ -2498,7 +2508,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
 
     // updates axes positions from line
     for (unsigned char a = X; a <= E; ++a) {
+#if ENABLE_PROCESS_G2_G3_LINES
+        m_end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
+#else
         m_end_position[a] = absolute_position((Axis)a, line);
+#endif // ENABLE_PROCESS_G2_G3_LINES
     }
 
     // updates feedrate from line, if present
@@ -2517,11 +2531,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
     if (max_abs_delta == 0.0f)
         return;
 
-    EMoveType type = move_type(delta_pos);
+    const EMoveType type = move_type(delta_pos);
     if (type == EMoveType::Extrude) {
-        float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
-        float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
-        float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
+        const float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
+        const float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
+        const float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
 
         // save extruded volume to the cache
         m_used_filaments.increase_caches(volume_extruded_filament);
@@ -2532,12 +2546,23 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
         m_mm3_per_mm_compare.update(area_toolpath_cross_section, m_extrusion_role);
 #endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
 
+#if ENABLE_PROCESS_G2_G3_LINES
+        if (m_forced_height > 0.0f)
+            m_height = m_forced_height;
+        else if (m_layer_id == 0)
+            m_height = (m_end_position[Z] <= double(m_first_layer_height)) ? m_end_position[Z] : m_first_layer_height;
+        else if (line.comment() != INTERNAL_G2G3_TAG){
+            if (m_end_position[Z] > m_extruded_last_z + EPSILON && delta_pos[Z] == 0.0)
+                m_height = m_end_position[Z] - m_extruded_last_z;
+        }
+#else
         if (m_forced_height > 0.0f)
             m_height = m_forced_height;
         else {
             if (m_end_position[Z] > m_extruded_last_z + EPSILON)
                 m_height = m_end_position[Z] - m_extruded_last_z;
         }
+#endif // ENABLE_PROCESS_G2_G3_LINES
 
         if (m_height == 0.0f)
             m_height = DEFAULT_TOOLPATH_HEIGHT;
@@ -2545,7 +2570,10 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
         if (m_end_position[Z] == 0.0f)
             m_end_position[Z] = m_height;
 
-        m_extruded_last_z = m_end_position[Z];
+#if ENABLE_PROCESS_G2_G3_LINES
+        if (line.comment() != INTERNAL_G2G3_TAG)
+#endif // ENABLE_PROCESS_G2_G3_LINES
+            m_extruded_last_z = m_end_position[Z];
         m_options_z_corrector.update(m_height);
 
 #if ENABLE_GCODE_VIEWER_DATA_CHECKING
@@ -2585,9 +2613,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
         return delta_pos[X] == 0.0f && delta_pos[Y] == 0.0f && delta_pos[Z] == 0.0f && delta_pos[E] != 0.0f;
     };
 
-    float distance = move_length(delta_pos);
+    const float distance = move_length(delta_pos);
     assert(distance != 0.0f);
-    float inv_distance = 1.0f / distance;
+    const float inv_distance = 1.0f / distance;
 
     for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::Count); ++i) {
         TimeMachine& machine = m_time_processor.machines[i];
@@ -2618,7 +2646,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
 
             curr.abs_axis_feedrate[a] = std::abs(curr.axis_feedrate[a]);
             if (curr.abs_axis_feedrate[a] != 0.0f) {
-                float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
+                const float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
                 if (axis_max_feedrate != 0.0f)
                     min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
             }
@@ -2641,7 +2669,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
                 get_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i)));
 
         for (unsigned char a = X; a <= E; ++a) {
-            float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
+            const float axis_max_acceleration = get_axis_max_acceleration(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
             if (acceleration * std::abs(delta_pos[a]) * inv_distance > axis_max_acceleration)
                 acceleration = axis_max_acceleration;
         }
@@ -2652,7 +2680,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
         curr.safe_feedrate = block.feedrate_profile.cruise;
 
         for (unsigned char a = X; a <= E; ++a) {
-            float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
+            const float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
             if (curr.abs_axis_feedrate[a] > axis_max_jerk)
                 curr.safe_feedrate = std::min(curr.safe_feedrate, axis_max_jerk);
         }
@@ -2686,7 +2714,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
                 }
 
                 // Calculate the jerk depending on whether the axis is coasting in the same direction or reversing a direction.
-                float jerk =
+                const float jerk =
                     (v_exit > v_entry) ?
                     ((v_entry > 0.0f || v_exit < 0.0f) ?
                         // coasting
@@ -2700,7 +2728,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
                         // axis reversal
                         std::max(-v_exit, v_entry));
 
-                float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
+                const float axis_max_jerk = get_axis_max_jerk(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
                 if (jerk > axis_max_jerk) {
                     v_factor *= axis_max_jerk / jerk;
                     limited = true;
@@ -2712,14 +2740,14 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
 
             // Now the transition velocity is known, which maximizes the shared exit / entry velocity while
             // respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
-            float vmax_junction_threshold = vmax_junction * 0.99f;
+            const float vmax_junction_threshold = vmax_junction * 0.99f;
 
             // Not coasting. The machine will stop and start the movements anyway, better to start the segment from start.
             if (prev.safe_feedrate > vmax_junction_threshold && curr.safe_feedrate > vmax_junction_threshold)
                 vmax_junction = curr.safe_feedrate;
         }
 
-        float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
+        const float v_allowable = max_allowable_speed(-acceleration, curr.safe_feedrate, block.distance);
         block.feedrate_profile.entry = std::min(vmax_junction, v_allowable);
 
         block.max_entry_speed = vmax_junction;
@@ -2781,6 +2809,211 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
     store_move_vertex(type);
 }
 
+#if ENABLE_PROCESS_G2_G3_LINES
+void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise)
+{
+    if (!line.has('X') || !line.has('Y') || !line.has('I') || !line.has('J'))
+        return;
+
+    // relative center
+    Vec3f rel_center = Vec3f::Zero();
+    if (!line.has_value('I', rel_center.x()) || !line.has_value('J', rel_center.y()))
+        return;
+
+    // scale center, if needed
+    if (m_units == EUnits::Inches)
+        rel_center *= INCHES_TO_MM;
+
+    struct Arc
+    {
+        Vec3d start{ Vec3d::Zero() };
+        Vec3d end{ Vec3d::Zero() };
+        Vec3d center{ Vec3d::Zero() };
+
+        double angle{ 0.0 };
+        double delta_x() const { return end.x() - start.x(); }
+        double delta_y() const { return end.y() - start.y(); }
+        double delta_z() const { return end.z() - start.z(); }
+
+        double length() const { return angle * start_radius(); }
+        double travel_length() const { return std::sqrt(sqr(length() + sqr(delta_z()))); }
+        double start_radius() const { return (start - center).norm(); }
+        double end_radius() const { return (end - center).norm(); }
+
+        Vec3d relative_start() const { return start - center; }
+        Vec3d relative_end() const { return end - center; }
+
+        bool closed() const { return end.isApprox(start); }
+    };
+
+    Arc arc;
+
+    // arc start endpoint
+    arc.start = Vec3d(m_start_position[X], m_start_position[Y], m_start_position[Z]);
+
+    // arc center
+    arc.center = arc.start + rel_center.cast<double>();
+
+    const float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_result.filament_diameters.size()) ? m_result.filament_diameters[m_extruder_id] : m_result.filament_diameters.back();
+    const float filament_radius = 0.5f * filament_diameter;
+    const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
+
+    AxisCoords end_position = m_start_position;
+    for (unsigned char a = X; a <= E; ++a) {
+        end_position[a] = extract_absolute_position_on_axis((Axis)a, line, double(area_filament_cross_section));
+    }
+
+    // arc end endpoint
+    arc.end = Vec3d(end_position[X], end_position[Y], end_position[Z]);
+
+    // radii
+    if (std::abs(arc.end_radius() - arc.start_radius()) > EPSILON) {
+        // what to do ???
+    }
+
+    // updates feedrate from line
+    std::optional<float> feedrate;
+    if (line.has_f())
+        feedrate = m_feed_multiply.current * line.f() * MMMIN_TO_MMSEC;
+
+    // updates extrusion from line
+    std::optional<float> extrusion;
+    if (line.has_e())
+        extrusion = end_position[E] - m_start_position[E];
+
+    // relative arc endpoints
+    const Vec3d rel_arc_start = arc.relative_start();
+    const Vec3d rel_arc_end   = arc.relative_end();
+
+    // arc angle
+    if (arc.closed())
+        arc.angle = 2.0 * PI;
+    else {
+        arc.angle = std::atan2(rel_arc_start.x() * rel_arc_end.y() - rel_arc_start.y() * rel_arc_end.x(),
+            rel_arc_start.x() * rel_arc_end.x() + rel_arc_start.y() * rel_arc_end.y());
+        if (arc.angle < 0.0)
+            arc.angle += 2.0 * PI;
+        if (clockwise)
+            arc.angle -= 2.0 * PI;
+    }
+
+    const double travel_length = arc.travel_length();
+    if (travel_length < 0.001)
+        return;
+
+    auto adjust_target = [this, area_filament_cross_section](const AxisCoords& target, const AxisCoords& prev_position) {
+        AxisCoords ret = target;
+        if (m_global_positioning_type == EPositioningType::Relative) {
+            for (unsigned char a = X; a <= E; ++a) {
+                ret[a] -= prev_position[a];
+            }
+        }
+        else if (m_e_local_positioning_type == EPositioningType::Relative)
+            ret[E] -= prev_position[E];
+
+        if (m_use_volumetric_e)
+            ret[E] *= area_filament_cross_section;
+
+        const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
+        for (unsigned char a = X; a <= E; ++a) {
+            ret[a] /= lengthsScaleFactor;
+        }
+        return ret;
+    };
+
+    auto fake_g1_line = [this](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
+        std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str();
+        if (has_z)
+            ret += (boost::format(" Z%1%") % target[Z]).str();
+        if (feedrate.has_value())
+            ret += (boost::format(" F%1%") % feedrate.value()).str();
+        if (extrusion.has_value())
+            ret += (boost::format(" E%1%") % target[E]).str();
+
+        ret += (boost::format(" ;%1%\n") % INTERNAL_G2G3_TAG).str();
+
+        return ret;
+    };
+
+    // calculate arc segments
+    // reference:
+    // Prusa-Firmware\Firmware\motion_control.cpp - mc_arc()
+
+    // segments count
+    static const double MM_PER_ARC_SEGMENT = 1.0;
+    const size_t segments = std::max<size_t>(std::floor(travel_length / MM_PER_ARC_SEGMENT), 1);
+
+    const double theta_per_segment = arc.angle / double(segments);
+    const double z_per_segment = arc.delta_z() / double(segments);
+    const double extruder_per_segment = (extrusion.has_value()) ? extrusion.value() / double(segments) : 0.0;
+
+    double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation
+    double sin_T = theta_per_segment;
+
+    AxisCoords prev_target = m_start_position;
+    AxisCoords arc_target;
+    double sin_Ti;
+    double cos_Ti;
+    double r_axisi;
+    size_t count = 0;
+
+    // Initialize the linear axis
+    arc_target[Z] = m_start_position[Z];
+
+    // Initialize the extruder axis
+    arc_target[E] = m_start_position[E];
+
+    static const size_t N_ARC_CORRECTION = 25;
+
+    Vec3d curr_rel_arc_start = arc.relative_start();
+    Vec3d curr_rel_arc_end   = arc.relative_end();
+
+    std::string gcode;
+
+    for (size_t i = 1; i < segments; ++i) { // Increment (segments-1)
+        if (count < N_ARC_CORRECTION) {
+            // Apply vector rotation matrix 
+            r_axisi = curr_rel_arc_start.x() * sin_T + curr_rel_arc_start.y() * cos_T;
+            curr_rel_arc_start.x() = curr_rel_arc_start.x() * cos_T - curr_rel_arc_start.y() * sin_T;
+            curr_rel_arc_start.y() = r_axisi;
+            count++;
+        }
+        else {
+            // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
+            // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
+            cos_Ti = ::cos(double(i) * theta_per_segment);
+            sin_Ti = ::sin(double(i) * theta_per_segment);
+            curr_rel_arc_start.x() = -double(rel_center.x()) * cos_Ti + double(rel_center.y()) * sin_Ti;
+            curr_rel_arc_start.y() = -double(rel_center.x()) * sin_Ti - double(rel_center.y()) * cos_Ti;
+            count = 0;
+        }
+
+        // Update arc_target location
+        arc_target[X] = arc.center.x() + curr_rel_arc_start.x();
+        arc_target[Y] = arc.center.y() + curr_rel_arc_start.y();
+        arc_target[Z] += z_per_segment;
+        arc_target[E] += extruder_per_segment;
+
+        gcode += fake_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion);
+        prev_target = arc_target;
+
+        // feedrate is constant, we do not need to repeat it
+        feedrate.reset();
+    }
+
+    // Ensure last segment arrives at target location.
+    gcode += fake_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion);
+
+    // process fake gcode lines
+    GCodeReader parser;
+    parser.parse_buffer(gcode, [this](GCodeReader&, const GCodeReader::GCodeLine& line) {
+        // force all lines to share the same id
+        --m_line_id;
+        process_gcode_line(line, false);
+        });
+}
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
 void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)
 {
     // stores retract move
@@ -3502,5 +3735,24 @@ void GCodeProcessor::update_estimated_times_stats()
     m_result.print_statistics.used_filaments_per_role   = m_used_filaments.filaments_per_role;
 }
 
+#if ENABLE_PROCESS_G2_G3_LINES
+double GCodeProcessor::extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section)
+{
+    if (line.has(Slic3r::Axis(axis))) {
+        bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
+        if (axis == E)
+            is_relative |= (m_e_local_positioning_type == EPositioningType::Relative);
+
+        const double lengthsScaleFactor = (m_units == EUnits::Inches) ? double(INCHES_TO_MM) : 1.0;
+        double ret = line.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
+        if (axis == E && m_use_volumetric_e)
+            ret /= area_filament_cross_section;
+        return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
+    }
+    else
+        return m_start_position[axis];
+}
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
 } /* namespace Slic3r */
 
diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp
index 25375f61b..59a91dc24 100644
--- a/src/libslic3r/GCode/GCodeProcessor.hpp
+++ b/src/libslic3r/GCode/GCodeProcessor.hpp
@@ -652,6 +652,11 @@ namespace Slic3r {
         void process_G0(const GCodeReader::GCodeLine& line);
         void process_G1(const GCodeReader::GCodeLine& line);
 
+#if ENABLE_PROCESS_G2_G3_LINES
+        // Arc Move
+        void process_G2_G3(const GCodeReader::GCodeLine& line, bool clockwise);
+#endif // ENABLE_PROCESS_G2_G3_LINES
+
         // Retract
         void process_G10(const GCodeReader::GCodeLine& line);
 
@@ -777,6 +782,10 @@ namespace Slic3r {
         void simulate_st_synchronize(float additional_time = 0.0f);
 
         void update_estimated_times_stats();
+
+#if ENABLE_PROCESS_G2_G3_LINES
+        double extract_absolute_position_on_axis(Axis axis, const GCodeReader::GCodeLine& line, double area_filament_cross_section);
+#endif // ENABLE_PROCESS_G2_G3_LINES
    };
 
 } /* namespace Slic3r */
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 635fc4994..f7df9e696 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -84,6 +84,8 @@
 #define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
 // Enable modified rectangle selection
 #define ENABLE_NEW_RECTANGLE_SELECTION (1 && ENABLE_2_5_0_ALPHA1)
+// Enable processing of gcode G2 and G3 lines
+#define ENABLE_PROCESS_G2_G3_LINES (1 && ENABLE_2_5_0_ALPHA1)
 
 
 #endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp
index 2cac5e356..8c1bb7707 100644
--- a/src/slic3r/GUI/GUI_Preview.cpp
+++ b/src/slic3r/GUI/GUI_Preview.cpp
@@ -859,6 +859,36 @@ void Preview::update_moves_slider()
     if (view.endpoints.last < view.endpoints.first)
         return;
 
+#if ENABLE_PROCESS_G2_G3_LINES
+    assert(view.endpoints.first <= view.current.first && view.current.first <= view.endpoints.last);
+    assert(view.endpoints.first <= view.current.last && view.current.last <= view.endpoints.last);
+
+    std::vector<double> values;
+    values.reserve(view.endpoints.last - view.endpoints.first + 1);
+    std::vector<double> alternate_values;
+    alternate_values.reserve(view.endpoints.last - view.endpoints.first + 1);
+    unsigned int last_gcode_id = view.gcode_ids[view.endpoints.first];
+    for (unsigned int i = view.endpoints.first; i <= view.endpoints.last; ++i) {
+        if (i > view.endpoints.first) {
+            // skip consecutive moves with same gcode id (resulting from processing G2 and G3 lines)
+            if (last_gcode_id == view.gcode_ids[i]) {
+                values.back() = static_cast<double>(i + 1);
+                alternate_values.back() = static_cast<double>(view.gcode_ids[i]);
+                continue;
+            }
+            else
+                last_gcode_id = view.gcode_ids[i];
+        }
+
+        values.emplace_back(static_cast<double>(i + 1));
+        alternate_values.emplace_back(static_cast<double>(view.gcode_ids[i]));
+    }
+
+    m_moves_slider->SetSliderValues(values);
+    m_moves_slider->SetSliderAlternateValues(alternate_values);
+    m_moves_slider->SetMaxValue(int(values.size()) - 1);
+    m_moves_slider->SetSelectionSpan(values.front() - 1, values.back() - 1);
+#else
     std::vector<double> values(view.endpoints.last - view.endpoints.first + 1);
     std::vector<double> alternate_values(view.endpoints.last - view.endpoints.first + 1);
     unsigned int count = 0;
@@ -873,6 +903,7 @@ void Preview::update_moves_slider()
     m_moves_slider->SetSliderAlternateValues(alternate_values);
     m_moves_slider->SetMaxValue(view.endpoints.last - view.endpoints.first);
     m_moves_slider->SetSelectionSpan(view.current.first - view.endpoints.first, view.current.last - view.endpoints.first);
+#endif // ENABLE_PROCESS_G2_G3_LINES
 }
 
 void Preview::enable_moves_slider(bool enable)

From 82fe599cae8c7501862b2daf0735aa262a7f6090 Mon Sep 17 00:00:00 2001
From: enricoturri1966 <enricoturri@seznam.cz>
Date: Fri, 18 Mar 2022 14:12:29 +0100
Subject: [PATCH 2/6] Fixed warnings and build on MAC OS

---
 src/libslic3r/GCode/GCodeProcessor.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp
index aaab86bd6..340515d5f 100644
--- a/src/libslic3r/GCode/GCodeProcessor.cpp
+++ b/src/libslic3r/GCode/GCodeProcessor.cpp
@@ -2897,12 +2897,12 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
         return ret;
     };
 
-    auto fake_g1_line = [this](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
+    auto fake_g1_line = [](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
         std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str();
         if (has_z)
             ret += (boost::format(" Z%1%") % target[Z]).str();
         if (feedrate.has_value())
-            ret += (boost::format(" F%1%") % feedrate.value()).str();
+            ret += (boost::format(" F%1%") % *feedrate).str();
         if (extrusion.has_value())
             ret += (boost::format(" E%1%") % target[E]).str();
 
@@ -2921,7 +2921,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
 
     const double theta_per_segment = arc.angle / double(segments);
     const double z_per_segment = arc.delta_z() / double(segments);
-    const double extruder_per_segment = (extrusion.has_value()) ? extrusion.value() / double(segments) : 0.0;
+    const double extruder_per_segment = (extrusion.has_value()) ? *extrusion / double(segments) : 0.0;
 
     double cos_T = 1.0 - 0.5 * sqr(theta_per_segment); // Small angle approximation
     double sin_T = theta_per_segment;
@@ -2942,7 +2942,6 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
     static const size_t N_ARC_CORRECTION = 25;
 
     Vec3d curr_rel_arc_start = arc.relative_start();
-    Vec3d curr_rel_arc_end   = arc.relative_end();
 
     std::string gcode;
 

From 93d703518d588720ff1333e7cd5919fab1a7df50 Mon Sep 17 00:00:00 2001
From: enricoturri1966 <enricoturri@seznam.cz>
Date: Mon, 21 Mar 2022 08:53:55 +0100
Subject: [PATCH 3/6] Tech ENABLE_PROCESS_G2_G3_LINES - Improved detection of
 layer zs for gcode produced by other slicers

---
 src/libslic3r/GCode/GCodeProcessor.cpp | 21 +++++++++++++++++----
 src/libslic3r/GCode/GCodeProcessor.hpp |  7 +++++++
 src/slic3r/GUI/GCodeViewer.cpp         | 20 +++++++++++++-------
 3 files changed, 37 insertions(+), 11 deletions(-)

diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp
index 340515d5f..0851f38ac 100644
--- a/src/libslic3r/GCode/GCodeProcessor.cpp
+++ b/src/libslic3r/GCode/GCodeProcessor.cpp
@@ -37,7 +37,7 @@ static const float DEFAULT_FILAMENT_DENSITY = 1.245f;
 static const Slic3r::Vec3f DEFAULT_EXTRUDER_OFFSET = Slic3r::Vec3f::Zero();
 
 #if ENABLE_PROCESS_G2_G3_LINES
-static const std::string INTERNAL_G2G3_TAG = "!#!#! from G2/G3 expansion !#!#!";
+static const std::string INTERNAL_G2G3_TAG = "!#!#! internal only - from G2/G3 expansion !#!#!";
 #endif // ENABLE_PROCESS_G2_G3_LINES
 
 namespace Slic3r {
@@ -2782,7 +2782,11 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
         m_result.spiral_vase_layers.back().second.second = m_result.moves.size() - 1;
 
     // store move
+#if ENABLE_PROCESS_G2_G3_LINES
+    store_move_vertex(type, line.comment() == INTERNAL_G2G3_TAG);
+#else
     store_move_vertex(type);
+#endif // ENABLE_PROCESS_G2_G3_LINES
 }
 
 #if ENABLE_PROCESS_G2_G3_LINES
@@ -2897,7 +2901,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
         return ret;
     };
 
-    auto fake_g1_line = [](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
+    auto internal_only_g1_line = [](const AxisCoords& target, bool has_z, const std::optional<float>& feedrate, const std::optional<float>& extrusion) {
         std::string ret = (boost::format("G1 X%1% Y%2%") % target[X] % target[Y]).str();
         if (has_z)
             ret += (boost::format(" Z%1%") % target[Z]).str();
@@ -2969,7 +2973,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
         arc_target[Z] += z_per_segment;
         arc_target[E] += extruder_per_segment;
 
-        gcode += fake_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion);
+        gcode += internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, feedrate, extrusion);
         prev_target = arc_target;
 
         // feedrate is constant, we do not need to repeat it
@@ -2977,7 +2981,7 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
     }
 
     // Ensure last segment arrives at target location.
-    gcode += fake_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion);
+    gcode += internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, feedrate, extrusion);
 
     // process fake gcode lines
     GCodeReader parser;
@@ -3489,7 +3493,11 @@ void GCodeProcessor::process_T(const std::string_view command)
     }
 }
 
+#if ENABLE_PROCESS_G2_G3_LINES
+void GCodeProcessor::store_move_vertex(EMoveType type, bool internal_only)
+#else
 void GCodeProcessor::store_move_vertex(EMoveType type)
+#endif // ENABLE_PROCESS_G2_G3_LINES
 {
     m_last_line_id = (type == EMoveType::Color_change || type == EMoveType::Pause_Print || type == EMoveType::Custom_GCode) ?
         m_line_id + 1 :
@@ -3509,7 +3517,12 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
         m_mm3_per_mm,
         m_fan_speed,
         m_extruder_temps[m_extruder_id],
+#if ENABLE_PROCESS_G2_G3_LINES
+        static_cast<float>(m_result.moves.size()),
+        internal_only
+#else
         static_cast<float>(m_result.moves.size())
+#endif // ENABLE_PROCESS_G2_G3_LINES
     });
 
     // stores stop time placeholders for later use
diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp
index 3a2634801..4b406b555 100644
--- a/src/libslic3r/GCode/GCodeProcessor.hpp
+++ b/src/libslic3r/GCode/GCodeProcessor.hpp
@@ -113,6 +113,9 @@ namespace Slic3r {
             float fan_speed{ 0.0f }; // percentage
             float temperature{ 0.0f }; // Celsius degrees
             float time{ 0.0f }; // s
+#if ENABLE_PROCESS_G2_G3_LINES
+            bool internal_only{ false };
+#endif // ENABLE_PROCESS_G2_G3_LINES
 
             float volumetric_rate() const { return feedrate * mm3_per_mm; }
         };
@@ -751,7 +754,11 @@ namespace Slic3r {
         void process_T(const GCodeReader::GCodeLine& line);
         void process_T(const std::string_view command);
 
+#if ENABLE_PROCESS_G2_G3_LINES
+        void store_move_vertex(EMoveType type, bool internal_only = false);
+#else
         void store_move_vertex(EMoveType type);
+#endif // ENABLE_PROCESS_G2_G3_LINES
 
         void set_extrusion_role(ExtrusionRole role);
 
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 5372d4565..a1be81ced 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -2284,13 +2284,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
         size_t move_id = i - seams_count;
 
         if (move.type == EMoveType::Extrude) {
-            // layers zs
-            const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
-            const double z = static_cast<double>(move.position.z());
-            if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
-                m_layers.append(z, { last_travel_s_id, move_id });
-            else
-                m_layers.get_ranges().back().last = move_id;
+#if ENABLE_PROCESS_G2_G3_LINES
+            if (move.extrusion_role != erNone && !move.internal_only) {
+#endif // ENABLE_PROCESS_G2_G3_LINES
+                // layers zs
+                const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back();
+                const double z = static_cast<double>(move.position.z());
+                if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z)
+                    m_layers.append(z, { last_travel_s_id, move_id });
+                else
+                    m_layers.get_ranges().back().last = move_id;
+#if ENABLE_PROCESS_G2_G3_LINES
+            }
+#endif // ENABLE_PROCESS_G2_G3_LINES
             // extruder ids
             m_extruder_ids.emplace_back(move.extruder_id);
             // roles

From 4964d6ecd56133237fc9999b677a71ae5fff2817 Mon Sep 17 00:00:00 2001
From: enricoturri1966 <enricoturri@seznam.cz>
Date: Mon, 21 Mar 2022 11:31:32 +0100
Subject: [PATCH 4/6] ENABLE_GL_IMGUI_SHADERS - Fixes in
 ImGuiWrapper::render_draw_data()

---
 src/slic3r/GUI/ImGuiWrapper.cpp | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp
index 613b16841..e659a386b 100644
--- a/src/slic3r/GUI/ImGuiWrapper.cpp
+++ b/src/slic3r/GUI/ImGuiWrapper.cpp
@@ -1528,19 +1528,15 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
     glsafe(::glLoadIdentity());
 #endif // ENABLE_GL_IMGUI_SHADERS
 
-#if ENABLE_GL_IMGUI_SHADERS
     // Will project scissor/clipping rectangles into framebuffer space
-    const ImVec2 clip_off   = draw_data->DisplayPos;         // (0,0) unless using multi-viewports
+    const ImVec2 clip_off   = draw_data->DisplayPos;       // (0,0) unless using multi-viewports
     const ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
-#else
-    const ImVec2 pos = draw_data->DisplayPos;
-#endif // ENABLE_GL_IMGUI_SHADERS
 
     // Render command lists
     for (int n = 0; n < draw_data->CmdListsCount; ++n) {
         const ImDrawList* cmd_list = draw_data->CmdLists[n];
         const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data;
-        const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
+        const ImDrawIdx* idx_buffer  = cmd_list->IdxBuffer.Data;
 #if ENABLE_GL_IMGUI_SHADERS
         const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
         const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
@@ -1596,18 +1592,20 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
                 glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
                 glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
 #else
-                const ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);
-                if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) {
-                    // Apply scissor/clipping rectangle
-                    glsafe(::glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)));
+                // Project scissor/clipping rectangles into framebuffer space
+                const ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+                const ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
+                if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
+                    continue;
 
-                    // Bind texture, Draw
-                    glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
-                    glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
-                }
+                // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
+                glsafe(::glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)));
+
+                // Bind texture, Draw
+                glsafe(::glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
+                glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset));
 #endif // ENABLE_GL_IMGUI_SHADERS
             }
-            idx_buffer += pcmd->ElemCount;
         }
 
 #if ENABLE_GL_IMGUI_SHADERS

From 76d1d4949bbd0964717f8112aae992a1267c5eb4 Mon Sep 17 00:00:00 2001
From: enricoturri1966 <enricoturri@seznam.cz>
Date: Mon, 21 Mar 2022 13:10:47 +0100
Subject: [PATCH 5/6] Tech ENABLE_GL_SHADERS_ATTRIBUTES - Added shaders for
 glsl version 140

---
 resources/shaders/110/background.fs           | 11 +++
 .../{background_attr.vs => 110/background.vs} |  0
 resources/shaders/110/flat.fs                 |  8 ++
 .../shaders/{flat_attr.vs => 110/flat.vs}     |  4 +-
 resources/shaders/110/flat_texture.fs         | 10 +++
 .../flat_texture.vs}                          |  6 +-
 resources/shaders/110/gouraud.fs              | 86 +++++++++++++++++++
 .../{gouraud_attr.vs => 110/gouraud.vs}       |  6 +-
 resources/shaders/110/gouraud_light.fs        | 12 +++
 .../gouraud_light.vs}                         |  6 +-
 .../shaders/110/gouraud_light_instanced.fs    | 12 +++
 .../gouraud_light_instanced.vs}               |  8 +-
 resources/shaders/{ => 110}/imgui.fs          |  0
 resources/shaders/{ => 110}/imgui.vs          |  0
 .../{mm_contour_attr.fs => 110/mm_contour.fs} |  0
 .../{mm_contour_attr.vs => 110/mm_contour.vs} |  4 +-
 .../{mm_gouraud_attr.fs => 110/mm_gouraud.fs} |  0
 .../{mm_gouraud_attr.vs => 110/mm_gouraud.vs} |  4 +-
 resources/shaders/110/printbed.fs             | 34 ++++++++
 .../{printbed_attr.vs => 110/printbed.vs}     |  6 +-
 resources/shaders/110/toolpaths_cog.fs        | 19 ++++
 .../toolpaths_cog.vs}                         |  6 +-
 .../shaders/110/variable_layer_height.fs      | 41 +++++++++
 .../variable_layer_height.vs}                 |  8 +-
 resources/shaders/140/background.fs           | 11 +++
 resources/shaders/140/background.vs           | 12 +++
 resources/shaders/140/flat.fs                 |  8 ++
 resources/shaders/140/flat.vs                 | 11 +++
 resources/shaders/140/flat_texture.fs         | 10 +++
 resources/shaders/140/flat_texture.vs         | 15 ++++
 resources/shaders/140/gouraud.fs              | 86 +++++++++++++++++++
 resources/shaders/140/gouraud.vs              | 77 +++++++++++++++++
 resources/shaders/140/gouraud_light.fs        | 12 +++
 resources/shaders/140/gouraud_light.vs        | 45 ++++++++++
 .../shaders/140/gouraud_light_instanced.fs    | 12 +++
 .../shaders/140/gouraud_light_instanced.vs    | 50 +++++++++++
 resources/shaders/140/imgui.fs                | 11 +++
 resources/shaders/140/imgui.vs                | 17 ++++
 resources/shaders/140/mm_contour.fs           | 13 +++
 resources/shaders/140/mm_contour.vs           | 11 +++
 resources/shaders/140/mm_gouraud.fs           | 63 ++++++++++++++
 resources/shaders/140/mm_gouraud.vs           | 28 ++++++
 resources/shaders/140/printbed.fs             | 34 ++++++++
 resources/shaders/140/printbed.vs             | 15 ++++
 resources/shaders/140/toolpaths_cog.fs        | 19 ++++
 resources/shaders/140/toolpaths_cog.vs        | 47 ++++++++++
 .../shaders/140/variable_layer_height.fs      | 41 +++++++++
 .../shaders/140/variable_layer_height.vs      | 60 +++++++++++++
 src/slic3r/GUI/3DBed.cpp                      | 16 ----
 src/slic3r/GUI/3DScene.cpp                    |  6 --
 src/slic3r/GUI/GCodeViewer.cpp                | 34 +-------
 src/slic3r/GUI/GLCanvas3D.cpp                 | 49 +----------
 src/slic3r/GUI/GLModel.cpp                    |  4 -
 src/slic3r/GUI/GLSelectionRectangle.cpp       |  4 -
 src/slic3r/GUI/GLShadersManager.cpp           | 27 +++---
 src/slic3r/GUI/GLTexture.cpp                  |  4 -
 src/slic3r/GUI/Gizmos/GLGizmoBase.cpp         |  8 --
 src/slic3r/GUI/Gizmos/GLGizmoCut.cpp          | 12 ---
 src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp      |  8 --
 src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp       |  4 -
 .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp     |  9 +-
 src/slic3r/GUI/Gizmos/GLGizmoMove.cpp         | 16 ----
 src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp  | 26 +-----
 src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp       |  8 --
 src/slic3r/GUI/Gizmos/GLGizmoScale.cpp        | 36 --------
 src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp     | 13 +--
 src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp  |  4 -
 src/slic3r/GUI/MeshUtils.cpp                  |  4 -
 src/slic3r/GUI/Selection.cpp                  | 12 ---
 69 files changed, 994 insertions(+), 309 deletions(-)
 create mode 100644 resources/shaders/110/background.fs
 rename resources/shaders/{background_attr.vs => 110/background.vs} (100%)
 create mode 100644 resources/shaders/110/flat.fs
 rename resources/shaders/{flat_attr.vs => 110/flat.vs} (100%)
 create mode 100644 resources/shaders/110/flat_texture.fs
 rename resources/shaders/{flat_texture_attr.vs => 110/flat_texture.vs} (100%)
 create mode 100644 resources/shaders/110/gouraud.fs
 rename resources/shaders/{gouraud_attr.vs => 110/gouraud.vs} (100%)
 create mode 100644 resources/shaders/110/gouraud_light.fs
 rename resources/shaders/{gouraud_light_attr.vs => 110/gouraud_light.vs} (100%)
 create mode 100644 resources/shaders/110/gouraud_light_instanced.fs
 rename resources/shaders/{gouraud_light_instanced_attr.vs => 110/gouraud_light_instanced.vs} (100%)
 rename resources/shaders/{ => 110}/imgui.fs (100%)
 rename resources/shaders/{ => 110}/imgui.vs (100%)
 rename resources/shaders/{mm_contour_attr.fs => 110/mm_contour.fs} (100%)
 rename resources/shaders/{mm_contour_attr.vs => 110/mm_contour.vs} (100%)
 rename resources/shaders/{mm_gouraud_attr.fs => 110/mm_gouraud.fs} (100%)
 rename resources/shaders/{mm_gouraud_attr.vs => 110/mm_gouraud.vs} (100%)
 create mode 100644 resources/shaders/110/printbed.fs
 rename resources/shaders/{printbed_attr.vs => 110/printbed.vs} (100%)
 create mode 100644 resources/shaders/110/toolpaths_cog.fs
 rename resources/shaders/{toolpaths_cog_attr.vs => 110/toolpaths_cog.vs} (100%)
 create mode 100644 resources/shaders/110/variable_layer_height.fs
 rename resources/shaders/{variable_layer_height_attr.vs => 110/variable_layer_height.vs} (100%)
 create mode 100644 resources/shaders/140/background.fs
 create mode 100644 resources/shaders/140/background.vs
 create mode 100644 resources/shaders/140/flat.fs
 create mode 100644 resources/shaders/140/flat.vs
 create mode 100644 resources/shaders/140/flat_texture.fs
 create mode 100644 resources/shaders/140/flat_texture.vs
 create mode 100644 resources/shaders/140/gouraud.fs
 create mode 100644 resources/shaders/140/gouraud.vs
 create mode 100644 resources/shaders/140/gouraud_light.fs
 create mode 100644 resources/shaders/140/gouraud_light.vs
 create mode 100644 resources/shaders/140/gouraud_light_instanced.fs
 create mode 100644 resources/shaders/140/gouraud_light_instanced.vs
 create mode 100644 resources/shaders/140/imgui.fs
 create mode 100644 resources/shaders/140/imgui.vs
 create mode 100644 resources/shaders/140/mm_contour.fs
 create mode 100644 resources/shaders/140/mm_contour.vs
 create mode 100644 resources/shaders/140/mm_gouraud.fs
 create mode 100644 resources/shaders/140/mm_gouraud.vs
 create mode 100644 resources/shaders/140/printbed.fs
 create mode 100644 resources/shaders/140/printbed.vs
 create mode 100644 resources/shaders/140/toolpaths_cog.fs
 create mode 100644 resources/shaders/140/toolpaths_cog.vs
 create mode 100644 resources/shaders/140/variable_layer_height.fs
 create mode 100644 resources/shaders/140/variable_layer_height.vs

diff --git a/resources/shaders/110/background.fs b/resources/shaders/110/background.fs
new file mode 100644
index 000000000..b14844089
--- /dev/null
+++ b/resources/shaders/110/background.fs
@@ -0,0 +1,11 @@
+#version 110
+
+uniform vec4 top_color;
+uniform vec4 bottom_color;
+
+varying vec2 tex_coord;
+
+void main()
+{
+    gl_FragColor = mix(bottom_color, top_color, tex_coord.y);
+}
diff --git a/resources/shaders/background_attr.vs b/resources/shaders/110/background.vs
similarity index 100%
rename from resources/shaders/background_attr.vs
rename to resources/shaders/110/background.vs
diff --git a/resources/shaders/110/flat.fs b/resources/shaders/110/flat.fs
new file mode 100644
index 000000000..ab656998d
--- /dev/null
+++ b/resources/shaders/110/flat.fs
@@ -0,0 +1,8 @@
+#version 110
+
+uniform vec4 uniform_color;
+
+void main()
+{
+    gl_FragColor = uniform_color;
+}
diff --git a/resources/shaders/flat_attr.vs b/resources/shaders/110/flat.vs
similarity index 100%
rename from resources/shaders/flat_attr.vs
rename to resources/shaders/110/flat.vs
index 370eedb72..d9063f0c7 100644
--- a/resources/shaders/flat_attr.vs
+++ b/resources/shaders/110/flat.vs
@@ -1,10 +1,10 @@
 #version 110
 
-attribute vec3 v_position;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 
+attribute vec3 v_position;
+
 void main()
 {
     gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
diff --git a/resources/shaders/110/flat_texture.fs b/resources/shaders/110/flat_texture.fs
new file mode 100644
index 000000000..ffe193b1c
--- /dev/null
+++ b/resources/shaders/110/flat_texture.fs
@@ -0,0 +1,10 @@
+#version 110
+
+uniform sampler2D uniform_texture;
+
+varying vec2 tex_coord;
+
+void main()
+{
+    gl_FragColor = texture2D(uniform_texture, tex_coord);
+}
diff --git a/resources/shaders/flat_texture_attr.vs b/resources/shaders/110/flat_texture.vs
similarity index 100%
rename from resources/shaders/flat_texture_attr.vs
rename to resources/shaders/110/flat_texture.vs
index e59a99da3..dc4868b04 100644
--- a/resources/shaders/flat_texture_attr.vs
+++ b/resources/shaders/110/flat_texture.vs
@@ -1,11 +1,11 @@
 #version 110
 
-attribute vec3 v_position;
-attribute vec2 v_tex_coord;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 
+attribute vec3 v_position;
+attribute vec2 v_tex_coord;
+
 varying vec2 tex_coord;
 
 void main()
diff --git a/resources/shaders/110/gouraud.fs b/resources/shaders/110/gouraud.fs
new file mode 100644
index 000000000..0742f6cc8
--- /dev/null
+++ b/resources/shaders/110/gouraud.fs
@@ -0,0 +1,86 @@
+#version 110
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+const float EPSILON = 0.0001;
+
+struct PrintVolumeDetection
+{
+	// 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid
+	int type;
+    // type = 0 (rectangle):
+    // x = min.x, y = min.y, z = max.x, w = max.y
+    // type = 1 (circle):
+    // x = center.x, y = center.y, z = radius
+	vec4 xy_data;
+    // x = min z, y = max z
+	vec2 z_data;
+};
+
+struct SlopeDetection
+{
+    bool actived;
+	float normal_z;
+    mat3 volume_world_normal_matrix;
+};
+
+uniform vec4 uniform_color;
+uniform SlopeDetection slope;
+
+uniform bool offset_depth_buffer;
+
+#ifdef ENABLE_ENVIRONMENT_MAP
+    uniform sampler2D environment_tex;
+    uniform bool use_environment_tex;
+#endif // ENABLE_ENVIRONMENT_MAP
+
+uniform PrintVolumeDetection print_volume;
+
+varying vec3 clipping_planes_dots;
+
+// x = diffuse, y = specular;
+varying vec2 intensity;
+
+varying vec4 world_pos;
+varying float world_normal_z;
+varying vec3 eye_normal;
+
+void main()
+{
+    if (any(lessThan(clipping_planes_dots, ZERO)))
+        discard;
+    vec3  color = uniform_color.rgb;
+    float alpha = uniform_color.a;
+
+    if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
+        color = vec3(0.7, 0.7, 1.0);
+        alpha = 1.0;
+    }
+	
+    // if the fragment is outside the print volume -> use darker color
+	vec3 pv_check_min = ZERO;
+	vec3 pv_check_max = ZERO;
+    if (print_volume.type == 0) {
+		// rectangle
+		pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x);
+		pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y);
+	}
+	else if (print_volume.type == 1) {
+		// circle
+		float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy);
+		pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
+		pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
+	}	
+	color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
+	
+#ifdef ENABLE_ENVIRONMENT_MAP
+    if (use_environment_tex)
+        gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
+    else
+#endif
+        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);
+}
diff --git a/resources/shaders/gouraud_attr.vs b/resources/shaders/110/gouraud.vs
similarity index 100%
rename from resources/shaders/gouraud_attr.vs
rename to resources/shaders/110/gouraud.vs
index 87e524c14..70f71f886 100644
--- a/resources/shaders/gouraud_attr.vs
+++ b/resources/shaders/110/gouraud.vs
@@ -25,9 +25,6 @@ struct SlopeDetection
     mat3 volume_world_normal_matrix;
 };
 
-attribute vec3 v_position;
-attribute vec3 v_normal;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 uniform mat3 normal_matrix;
@@ -39,6 +36,9 @@ uniform vec2 z_range;
 // Clipping plane - general orientation. Used by the SLA gizmo.
 uniform vec4 clipping_plane;
 
+attribute vec3 v_position;
+attribute vec3 v_normal;
+
 // x = diffuse, y = specular;
 varying vec2 intensity;
 
diff --git a/resources/shaders/110/gouraud_light.fs b/resources/shaders/110/gouraud_light.fs
new file mode 100644
index 000000000..970185a00
--- /dev/null
+++ b/resources/shaders/110/gouraud_light.fs
@@ -0,0 +1,12 @@
+#version 110
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+
+void main()
+{
+    gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/gouraud_light_attr.vs b/resources/shaders/110/gouraud_light.vs
similarity index 100%
rename from resources/shaders/gouraud_light_attr.vs
rename to resources/shaders/110/gouraud_light.vs
index 2e1b5fb42..a03653b8a 100644
--- a/resources/shaders/gouraud_light_attr.vs
+++ b/resources/shaders/110/gouraud_light.vs
@@ -14,13 +14,13 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
 
 #define INTENSITY_AMBIENT    0.3
 
-attribute vec3 v_position;
-attribute vec3 v_normal;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 uniform mat3 normal_matrix;
 
+attribute vec3 v_position;
+attribute vec3 v_normal;
+
 // x = tainted, y = specular;
 varying vec2 intensity;
 
diff --git a/resources/shaders/110/gouraud_light_instanced.fs b/resources/shaders/110/gouraud_light_instanced.fs
new file mode 100644
index 000000000..970185a00
--- /dev/null
+++ b/resources/shaders/110/gouraud_light_instanced.fs
@@ -0,0 +1,12 @@
+#version 110
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+
+void main()
+{
+    gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/gouraud_light_instanced_attr.vs b/resources/shaders/110/gouraud_light_instanced.vs
similarity index 100%
rename from resources/shaders/gouraud_light_instanced_attr.vs
rename to resources/shaders/110/gouraud_light_instanced.vs
index 7069feb65..87748ce6f 100644
--- a/resources/shaders/gouraud_light_instanced_attr.vs
+++ b/resources/shaders/110/gouraud_light_instanced.vs
@@ -14,6 +14,10 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
 
 #define INTENSITY_AMBIENT    0.3
 
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
 // vertex attributes
 attribute vec3 v_position;
 attribute vec3 v_normal;
@@ -21,10 +25,6 @@ attribute vec3 v_normal;
 attribute vec3 i_offset;
 attribute vec2 i_scales;
 
-uniform mat4 view_model_matrix;
-uniform mat4 projection_matrix;
-uniform mat3 normal_matrix;
-
 // x = tainted, y = specular;
 varying vec2 intensity;
 
diff --git a/resources/shaders/imgui.fs b/resources/shaders/110/imgui.fs
similarity index 100%
rename from resources/shaders/imgui.fs
rename to resources/shaders/110/imgui.fs
diff --git a/resources/shaders/imgui.vs b/resources/shaders/110/imgui.vs
similarity index 100%
rename from resources/shaders/imgui.vs
rename to resources/shaders/110/imgui.vs
diff --git a/resources/shaders/mm_contour_attr.fs b/resources/shaders/110/mm_contour.fs
similarity index 100%
rename from resources/shaders/mm_contour_attr.fs
rename to resources/shaders/110/mm_contour.fs
diff --git a/resources/shaders/mm_contour_attr.vs b/resources/shaders/110/mm_contour.vs
similarity index 100%
rename from resources/shaders/mm_contour_attr.vs
rename to resources/shaders/110/mm_contour.vs
index 370eedb72..d9063f0c7 100644
--- a/resources/shaders/mm_contour_attr.vs
+++ b/resources/shaders/110/mm_contour.vs
@@ -1,10 +1,10 @@
 #version 110
 
-attribute vec3 v_position;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 
+attribute vec3 v_position;
+
 void main()
 {
     gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
diff --git a/resources/shaders/mm_gouraud_attr.fs b/resources/shaders/110/mm_gouraud.fs
similarity index 100%
rename from resources/shaders/mm_gouraud_attr.fs
rename to resources/shaders/110/mm_gouraud.fs
diff --git a/resources/shaders/mm_gouraud_attr.vs b/resources/shaders/110/mm_gouraud.vs
similarity index 100%
rename from resources/shaders/mm_gouraud_attr.vs
rename to resources/shaders/110/mm_gouraud.vs
index 76101b767..10c25239f 100644
--- a/resources/shaders/mm_gouraud_attr.vs
+++ b/resources/shaders/110/mm_gouraud.vs
@@ -2,8 +2,6 @@
 
 const vec3 ZERO = vec3(0.0, 0.0, 0.0);
 
-attribute vec3 v_position;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 
@@ -13,6 +11,8 @@ 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;
 varying vec4 model_pos;
 
diff --git a/resources/shaders/110/printbed.fs b/resources/shaders/110/printbed.fs
new file mode 100644
index 000000000..833dff08f
--- /dev/null
+++ b/resources/shaders/110/printbed.fs
@@ -0,0 +1,34 @@
+#version 110
+
+const vec3 back_color_dark  = vec3(0.235, 0.235, 0.235);
+const vec3 back_color_light = vec3(0.365, 0.365, 0.365);
+
+uniform sampler2D texture;
+uniform bool transparent_background;
+uniform bool svg_source;
+
+varying vec2 tex_coord;
+
+vec4 svg_color()
+{
+    // takes foreground from texture
+    vec4 fore_color = texture2D(texture, tex_coord);
+
+    // calculates radial gradient
+    vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5)))));
+
+    // blends foreground with background
+    return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0);
+}
+
+vec4 non_svg_color()
+{
+    // takes foreground from texture
+    vec4 color = texture2D(texture, tex_coord);
+    return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a);
+}
+
+void main()
+{
+    gl_FragColor = svg_source ? svg_color() : non_svg_color();
+}
\ No newline at end of file
diff --git a/resources/shaders/printbed_attr.vs b/resources/shaders/110/printbed.vs
similarity index 100%
rename from resources/shaders/printbed_attr.vs
rename to resources/shaders/110/printbed.vs
index e59a99da3..dc4868b04 100644
--- a/resources/shaders/printbed_attr.vs
+++ b/resources/shaders/110/printbed.vs
@@ -1,11 +1,11 @@
 #version 110
 
-attribute vec3 v_position;
-attribute vec2 v_tex_coord;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 
+attribute vec3 v_position;
+attribute vec2 v_tex_coord;
+
 varying vec2 tex_coord;
 
 void main()
diff --git a/resources/shaders/110/toolpaths_cog.fs b/resources/shaders/110/toolpaths_cog.fs
new file mode 100644
index 000000000..668fe03ec
--- /dev/null
+++ b/resources/shaders/110/toolpaths_cog.fs
@@ -0,0 +1,19 @@
+#version 110
+
+const vec4 BLACK = vec4(vec3(0.1), 1.0);
+const vec4 WHITE = vec4(vec3(1.0), 1.0);
+
+const float emission_factor = 0.25;
+
+uniform vec3 world_center;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+varying vec3 world_position;
+
+void main()
+{
+    vec3 delta = world_position - world_center;
+    vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;
+    gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0);
+}
diff --git a/resources/shaders/toolpaths_cog_attr.vs b/resources/shaders/110/toolpaths_cog.vs
similarity index 100%
rename from resources/shaders/toolpaths_cog_attr.vs
rename to resources/shaders/110/toolpaths_cog.vs
index 5951238b7..38d2f7944 100644
--- a/resources/shaders/toolpaths_cog_attr.vs
+++ b/resources/shaders/110/toolpaths_cog.vs
@@ -14,13 +14,13 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
 
 #define INTENSITY_AMBIENT    0.3
 
-attribute vec3 v_position;
-attribute vec3 v_normal;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 uniform mat3 normal_matrix;
 
+attribute vec3 v_position;
+attribute vec3 v_normal;
+
 // x = tainted, y = specular;
 varying vec2 intensity;
 varying vec3 world_position;
diff --git a/resources/shaders/110/variable_layer_height.fs b/resources/shaders/110/variable_layer_height.fs
new file mode 100644
index 000000000..693c1c6a0
--- /dev/null
+++ b/resources/shaders/110/variable_layer_height.fs
@@ -0,0 +1,41 @@
+#version 110
+
+#define M_PI 3.1415926535897932384626433832795
+
+// 2D texture (1D texture split by the rows) of color along the object Z axis.
+uniform sampler2D z_texture;
+// Scaling from the Z texture rows coordinate to the normalized texture row coordinate.
+uniform float z_to_texture_row;
+uniform float z_texture_row_to_normalized;
+uniform float z_cursor;
+uniform float z_cursor_band_width;
+
+// x = tainted, y = specular;
+varying vec2 intensity;
+
+varying float object_z;
+
+void main()
+{
+    float object_z_row = z_to_texture_row * object_z;
+    // Index of the row in the texture.
+    float z_texture_row = floor(object_z_row);
+    // Normalized coordinate from 0. to 1.
+    float z_texture_col = object_z_row - z_texture_row;
+    float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25;
+    // Calculate level of detail from the object Z coordinate.
+    // This makes the slowly sloping surfaces to be shown with high detail (with stripes),
+    // and the vertical surfaces to be shown with low detail (no stripes)
+    float z_in_cells = object_z_row * 190.;
+    // Gradient of Z projected on the screen.
+    float dx_vtc = dFdx(z_in_cells);
+    float dy_vtc = dFdy(z_in_cells);
+    float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.);
+    // Sample the Z texture. Texture coordinates are normalized to <0, 1>.
+    vec4 color = vec4(0.25, 0.25, 0.25, 1.0);
+    if (z_texture_row >= 0.0)
+        color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5    )), -10000.),
+                    texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)),  10000.), lod);            
+    // Mix the final color.
+    gl_FragColor = vec4(vec3(intensity.y), 1.0) +  intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
+}
diff --git a/resources/shaders/variable_layer_height_attr.vs b/resources/shaders/110/variable_layer_height.vs
similarity index 100%
rename from resources/shaders/variable_layer_height_attr.vs
rename to resources/shaders/110/variable_layer_height.vs
index 40609bd0d..e6c88fa80 100644
--- a/resources/shaders/variable_layer_height_attr.vs
+++ b/resources/shaders/110/variable_layer_height.vs
@@ -14,16 +14,16 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
 
 #define INTENSITY_AMBIENT    0.3
 
-attribute vec3 v_position;
-attribute vec3 v_normal;
-attribute vec2 v_tex_coord;
-
 uniform mat4 view_model_matrix;
 uniform mat4 projection_matrix;
 uniform mat3 normal_matrix;
 uniform mat4 volume_world_matrix;
 uniform float object_max_z;
 
+attribute vec3 v_position;
+attribute vec3 v_normal;
+attribute vec2 v_tex_coord;
+
 // x = tainted, y = specular;
 varying vec2 intensity;
 
diff --git a/resources/shaders/140/background.fs b/resources/shaders/140/background.fs
new file mode 100644
index 000000000..c21f3a70c
--- /dev/null
+++ b/resources/shaders/140/background.fs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform vec4 top_color;
+uniform vec4 bottom_color;
+
+in vec2 tex_coord;
+
+void main()
+{
+    gl_FragColor = mix(bottom_color, top_color, tex_coord.y);
+}
diff --git a/resources/shaders/140/background.vs b/resources/shaders/140/background.vs
new file mode 100644
index 000000000..13609b3a2
--- /dev/null
+++ b/resources/shaders/140/background.vs
@@ -0,0 +1,12 @@
+#version 140
+
+in vec3 v_position;
+in vec2 v_tex_coord;
+
+out vec2 tex_coord;
+
+void main()
+{
+	tex_coord = v_tex_coord;
+    gl_Position = vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/flat.fs b/resources/shaders/140/flat.fs
new file mode 100644
index 000000000..e74124dca
--- /dev/null
+++ b/resources/shaders/140/flat.fs
@@ -0,0 +1,8 @@
+#version 140
+
+uniform vec4 uniform_color;
+
+void main()
+{
+    gl_FragColor = uniform_color;
+}
diff --git a/resources/shaders/140/flat.vs b/resources/shaders/140/flat.vs
new file mode 100644
index 000000000..7042671de
--- /dev/null
+++ b/resources/shaders/140/flat.vs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+
+void main()
+{
+    gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/flat_texture.fs b/resources/shaders/140/flat_texture.fs
new file mode 100644
index 000000000..7db62b682
--- /dev/null
+++ b/resources/shaders/140/flat_texture.fs
@@ -0,0 +1,10 @@
+#version 140
+
+uniform sampler2D uniform_texture;
+
+in vec2 tex_coord;
+
+void main()
+{
+    gl_FragColor = texture2D(uniform_texture, tex_coord);
+}
diff --git a/resources/shaders/140/flat_texture.vs b/resources/shaders/140/flat_texture.vs
new file mode 100644
index 000000000..57d8ca3b7
--- /dev/null
+++ b/resources/shaders/140/flat_texture.vs
@@ -0,0 +1,15 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+in vec2 v_tex_coord;
+
+out vec2 tex_coord;
+
+void main()
+{
+	tex_coord = v_tex_coord;
+    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
new file mode 100644
index 000000000..7651380d7
--- /dev/null
+++ b/resources/shaders/140/gouraud.fs
@@ -0,0 +1,86 @@
+#version 140
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+const float EPSILON = 0.0001;
+
+struct PrintVolumeDetection
+{
+	// 0 = rectangle, 1 = circle, 2 = custom, 3 = invalid
+	int type;
+    // type = 0 (rectangle):
+    // x = min.x, y = min.y, z = max.x, w = max.y
+    // type = 1 (circle):
+    // x = center.x, y = center.y, z = radius
+	vec4 xy_data;
+    // x = min z, y = max z
+	vec2 z_data;
+};
+
+struct SlopeDetection
+{
+    bool actived;
+	float normal_z;
+    mat3 volume_world_normal_matrix;
+};
+
+uniform vec4 uniform_color;
+uniform SlopeDetection slope;
+
+uniform bool offset_depth_buffer;
+
+#ifdef ENABLE_ENVIRONMENT_MAP
+    uniform sampler2D environment_tex;
+    uniform bool use_environment_tex;
+#endif // ENABLE_ENVIRONMENT_MAP
+
+uniform PrintVolumeDetection print_volume;
+
+in vec3 clipping_planes_dots;
+
+// x = diffuse, y = specular;
+in vec2 intensity;
+
+in vec4 world_pos;
+in float world_normal_z;
+in vec3 eye_normal;
+
+void main()
+{
+    if (any(lessThan(clipping_planes_dots, ZERO)))
+        discard;
+    vec3  color = uniform_color.rgb;
+    float alpha = uniform_color.a;
+
+    if (slope.actived && world_normal_z < slope.normal_z - EPSILON) {
+        color = vec3(0.7, 0.7, 1.0);
+        alpha = 1.0;
+    }
+	
+    // if the fragment is outside the print volume -> use darker color
+	vec3 pv_check_min = ZERO;
+	vec3 pv_check_max = ZERO;
+    if (print_volume.type == 0) {
+		// rectangle
+		pv_check_min = world_pos.xyz - vec3(print_volume.xy_data.x, print_volume.xy_data.y, print_volume.z_data.x);
+		pv_check_max = world_pos.xyz - vec3(print_volume.xy_data.z, print_volume.xy_data.w, print_volume.z_data.y);
+	}
+	else if (print_volume.type == 1) {
+		// circle
+		float delta_radius = print_volume.xy_data.z - distance(world_pos.xy, print_volume.xy_data.xy);
+		pv_check_min = vec3(delta_radius, 0.0, world_pos.z - print_volume.z_data.x);
+		pv_check_max = vec3(0.0, 0.0, world_pos.z - print_volume.z_data.y);
+	}	
+	color = (any(lessThan(pv_check_min, ZERO)) || any(greaterThan(pv_check_max, ZERO))) ? mix(color, ZERO, 0.3333) : color;
+	
+#ifdef ENABLE_ENVIRONMENT_MAP
+    if (use_environment_tex)
+        gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
+    else
+#endif
+        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);
+}
diff --git a/resources/shaders/140/gouraud.vs b/resources/shaders/140/gouraud.vs
new file mode 100644
index 000000000..aaf251c42
--- /dev/null
+++ b/resources/shaders/140/gouraud.vs
@@ -0,0 +1,77 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS  20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SHININESS 5.0
+
+#define INTENSITY_AMBIENT    0.3
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+
+struct SlopeDetection
+{
+    bool actived;
+	float normal_z;
+    mat3 volume_world_normal_matrix;
+};
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+uniform mat4 volume_world_matrix;
+uniform SlopeDetection slope;
+
+// 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;
+in vec3 v_normal;
+
+// x = diffuse, y = specular;
+out vec2 intensity;
+
+out vec3 clipping_planes_dots;
+
+out vec4 world_pos;
+out float world_normal_z;
+out vec3 eye_normal;
+
+void main()
+{
+	// First transform the normal into camera space and normalize the result.
+    eye_normal = normalize(normal_matrix * v_normal);
+
+	// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+	// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+	float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
+
+	intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+    vec4 position = view_model_matrix * vec4(v_position, 1.0);
+    intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
+
+	// Perform the same lighting calculation for the 2nd light source (no specular applied).
+	NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
+	intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+    // Point in homogenous coordinates.
+    world_pos = volume_world_matrix * vec4(v_position, 1.0);
+
+    // z component of normal vector in world coordinate used for slope shading
+    world_normal_z = slope.actived ? (normalize(slope.volume_world_normal_matrix * v_normal)).z : 0.0;
+
+    gl_Position = projection_matrix * position;
+    // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
+    clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
+}
diff --git a/resources/shaders/140/gouraud_light.fs b/resources/shaders/140/gouraud_light.fs
new file mode 100644
index 000000000..de616e066
--- /dev/null
+++ b/resources/shaders/140/gouraud_light.fs
@@ -0,0 +1,12 @@
+#version 140
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+
+void main()
+{
+    gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/140/gouraud_light.vs b/resources/shaders/140/gouraud_light.vs
new file mode 100644
index 000000000..b75a84405
--- /dev/null
+++ b/resources/shaders/140/gouraud_light.vs
@@ -0,0 +1,45 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS  20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT    0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 v_position;
+in vec3 v_normal;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+
+void main()
+{
+    // First transform the normal into camera space and normalize the result.
+    vec3 normal = normalize(normal_matrix * v_normal);
+    
+    // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+    // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+    float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
+
+    intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+    vec4 position = view_model_matrix * vec4(v_position, 1.0);
+    intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
+
+    // Perform the same lighting calculation for the 2nd light source (no specular applied).
+    NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+    intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+    gl_Position = projection_matrix * position;
+}
diff --git a/resources/shaders/140/gouraud_light_instanced.fs b/resources/shaders/140/gouraud_light_instanced.fs
new file mode 100644
index 000000000..de616e066
--- /dev/null
+++ b/resources/shaders/140/gouraud_light_instanced.fs
@@ -0,0 +1,12 @@
+#version 140
+
+uniform vec4 uniform_color;
+uniform float emission_factor;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+
+void main()
+{
+    gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
+}
diff --git a/resources/shaders/140/gouraud_light_instanced.vs b/resources/shaders/140/gouraud_light_instanced.vs
new file mode 100644
index 000000000..b6b9ab8be
--- /dev/null
+++ b/resources/shaders/140/gouraud_light_instanced.vs
@@ -0,0 +1,50 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS  20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT    0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
+// vertex attributes
+in vec3 v_position;
+in vec3 v_normal;
+// instance attributes
+in vec3 i_offset;
+in vec2 i_scales;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+
+void main()
+{
+    // First transform the normal into camera space and normalize the result.
+    vec3 eye_normal = normalize(normal_matrix * v_normal);
+    
+    // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+    // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+    float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
+
+    intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+    vec4 world_position = vec4(v_position * vec3(vec2(1.5 * i_scales.x), 1.5 * i_scales.y) + i_offset - vec3(0.0, 0.0, 0.5 * i_scales.y), 1.0);
+    vec4 eye_position = view_model_matrix * world_position;
+    intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
+
+    // Perform the same lighting calculation for the 2nd light source (no specular applied).
+    NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
+    intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+    gl_Position = projection_matrix * eye_position;
+}
diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs
new file mode 100644
index 000000000..8e7999fdf
--- /dev/null
+++ b/resources/shaders/140/imgui.fs
@@ -0,0 +1,11 @@
+#version 110
+
+uniform sampler2D Texture;
+
+in vec2 Frag_UV;
+in vec4 Frag_Color;
+
+void main()
+{
+	gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);
+}
\ No newline at end of file
diff --git a/resources/shaders/140/imgui.vs b/resources/shaders/140/imgui.vs
new file mode 100644
index 000000000..fd743bdf2
--- /dev/null
+++ b/resources/shaders/140/imgui.vs
@@ -0,0 +1,17 @@
+#version 140
+
+uniform mat4 ProjMtx;
+
+in vec2 Position;
+in vec2 UV;
+in vec4 Color;
+
+out vec2 Frag_UV;
+out vec4 Frag_Color;
+
+void main()
+{
+	Frag_UV = UV;
+	Frag_Color = Color;
+    gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0);
+}
\ No newline at end of file
diff --git a/resources/shaders/140/mm_contour.fs b/resources/shaders/140/mm_contour.fs
new file mode 100644
index 000000000..3681d76c1
--- /dev/null
+++ b/resources/shaders/140/mm_contour.fs
@@ -0,0 +1,13 @@
+#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
new file mode 100644
index 000000000..7042671de
--- /dev/null
+++ b/resources/shaders/140/mm_contour.vs
@@ -0,0 +1,11 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+
+void main()
+{
+    gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/mm_gouraud.fs b/resources/shaders/140/mm_gouraud.fs
new file mode 100644
index 000000000..e59d844f2
--- /dev/null
+++ b/resources/shaders/140/mm_gouraud.fs
@@ -0,0 +1,63 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS  20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT    0.3
+
+const vec3  ZERO    = vec3(0.0, 0.0, 0.0);
+const float EPSILON = 0.0001;
+
+uniform vec4 uniform_color;
+
+uniform bool volume_mirrored;
+
+uniform mat4 view_model_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 clipping_planes_dots;
+in vec4 model_pos;
+
+void main()
+{
+    if (any(lessThan(clipping_planes_dots, ZERO)))
+        discard;
+    vec3  color = uniform_color.rgb;
+    float alpha = uniform_color.a;
+
+    vec3 triangle_normal = normalize(cross(dFdx(model_pos.xyz), dFdy(model_pos.xyz)));
+#ifdef FLIP_TRIANGLE_NORMALS
+    triangle_normal = -triangle_normal;
+#endif
+
+    if (volume_mirrored)
+        triangle_normal = -triangle_normal;
+
+    // First transform the normal into camera space and normalize the result.
+    vec3 eye_normal = normalize(normal_matrix * triangle_normal);
+
+    // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+    // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+    float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
+
+    // x = diffuse, y = specular;
+    vec2 intensity = vec2(0.0);
+    intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+    vec3 position = (view_model_matrix * model_pos).xyz;
+    intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
+
+    // Perform the same lighting calculation for the 2nd light source (no specular applied).
+    NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
+    intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+    gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
+}
diff --git a/resources/shaders/140/mm_gouraud.vs b/resources/shaders/140/mm_gouraud.vs
new file mode 100644
index 000000000..30223f4ee
--- /dev/null
+++ b/resources/shaders/140/mm_gouraud.vs
@@ -0,0 +1,28 @@
+#version 140
+
+const vec3 ZERO = vec3(0.0, 0.0, 0.0);
+
+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;
+out vec4 model_pos;
+
+void main()
+{
+    model_pos = vec4(v_position, 1.0);
+    // Point in homogenous coordinates.
+    vec4 world_pos = volume_world_matrix * model_pos;
+
+    gl_Position = projection_matrix * view_model_matrix * model_pos;
+    // Fill in the scalars for fragment shader clipping. Fragments with any of these components lower than zero are discarded.
+    clipping_planes_dots = vec3(dot(world_pos, clipping_plane), world_pos.z - z_range.x, z_range.y - world_pos.z);
+}
diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs
new file mode 100644
index 000000000..73ff8f690
--- /dev/null
+++ b/resources/shaders/140/printbed.fs
@@ -0,0 +1,34 @@
+#version 140
+
+const vec3 back_color_dark  = vec3(0.235, 0.235, 0.235);
+const vec3 back_color_light = vec3(0.365, 0.365, 0.365);
+
+uniform sampler2D texture;
+uniform bool transparent_background;
+uniform bool svg_source;
+
+in vec2 tex_coord;
+
+vec4 svg_color()
+{
+    // takes foreground from texture
+    vec4 fore_color = texture2D(texture, tex_coord);
+
+    // calculates radial gradient
+    vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5)))));
+
+    // blends foreground with background
+    return vec4(mix(back_color, fore_color.rgb, fore_color.a), transparent_background ? fore_color.a : 1.0);
+}
+
+vec4 non_svg_color()
+{
+    // takes foreground from texture
+    vec4 color = texture2D(texture, tex_coord);
+    return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a);
+}
+
+void main()
+{
+    gl_FragColor = svg_source ? svg_color() : non_svg_color();
+}
\ No newline at end of file
diff --git a/resources/shaders/140/printbed.vs b/resources/shaders/140/printbed.vs
new file mode 100644
index 000000000..57d8ca3b7
--- /dev/null
+++ b/resources/shaders/140/printbed.vs
@@ -0,0 +1,15 @@
+#version 140
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+
+in vec3 v_position;
+in vec2 v_tex_coord;
+
+out vec2 tex_coord;
+
+void main()
+{
+	tex_coord = v_tex_coord;
+    gl_Position = projection_matrix * view_model_matrix * vec4(v_position, 1.0);
+}
diff --git a/resources/shaders/140/toolpaths_cog.fs b/resources/shaders/140/toolpaths_cog.fs
new file mode 100644
index 000000000..1c745dda9
--- /dev/null
+++ b/resources/shaders/140/toolpaths_cog.fs
@@ -0,0 +1,19 @@
+#version 140
+
+const vec4 BLACK = vec4(vec3(0.1), 1.0);
+const vec4 WHITE = vec4(vec3(1.0), 1.0);
+
+const float emission_factor = 0.25;
+
+uniform vec3 world_center;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+in vec3 world_position;
+
+void main()
+{
+    vec3 delta = world_position - world_center;
+    vec4 color = delta.x * delta.y * delta.z > 0.0 ? BLACK : WHITE;
+    gl_FragColor = vec4(vec3(intensity.y) + color.rgb * (intensity.x + emission_factor), 1.0);
+}
diff --git a/resources/shaders/140/toolpaths_cog.vs b/resources/shaders/140/toolpaths_cog.vs
new file mode 100644
index 000000000..ef676a375
--- /dev/null
+++ b/resources/shaders/140/toolpaths_cog.vs
@@ -0,0 +1,47 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS  20.0
+
+// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION)
+
+#define INTENSITY_AMBIENT    0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+
+in vec3 v_position;
+in vec3 v_normal;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+out vec3 world_position;
+
+void main()
+{
+    // First transform the normal into camera space and normalize the result.
+    vec3 normal = normalize(normal_matrix * v_normal);
+    
+    // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+    // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+    float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
+
+    intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+    vec4 position = view_model_matrix * vec4(v_position, 1.0);
+    intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
+
+    // Perform the same lighting calculation for the 2nd light source (no specular applied).
+    NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+    intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+	world_position = v_position;
+    gl_Position = projection_matrix * position;
+}
diff --git a/resources/shaders/140/variable_layer_height.fs b/resources/shaders/140/variable_layer_height.fs
new file mode 100644
index 000000000..5fa7e6835
--- /dev/null
+++ b/resources/shaders/140/variable_layer_height.fs
@@ -0,0 +1,41 @@
+#version 140
+
+#define M_PI 3.1415926535897932384626433832795
+
+// 2D texture (1D texture split by the rows) of color along the object Z axis.
+uniform sampler2D z_texture;
+// Scaling from the Z texture rows coordinate to the normalized texture row coordinate.
+uniform float z_to_texture_row;
+uniform float z_texture_row_to_normalized;
+uniform float z_cursor;
+uniform float z_cursor_band_width;
+
+// x = tainted, y = specular;
+in vec2 intensity;
+
+in float object_z;
+
+void main()
+{
+    float object_z_row = z_to_texture_row * object_z;
+    // Index of the row in the texture.
+    float z_texture_row = floor(object_z_row);
+    // Normalized coordinate from 0. to 1.
+    float z_texture_col = object_z_row - z_texture_row;
+    float z_blend = 0.25 * cos(min(M_PI, abs(M_PI * (object_z - z_cursor) * 1.8 / z_cursor_band_width))) + 0.25;
+    // Calculate level of detail from the object Z coordinate.
+    // This makes the slowly sloping surfaces to be shown with high detail (with stripes),
+    // and the vertical surfaces to be shown with low detail (no stripes)
+    float z_in_cells = object_z_row * 190.;
+    // Gradient of Z projected on the screen.
+    float dx_vtc = dFdx(z_in_cells);
+    float dy_vtc = dFdy(z_in_cells);
+    float lod = clamp(0.5 * log2(max(dx_vtc * dx_vtc, dy_vtc * dy_vtc)), 0., 1.);
+    // Sample the Z texture. Texture coordinates are normalized to <0, 1>.
+    vec4 color = vec4(0.25, 0.25, 0.25, 1.0);
+    if (z_texture_row >= 0.0)
+        color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5    )), -10000.),
+                    texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)),  10000.), lod);            
+    // Mix the final color.
+    gl_FragColor = vec4(vec3(intensity.y), 1.0) +  intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
+}
diff --git a/resources/shaders/140/variable_layer_height.vs b/resources/shaders/140/variable_layer_height.vs
new file mode 100644
index 000000000..dd463b9c7
--- /dev/null
+++ b/resources/shaders/140/variable_layer_height.vs
@@ -0,0 +1,60 @@
+#version 140
+
+#define INTENSITY_CORRECTION 0.6
+
+const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
+#define LIGHT_TOP_DIFFUSE    (0.8 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SPECULAR   (0.125 * INTENSITY_CORRECTION)
+#define LIGHT_TOP_SHININESS  20.0
+
+const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
+#define LIGHT_FRONT_DIFFUSE  (0.3 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SPECULAR (0.0 * INTENSITY_CORRECTION)
+//#define LIGHT_FRONT_SHININESS 5.0
+
+#define INTENSITY_AMBIENT    0.3
+
+uniform mat4 view_model_matrix;
+uniform mat4 projection_matrix;
+uniform mat3 normal_matrix;
+uniform mat4 volume_world_matrix;
+uniform float object_max_z;
+
+in vec3 v_position;
+in vec3 v_normal;
+in vec2 v_tex_coord;
+
+// x = tainted, y = specular;
+out vec2 intensity;
+
+out float object_z;
+
+void main()
+{
+	// =====================================================
+	// NOTE:
+	// when object_max_z > 0.0  we are rendering the overlay
+	// when object_max_z == 0.0 we are rendering the volumes
+	// =====================================================
+
+    // First transform the normal into camera space and normalize the result.
+    vec3 normal = (object_max_z > 0.0) ? vec3(0.0, 0.0, 1.0) : normalize(normal_matrix * v_normal);
+    
+    // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
+    // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
+    float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0);
+
+    intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
+    vec4 position = view_model_matrix * vec4(v_position, 1.0);
+    intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position.xyz), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
+
+    // Perform the same lighting calculation for the 2nd light source (no specular)
+    NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+    
+    intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+    // Scaled to widths of the Z texture.
+    object_z = (object_max_z > 0.0) ? object_max_z * v_tex_coord.y : (volume_world_matrix * vec4(v_position, 1.0)).z;
+        
+    gl_Position = projection_matrix * position;
+}
diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp
index 3cbebfff8..66fa8fb92 100644
--- a/src/slic3r/GUI/3DBed.cpp
+++ b/src/slic3r/GUI/3DBed.cpp
@@ -130,11 +130,7 @@ void Bed3D::Axes::render()
     if (!m_arrow.is_initialized())
         m_arrow.init_from(stilized_arrow(16, DefaultTipRadius, DefaultTipLength, DefaultStemRadius, m_stem_length));
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -620,11 +616,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
 #if ENABLE_LEGACY_OPENGL_REMOVAL
     init_triangles();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("printbed_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("printbed");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -748,11 +740,7 @@ void Bed3D::render_model()
     }
 
     if (!m_model.get_filename().empty()) {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
             shader->set_uniform("emission_factor", 0.0f);
@@ -816,11 +804,7 @@ void Bed3D::render_default(bool bottom, bool picking)
     init_gridlines();
     init_triangles();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index 50e488686..c9fb05439 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -1085,14 +1085,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
         return;
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat_attr");
-    GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat_attr");
-    assert(boost::algorithm::iends_with(shader->get_name(), "_attr"));
-#else
     GLShaderProgram* sink_shader  = GUI::wxGetApp().get_shader("flat");
     GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
 
     if (type == ERenderType::Transparent) {
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 5372d4565..acb1ba4d0 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -184,11 +184,7 @@ void GCodeViewer::COG::render()
 
     init();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("toolpaths_cog");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -331,11 +327,7 @@ void GCodeViewer::SequentialView::Marker::render()
     if (!m_visible)
         return;
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -703,11 +695,7 @@ void GCodeViewer::init()
 #if !DISABLE_GCODEVIEWER_INSTANCED_MODELS
             if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
                 buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::InstancedModel;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-                buffer.shader = "gouraud_light_instanced_attr";
-#else
                 buffer.shader = "gouraud_light_instanced";
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
                 buffer.model.model.init_from(diamond(16));
                 buffer.model.color = option_color(type);
                 buffer.model.instances.format = InstanceVBuffer::EFormat::InstancedModel;
@@ -716,12 +704,7 @@ void GCodeViewer::init()
 #endif // !DISABLE_GCODEVIEWER_INSTANCED_MODELS
                 buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::BatchedModel;
                 buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-                buffer.shader = "gouraud_light_attr";
-#else
                 buffer.shader = "gouraud_light";
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
-
                 buffer.model.data = diamond(16);
                 buffer.model.color = option_color(type);
                 buffer.model.instances.format = InstanceVBuffer::EFormat::BatchedModel;
@@ -734,18 +717,14 @@ void GCodeViewer::init()
         case EMoveType::Extrude: {
             buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle;
             buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-            buffer.shader = "gouraud_light_attr";
-#else
             buffer.shader = "gouraud_light";
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
             break;
         }
         case EMoveType::Travel: {
             buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line;
 #if ENABLE_GL_SHADERS_ATTRIBUTES
             buffer.vertices.format = VBuffer::EFormat::Position;
-            buffer.shader = "flat_attr";
+            buffer.shader = "flat";
 #else
             buffer.vertices.format = VBuffer::EFormat::PositionNormal3;
             buffer.shader = "toolpaths_lines";
@@ -3161,11 +3140,8 @@ void GCodeViewer::render_toolpaths()
             const int position_id = shader->get_attrib_location("v_position");
             const int normal_id   = shader->get_attrib_location("v_normal");
 #else
-            switch (buffer.render_primitive_type) {
-            case TBuffer::ERenderPrimitiveType::Point: shader_init_as_points(*shader); break;
-            case TBuffer::ERenderPrimitiveType::Line:  shader_init_as_lines(*shader); break;
-            default: break;
-            }
+            if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Line)
+                shader_init_as_lines(*shader);
 #endif // ENABLE_GL_SHADERS_ATTRIBUTES
             const int uniform_color = shader->get_uniform_location("uniform_color");
 
@@ -3322,11 +3298,7 @@ void GCodeViewer::render_shells()
     if (!m_shells.visible || m_shells.volumes.empty())
         return;
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 91add7c56..1649d2082 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -161,11 +161,7 @@ void GLCanvas3D::LayersEditing::select_object(const Model &model, int object_id)
 
 bool GLCanvas3D::LayersEditing::is_allowed() const
 {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    return wxGetApp().get_shader("variable_layer_height_attr") != nullptr && m_z_texture_id > 0;
-#else
     return wxGetApp().get_shader("variable_layer_height") != nullptr && m_z_texture_id > 0;
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 }
 
 bool GLCanvas3D::LayersEditing::is_enabled() const
@@ -328,11 +324,7 @@ Rect GLCanvas3D::LayersEditing::get_bar_rect_viewport(const GLCanvas3D& canvas)
 
 bool GLCanvas3D::LayersEditing::is_initialized() const
 {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    return wxGetApp().get_shader("variable_layer_height_attr") != nullptr;
-#else
     return wxGetApp().get_shader("variable_layer_height") != nullptr;
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 }
 
 std::string GLCanvas3D::LayersEditing::get_tooltip(const GLCanvas3D& canvas) const
@@ -375,11 +367,8 @@ void GLCanvas3D::LayersEditing::render_active_object_annotations(const GLCanvas3
         return;
 
     const float cnv_inv_width = 1.0f / cnv_width;
-
-    GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr");
-#else
-    GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
 #endif // ENABLE_GL_SHADERS_ATTRIBUTES
+    GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
     if (shader == nullptr)
         return;
 
@@ -550,11 +539,7 @@ void GLCanvas3D::LayersEditing::render_profile(const Rect& bar_rect)
         m_profile.profile.init_from(std::move(init_data));
     }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -594,11 +579,7 @@ void GLCanvas3D::LayersEditing::render_volumes(const GLCanvas3D& canvas, const G
     if (current_shader != nullptr)
         current_shader->stop_using();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("variable_layer_height");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -1075,11 +1056,7 @@ void GLCanvas3D::SequentialPrintClearance::render()
     const ColorRGBA NO_FILL_COLOR = { 1.0f, 1.0f, 1.0f, 0.75f };
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
@@ -4608,11 +4585,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const
 
     camera.apply_projection(volumes_box, near_z, far_z);
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -5551,11 +5524,7 @@ void GLCanvas3D::_render_background()
         m_background.init_from(std::move(init_data));
     }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("background_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("background");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
         shader->set_uniform("top_color", use_error_color ? ERROR_BG_LIGHT_COLOR : DEFAULT_BG_LIGHT_COLOR);
@@ -5681,11 +5650,7 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type)
     m_volumes.set_show_non_manifold_edges(!m_gizmos.is_hiding_instances() && m_gizmos.get_current_type() != GLGizmosManager::Simplify);
 #endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("gouraud_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 
@@ -5910,11 +5875,7 @@ void GLCanvas3D::_render_overlays()
 void GLCanvas3D::_render_volumes_for_picking() const
 {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
@@ -6137,11 +6098,7 @@ void GLCanvas3D::_render_camera_target()
         }
     }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -6322,11 +6279,7 @@ void GLCanvas3D::_render_sla_slices()
         }
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 
diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp
index b81287ece..4297a9091 100644
--- a/src/slic3r/GUI/GLModel.cpp
+++ b/src/slic3r/GUI/GLModel.cpp
@@ -935,11 +935,7 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
 
     GLShaderProgram* shader = wxGetApp().get_current_shader();
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced_attr"))
-#else
     if (shader == nullptr || !boost::algorithm::iends_with(shader->get_name(), "_instanced"))
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         return;
 
     // vertex attributes
diff --git a/src/slic3r/GUI/GLSelectionRectangle.cpp b/src/slic3r/GUI/GLSelectionRectangle.cpp
index 19327b33a..a8be0f84e 100644
--- a/src/slic3r/GUI/GLSelectionRectangle.cpp
+++ b/src/slic3r/GUI/GLSelectionRectangle.cpp
@@ -131,11 +131,7 @@ namespace GUI {
         glsafe(::glEnable(GL_LINE_STIPPLE));
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 
diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp
index 9f0b03ea0..a01c39864 100644
--- a/src/slic3r/GUI/GLShadersManager.cpp
+++ b/src/slic3r/GUI/GLShadersManager.cpp
@@ -35,14 +35,15 @@ std::pair<bool, std::string> GLShadersManager::init()
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
 #if ENABLE_GL_SHADERS_ATTRIBUTES
+    const std::string prefix = !GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1) ? "140/" : "110/";
     // imgui shader
-    valid &= append_shader("imgui", { "imgui.vs", "imgui.fs" });
+    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_attr", { "flat_attr.vs", "flat.fs" });
+    valid &= append_shader("flat", { prefix + "flat.vs", prefix + "flat.fs" });
     // basic shader for textures, used to render textures
-    valid &= append_shader("flat_texture_attr", { "flat_texture_attr.vs", "flat_texture.fs" });
+    valid &= append_shader("flat_texture", { prefix + "flat_texture.vs", prefix + "flat_texture.fs" });
     // used to render 3D scene background
-    valid &= append_shader("background_attr", { "background_attr.vs", "background.fs" });
+    valid &= append_shader("background", { prefix + "background.vs", prefix + "background.fs" });
 #else
     // basic shader, used to render all what was previously rendered using the immediate mode
     valid &= append_shader("flat", { "flat.vs", "flat.fs" });
@@ -55,16 +56,16 @@ std::pair<bool, std::string> GLShadersManager::init()
 #if ENABLE_SHOW_TOOLPATHS_COG
     // used to render toolpaths center of gravity
 #if ENABLE_GL_SHADERS_ATTRIBUTES
-    valid &= append_shader("toolpaths_cog_attr", { "toolpaths_cog_attr.vs", "toolpaths_cog.fs" });
+    valid &= append_shader("toolpaths_cog", { prefix + "toolpaths_cog.vs", prefix + "toolpaths_cog.fs" });
 #else
     valid &= append_shader("toolpaths_cog", { "toolpaths_cog.vs", "toolpaths_cog.fs" });
 #endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #endif // ENABLE_SHOW_TOOLPATHS_COG
 #if ENABLE_GL_SHADERS_ATTRIBUTES
     // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
-    valid &= append_shader("gouraud_light_attr", { "gouraud_light_attr.vs", "gouraud_light.fs" });
+    valid &= append_shader("gouraud_light", { prefix + "gouraud_light.vs", prefix + "gouraud_light.fs" });
     // used to render printbed
-    valid &= append_shader("printbed_attr", { "printbed_attr.vs", "printbed.fs" });
+    valid &= append_shader("printbed", { prefix + "printbed.vs", prefix + "printbed.fs" });
 #else
     // used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
     valid &= append_shader("gouraud_light", { "gouraud_light.vs", "gouraud_light.fs" });
@@ -74,14 +75,14 @@ std::pair<bool, std::string> GLShadersManager::init()
     // used to render options in gcode preview
     if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) {
 #if ENABLE_GL_SHADERS_ATTRIBUTES
-        valid &= append_shader("gouraud_light_instanced_attr", { "gouraud_light_instanced_attr.vs", "gouraud_light_instanced.fs" });
+        valid &= append_shader("gouraud_light_instanced", { prefix + "gouraud_light_instanced.vs", prefix + "gouraud_light_instanced.fs" });
 #else
         valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" });
 #endif // ENABLE_GL_SHADERS_ATTRIBUTES
     }
 #if ENABLE_GL_SHADERS_ATTRIBUTES
     // used to render objects in 3d editor
-    valid &= append_shader("gouraud_attr", { "gouraud_attr.vs", "gouraud.fs" }
+    valid &= append_shader("gouraud", { prefix + "gouraud.vs", prefix + "gouraud.fs" }
 #else
     // used to render extrusion and travel paths as lines in gcode preview
     valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" });
@@ -94,9 +95,9 @@ std::pair<bool, std::string> GLShadersManager::init()
         );
 #if ENABLE_GL_SHADERS_ATTRIBUTES
     // used to render variable layers heights in 3d editor
-    valid &= append_shader("variable_layer_height_attr", { "variable_layer_height_attr.vs", "variable_layer_height.fs" });
+    valid &= append_shader("variable_layer_height", { prefix + "variable_layer_height.vs", prefix + "variable_layer_height.fs" });
     // used to render highlight contour around selected triangles inside the multi-material gizmo
-    valid &= append_shader("mm_contour_attr", { "mm_contour_attr.vs", "mm_contour_attr.fs" });
+    valid &= append_shader("mm_contour", { prefix + "mm_contour.vs", prefix + "mm_contour.fs" });
 #else
     // used to render variable layers heights in 3d editor
     valid &= append_shader("variable_layer_height", { "variable_layer_height.vs", "variable_layer_height.fs" });
@@ -111,9 +112,9 @@ std::pair<bool, std::string> GLShadersManager::init()
     // triangle normals inside fragment shader have the right direction.
 #if ENABLE_GL_SHADERS_ATTRIBUTES
     if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12)
-        valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" }, { "FLIP_TRIANGLE_NORMALS"sv });
+        valid &= append_shader("mm_gouraud", { prefix + "mm_gouraud.vs", prefix + "mm_gouraud.fs" }, { "FLIP_TRIANGLE_NORMALS"sv });
     else
-        valid &= append_shader("mm_gouraud_attr", { "mm_gouraud_attr.vs", "mm_gouraud_attr.fs" });
+        valid &= append_shader("mm_gouraud", { prefix + "mm_gouraud.vs", prefix + "mm_gouraud.fs" });
 #else
     if (platform_flavor() == PlatformFlavor::OSXOnArm && wxPlatformInfo::Get().GetOSMajorVersion() < 12)
         valid &= append_shader("mm_gouraud", {"mm_gouraud.vs", "mm_gouraud.fs"}, {"FLIP_TRIANGLE_NORMALS"sv});
diff --git a/src/slic3r/GUI/GLTexture.cpp b/src/slic3r/GUI/GLTexture.cpp
index 064ca1a18..137a0a109 100644
--- a/src/slic3r/GUI/GLTexture.cpp
+++ b/src/slic3r/GUI/GLTexture.cpp
@@ -358,11 +358,7 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
     GLModel model;
     model.init_from(std::move(init_data));
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_texture_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat_texture");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
index 83aed4289..aacecb6ef 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
@@ -134,11 +134,7 @@ void GLGizmoBase::render_grabbers(const BoundingBoxf3& box) const
 
 void GLGizmoBase::render_grabbers(float size) const
 {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
     shader->start_using();
@@ -153,11 +149,7 @@ void GLGizmoBase::render_grabbers(float size) const
 void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
 {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
index 5c9b08a93..9a87d5a45 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp
@@ -107,11 +107,7 @@ void GLGizmoCut::on_render()
     glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
         const Vec3d diff = plane_center - m_old_center;
@@ -197,11 +193,7 @@ void GLGizmoCut::on_render()
         shader->stop_using();
     }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
     shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
     glsafe(::glColor3f(1.0, 1.0, 0.0));
     ::glBegin(GL_LINES);
@@ -222,11 +214,7 @@ void GLGizmoCut::on_render()
     }
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    shader = wxGetApp().get_shader("flat_attr");
-#else
     shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
index 48c81bc5a..aa291f623 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoFlatten.cpp
@@ -105,11 +105,7 @@ void GLGizmoFlatten::on_render()
     const Selection& selection = m_parent.get_selection();
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
     
@@ -165,11 +161,7 @@ void GLGizmoFlatten::on_render_for_picking()
     const Selection& selection = m_parent.get_selection();
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
index e979297df..88b319f25 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp
@@ -104,11 +104,7 @@ void GLGizmoHollow::on_render_for_picking()
 void GLGizmoHollow::render_points(const Selection& selection, bool picking)
 {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
index 49eb8cb95..308100d7f 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp
@@ -170,11 +170,7 @@ void GLGizmoMmuSegmentation::data_changed()
 void GLGizmoMmuSegmentation::render_triangles(const Selection &selection) const
 {
     ClippingPlaneDataWrapper clp_data = this->get_clipping_plane_data();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    auto* shader = wxGetApp().get_shader("mm_gouraud_attr");
-#else
     auto                    *shader   = wxGetApp().get_shader("mm_gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (!shader)
         return;
     shader->start_using();
@@ -598,16 +594,13 @@ void TriangleSelectorMmGui::render(ImGuiWrapper *imgui)
     auto *shader = wxGetApp().get_current_shader();
     if (!shader)
         return;
+    assert(shader->get_name() == "mm_gouraud");
 #if ENABLE_GL_SHADERS_ATTRIBUTES
-    assert(shader->get_name() == "mm_gouraud_attr");
-
     const Camera& camera = wxGetApp().plater()->get_camera();
     const Transform3d view_model_matrix = camera.get_view_matrix() * matrix;
     shader->set_uniform("view_model_matrix", view_model_matrix);
     shader->set_uniform("projection_matrix", camera.get_projection_matrix());
     shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
-#else
-    assert(shader->get_name() == "mm_gouraud");
 #endif // ENABLE_GL_SHADERS_ATTRIBUTES
 
     for (size_t color_idx = 0; color_idx < m_gizmo_scene.triangle_indices.size(); ++color_idx) {
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
index 18acf6e9b..a798122ec 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp
@@ -154,11 +154,7 @@ void GLGizmoMove3D::on_render()
 
     if (m_hover_id == -1) {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
@@ -199,11 +195,7 @@ void GLGizmoMove3D::on_render()
     else {
         // draw axis
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 
@@ -217,11 +209,7 @@ void GLGizmoMove3D::on_render()
             shader->stop_using();
         }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
         shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
         glsafe(::glColor4fv(AXES_COLOR[m_hover_id].data()));
         ::glBegin(GL_LINES);
@@ -286,11 +274,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box
     const double size = m_dragging ? double(m_grabbers[axis].get_dragging_half_size(mean_size)) : double(m_grabbers[axis].get_half_size(mean_size));
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
     GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
index 03d60440a..01dc59514 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp
@@ -80,11 +80,7 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl
 
 void GLGizmoPainterBase::render_triangles(const Selection& selection) const
 {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    auto* shader = wxGetApp().get_shader("gouraud_attr");
-#else
     auto* shader = wxGetApp().get_shader("gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (! shader)
         return;
     shader->start_using();
@@ -250,11 +246,7 @@ void GLGizmoPainterBase::render_cursor_circle()
         m_circle.init_from(std::move(init_data));
     }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = GUI::wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -292,11 +284,7 @@ void GLGizmoPainterBase::render_cursor_sphere(const Transform3d& trafo) const
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
     }
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -927,11 +915,9 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui)
     auto* shader = wxGetApp().get_current_shader();
     if (! shader)
         return;
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    assert(shader->get_name() == "gouraud_attr");
-#else
+
     assert(shader->get_name() == "gouraud");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
+
     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),
@@ -1288,11 +1274,7 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui)
     if (curr_shader != nullptr)
         curr_shader->stop_using();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 
@@ -1375,11 +1357,7 @@ void TriangleSelectorGUI::render_paint_contour()
     if (curr_shader != nullptr)
         curr_shader->stop_using();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    auto* contour_shader = wxGetApp().get_shader("mm_contour_attr");
-#else
     auto* contour_shader = wxGetApp().get_shader("mm_contour");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (contour_shader != nullptr) {
         contour_shader->start_using();
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
index 1d817b58b..6bec8be50 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp
@@ -172,11 +172,7 @@ void GLGizmoRotate::on_render()
 
     glsafe(::glLineWidth((m_hover_id != -1) ? 2.0f : 1.5f));
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 
@@ -576,11 +572,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick
     const double size = m_dragging ? double(m_grabbers.front().get_dragging_half_size(mean_size)) : double(m_grabbers.front().get_half_size(mean_size));
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat_attr" : "gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
index 373a2396d..26c9251b4 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp
@@ -265,11 +265,7 @@ void GLGizmoScale3D::on_render()
     if (m_hover_id == -1) {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
         // draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -316,11 +312,7 @@ void GLGizmoScale3D::on_render()
     else if (m_hover_id == 0 || m_hover_id == 1) {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
         // draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -333,11 +325,7 @@ void GLGizmoScale3D::on_render()
         }
 
         // draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
         shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
         // draw connection
         glsafe(::glColor4fv(m_grabbers[0].color.data()));
@@ -357,11 +345,7 @@ void GLGizmoScale3D::on_render()
     else if (m_hover_id == 2 || m_hover_id == 3) {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
         // draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -374,11 +358,7 @@ void GLGizmoScale3D::on_render()
         }
 
         // draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
         shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
         // draw connection
         glsafe(::glColor4fv(m_grabbers[2].color.data()));
@@ -398,11 +378,7 @@ void GLGizmoScale3D::on_render()
     else if (m_hover_id == 4 || m_hover_id == 5) {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
         // draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -415,11 +391,7 @@ void GLGizmoScale3D::on_render()
         }
 
         // draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
         shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
         // draw connection
         glsafe(::glColor4fv(m_grabbers[4].color.data()));
@@ -439,11 +411,7 @@ void GLGizmoScale3D::on_render()
     else if (m_hover_id >= 6) {
 #if ENABLE_LEGACY_OPENGL_REMOVAL
         // draw connections
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
         GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
         if (shader != nullptr) {
             shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
@@ -459,11 +427,7 @@ void GLGizmoScale3D::on_render()
         }
 
         // draw grabbers
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
         shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
 #else
         // draw connection
         glsafe(::glColor4fv(m_drag_color.data()));
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
index 1a383187c..bce1123e0 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp
@@ -737,14 +737,11 @@ void GLGizmoSimplify::on_render()
         GLModel &glmodel = it->second;
 
         const Transform3d trafo_matrix = selected_volume->world_matrix();
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-        auto* gouraud_shader = wxGetApp().get_shader("gouraud_light_attr");
-#else
+#if !ENABLE_GL_SHADERS_ATTRIBUTES
         glsafe(::glPushMatrix());
         glsafe(::glMultMatrixd(trafo_matrix.data()));
-
-        auto *gouraud_shader = wxGetApp().get_shader("gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
+#endif // !ENABLE_GL_SHADERS_ATTRIBUTES
+        auto* gouraud_shader = wxGetApp().get_shader("gouraud_light");
         glsafe(::glPushAttrib(GL_DEPTH_TEST));
         glsafe(::glEnable(GL_DEPTH_TEST));
         gouraud_shader->start_using();
@@ -759,11 +756,7 @@ void GLGizmoSimplify::on_render()
         gouraud_shader->stop_using();
 
         if (m_show_wireframe) {
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-            auto* contour_shader = wxGetApp().get_shader("mm_contour_attr");
-#else
             auto *contour_shader = wxGetApp().get_shader("mm_contour");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
             contour_shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
             contour_shader->set_uniform("view_model_matrix", view_model_matrix);
diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
index 4007f0cb0..7c61673b4 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp
@@ -130,11 +130,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
         return;
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat_attr") : wxGetApp().get_shader("gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader(picking ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp
index e7e9ba2fb..bbdcdeb34 100644
--- a/src/slic3r/GUI/MeshUtils.cpp
+++ b/src/slic3r/GUI/MeshUtils.cpp
@@ -87,11 +87,7 @@ void MeshClipper::render_cut()
     if (curr_shader != nullptr)
         curr_shader->stop_using();
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader != nullptr) {
         shader->start_using();
 #if ENABLE_GL_SHADERS_ATTRIBUTES
diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp
index 68a052341..7ccc6fc25 100644
--- a/src/slic3r/GUI/Selection.cpp
+++ b/src/slic3r/GUI/Selection.cpp
@@ -1275,11 +1275,7 @@ void Selection::render_center(bool gizmo_is_dragging)
         return;
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -1324,11 +1320,7 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field)
         return;
 
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat_attr" : "gouraud_light_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader(boost::starts_with(sidebar_field, "layer") ? "flat" : "gouraud_light");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 
@@ -2020,11 +2012,7 @@ void Selection::render_bounding_box(const BoundingBoxf3 & box, float* color) con
 
     glsafe(::glLineWidth(2.0f * m_scale_factor));
 
-#if ENABLE_GL_SHADERS_ATTRIBUTES
-    GLShaderProgram* shader = wxGetApp().get_shader("flat_attr");
-#else
     GLShaderProgram* shader = wxGetApp().get_shader("flat");
-#endif // ENABLE_GL_SHADERS_ATTRIBUTES
     if (shader == nullptr)
         return;
 

From 9be3d926c5ff8debf25f22e2d53dd1410bfcdd79 Mon Sep 17 00:00:00 2001
From: enricoturri1966 <enricoturri@seznam.cz>
Date: Tue, 22 Mar 2022 08:18:39 +0100
Subject: [PATCH 6/6] Tech ENABLE_LEGACY_OPENGL_REMOVAL - A few refactorings
 and fixes

---
 resources/shaders/140/flat_texture.fs         |  2 +-
 resources/shaders/140/gouraud.fs              |  2 +-
 resources/shaders/140/imgui.fs                |  4 ++--
 resources/shaders/140/printbed.fs             |  4 ++--
 .../shaders/140/variable_layer_height.fs      |  4 ++--
 src/slic3r/GUI/GLModel.cpp                    | 21 ++++++++++---------
 src/slic3r/GUI/ImGuiWrapper.cpp               | 19 ++++++++++-------
 7 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/resources/shaders/140/flat_texture.fs b/resources/shaders/140/flat_texture.fs
index 7db62b682..dec946721 100644
--- a/resources/shaders/140/flat_texture.fs
+++ b/resources/shaders/140/flat_texture.fs
@@ -6,5 +6,5 @@ in vec2 tex_coord;
 
 void main()
 {
-    gl_FragColor = texture2D(uniform_texture, tex_coord);
+    gl_FragColor = texture(uniform_texture, tex_coord);
 }
diff --git a/resources/shaders/140/gouraud.fs b/resources/shaders/140/gouraud.fs
index 7651380d7..beb3a947b 100644
--- a/resources/shaders/140/gouraud.fs
+++ b/resources/shaders/140/gouraud.fs
@@ -74,7 +74,7 @@ void main()
 	
 #ifdef ENABLE_ENVIRONMENT_MAP
     if (use_environment_tex)
-        gl_FragColor = vec4(0.45 * texture2D(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
+        gl_FragColor = vec4(0.45 * texture(environment_tex, normalize(eye_normal).xy * 0.5 + 0.5).xyz + 0.8 * color * intensity.x, alpha);
     else
 #endif
         gl_FragColor = vec4(vec3(intensity.y) + color * intensity.x, alpha);
diff --git a/resources/shaders/140/imgui.fs b/resources/shaders/140/imgui.fs
index 8e7999fdf..4b2571749 100644
--- a/resources/shaders/140/imgui.fs
+++ b/resources/shaders/140/imgui.fs
@@ -1,4 +1,4 @@
-#version 110
+#version 140
 
 uniform sampler2D Texture;
 
@@ -7,5 +7,5 @@ in vec4 Frag_Color;
 
 void main()
 {
-	gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);
+	gl_FragColor = Frag_Color * texture(Texture, Frag_UV.st);
 }
\ No newline at end of file
diff --git a/resources/shaders/140/printbed.fs b/resources/shaders/140/printbed.fs
index 73ff8f690..86edd0daf 100644
--- a/resources/shaders/140/printbed.fs
+++ b/resources/shaders/140/printbed.fs
@@ -12,7 +12,7 @@ in vec2 tex_coord;
 vec4 svg_color()
 {
     // takes foreground from texture
-    vec4 fore_color = texture2D(texture, tex_coord);
+    vec4 fore_color = texture(texture, tex_coord);
 
     // calculates radial gradient
     vec3 back_color = vec3(mix(back_color_light, back_color_dark, smoothstep(0.0, 0.5, length(abs(tex_coord.xy) - vec2(0.5)))));
@@ -24,7 +24,7 @@ vec4 svg_color()
 vec4 non_svg_color()
 {
     // takes foreground from texture
-    vec4 color = texture2D(texture, tex_coord);
+    vec4 color = texture(texture, tex_coord);
     return vec4(color.rgb, transparent_background ? color.a * 0.25 : color.a);
 }
 
diff --git a/resources/shaders/140/variable_layer_height.fs b/resources/shaders/140/variable_layer_height.fs
index 5fa7e6835..cf1fc309c 100644
--- a/resources/shaders/140/variable_layer_height.fs
+++ b/resources/shaders/140/variable_layer_height.fs
@@ -34,8 +34,8 @@ void main()
     // Sample the Z texture. Texture coordinates are normalized to <0, 1>.
     vec4 color = vec4(0.25, 0.25, 0.25, 1.0);
     if (z_texture_row >= 0.0)
-        color = mix(texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5    )), -10000.),
-                    texture2D(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)),  10000.), lod);            
+        color = mix(texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row + 0.5    )), -10000.),
+                    texture(z_texture, vec2(z_texture_col, z_texture_row_to_normalized * (z_texture_row * 2. + 1.)),  10000.), lod);            
     // Mix the final color.
     gl_FragColor = vec4(vec3(intensity.y), 1.0) +  intensity.x * mix(color, vec4(1.0, 1.0, 0.0, 1.0), z_blend);
 }
diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp
index 4297a9091..9c9d69526 100644
--- a/src/slic3r/GUI/GLModel.cpp
+++ b/src/slic3r/GUI/GLModel.cpp
@@ -861,7 +861,7 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
 #if ENABLE_GL_SHADERS_ATTRIBUTES
         position_id = shader->get_attrib_location("v_position");
         if (position_id != -1) {
-            glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format)));
+            glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format)));
             glsafe(::glEnableVertexAttribArray(position_id));
         }
 #else
@@ -873,7 +873,7 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
 #if ENABLE_GL_SHADERS_ATTRIBUTES
         normal_id = shader->get_attrib_location("v_normal");
         if (normal_id != -1) {
-            glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format)));
+            glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format)));
             glsafe(::glEnableVertexAttribArray(normal_id));
         }
 #else
@@ -885,7 +885,7 @@ void GLModel::render(const std::pair<size_t, size_t>& range)
 #if ENABLE_GL_SHADERS_ATTRIBUTES
         tex_coord_id = shader->get_attrib_location("v_tex_coord");
         if (tex_coord_id != -1) {
-            glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::tex_coord_offset_bytes(data.format)));
+            glsafe(::glVertexAttribPointer(tex_coord_id, Geometry::tex_coord_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::tex_coord_offset_bytes(data.format)));
             glsafe(::glEnableVertexAttribArray(tex_coord_id));
         }
 #else
@@ -930,7 +930,7 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
 void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const
 #endif // ENABLE_LEGACY_OPENGL_REMOVAL
 {
-    if (instances_vbo == 0)
+    if (instances_vbo == 0 || instances_count == 0)
         return;
 
     GLShaderProgram* shader = wxGetApp().get_current_shader();
@@ -970,11 +970,12 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
 
     glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instances_vbo));
 #if ENABLE_LEGACY_OPENGL_REMOVAL
-    glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0));
+    const size_t instance_stride = 5 * sizeof(float);
+    glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, instance_stride, (const void*)0));
     glsafe(::glEnableVertexAttribArray(offset_id));
     glsafe(::glVertexAttribDivisor(offset_id, 1));
 
-    glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)(3 * sizeof(float))));
+    glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, instance_stride, (const void*)(3 * sizeof(float))));
     glsafe(::glEnableVertexAttribArray(scales_id));
     glsafe(::glVertexAttribDivisor(scales_id, 1));
 #else
@@ -996,8 +997,6 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
     const GLenum mode = get_primitive_mode(data.format);
     const GLenum index_type = get_index_type(data);
 
-    shader->set_uniform("uniform_color", data.color);
-
     const size_t vertex_stride_bytes = Geometry::vertex_stride_bytes(data.format);
     const bool position = Geometry::has_position(data.format);
     const bool normal   = Geometry::has_normal(data.format);
@@ -1005,15 +1004,17 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance
     glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_render_data.vbo_id));
 
     if (position) {
-        glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::position_offset_bytes(data.format)));
+        glsafe(::glVertexAttribPointer(position_id, Geometry::position_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::position_offset_bytes(data.format)));
         glsafe(::glEnableVertexAttribArray(position_id));
     }
 
     if (normal) {
-        glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (GLvoid*)Geometry::normal_offset_bytes(data.format)));
+        glsafe(::glVertexAttribPointer(normal_id, Geometry::normal_stride_floats(data.format), GL_FLOAT, GL_FALSE, vertex_stride_bytes, (const void*)Geometry::normal_offset_bytes(data.format)));
         glsafe(::glEnableVertexAttribArray(normal_id));
     }
 
+    shader->set_uniform("uniform_color", data.color);
+
     glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_render_data.ibo_id));
     glsafe(::glDrawElementsInstanced(mode, indices_count(), index_type, (const void*)0, instances_count));
     glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp
index e659a386b..d5dfa276c 100644
--- a/src/slic3r/GUI/ImGuiWrapper.cpp
+++ b/src/slic3r/GUI/ImGuiWrapper.cpp
@@ -1475,10 +1475,10 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
 
     // We are using the OpenGL fixed pipeline to make the example code simpler to read!
     // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers, polygon fill.
-    GLint last_texture; glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
-    GLint last_polygon_mode[2]; glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode));
-    GLint last_viewport[4]; glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport));
-    GLint last_scissor_box[4]; glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box));
+    GLint last_texture;          glsafe(::glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
+    GLint last_polygon_mode[2];  glsafe(::glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode));
+    GLint last_viewport[4];      glsafe(::glGetIntegerv(GL_VIEWPORT, last_viewport));
+    GLint last_scissor_box[4];   glsafe(::glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box));
     GLint last_texture_env_mode; glsafe(::glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_texture_env_mode));
     glsafe(::glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT));
     glsafe(::glEnable(GL_BLEND));
@@ -1553,17 +1553,17 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
 
         const int position_id = shader->get_attrib_location("Position");
         if (position_id != -1) {
-            glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
+            glsafe(::glVertexAttribPointer(position_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, pos)));
             glsafe(::glEnableVertexAttribArray(position_id));
         }
         const int uv_id = shader->get_attrib_location("UV");
         if (uv_id != -1) {
-            glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
+            glsafe(::glVertexAttribPointer(uv_id, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, uv)));
             glsafe(::glEnableVertexAttribArray(uv_id));
         }
         const int color_id = shader->get_attrib_location("Color");
         if (color_id != -1) {
-            glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
+            glsafe(::glVertexAttribPointer(color_id, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (const void*)IM_OFFSETOF(ImDrawVert, col)));
             glsafe(::glEnableVertexAttribArray(color_id));
         }
 #else
@@ -1637,11 +1637,14 @@ void ImGuiWrapper::render_draw_data(ImDrawData *draw_data)
     glsafe(::glPopMatrix());
 #endif // !ENABLE_GL_IMGUI_SHADERS
     glsafe(::glPopAttrib());
-    glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]));
+    glsafe(::glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]);
+    glsafe(::glPolygonMode(GL_BACK,  (GLenum)last_polygon_mode[1])));
     glsafe(::glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]));
     glsafe(::glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]));
 
 #if ENABLE_GL_IMGUI_SHADERS
+    shader->stop_using();
+
     if (curr_shader != nullptr)
         curr_shader->start_using();
 #endif // ENABLE_GL_IMGUI_SHADERS