diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ffc33a93e..9937d8de8 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3764,6 +3764,7 @@ void GLCanvas3D::_picking_pass() const // Better to use software ray - casting on a bounding - box hierarchy. if (m_multisample_allowed) + // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. glsafe(::glDisable(GL_MULTISAMPLE)); glsafe(::glDisable(GL_BLEND)); @@ -3793,7 +3794,9 @@ void GLCanvas3D::_picking_pass() const if (inside) { glsafe(::glReadPixels(m_mouse.position(0), cnv_size.get_height() - m_mouse.position(1) - 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, (void*)color)); - volume_id = color[0] + (color[1] << 8) + (color[2] << 16); + if (((color[0] | color[1] | color[2] | color[3]) & 0x7) == 0) + // Only non-interpolated colors are valid, those have their lowest three bits zeroed. + volume_id = (color[0] >> 3) + (color[1] << (5 - 3)) + (color[2] << (10 - 3)) + (color[3] << (15 - 3)); } if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) { @@ -3816,6 +3819,7 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const if (m_picking_enabled) { if (m_multisample_allowed) + // This flag is often ignored by NVIDIA drivers if rendering into a screen buffer. glsafe(::glDisable(GL_MULTISAMPLE)); glsafe(::glDisable(GL_BLEND)); @@ -3841,7 +3845,9 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const struct Pixel { std::array data; - int id() const { return data[0] + (data[1] << 8) + (data[2] << 16); } + // Only non-interpolated colors are valid, those have their lowest three bits zeroed. + bool valid() const { return ((data[0] | data[1] | data[2] | data[3]) & 0x7) == 0; } + int id() const { return (data[0] >> 3) + (data[1] << (5 - 3)) + (data[2] << (10 - 3)) + (data[3] << (15 - 3)); } }; std::vector frame(px_count); @@ -3851,17 +3857,15 @@ void GLCanvas3D::_rectangular_selection_picking_pass() const tbb::parallel_for(tbb::blocked_range(0, frame.size(), (size_t)width), [this, &frame, &idxs, &mutex](const tbb::blocked_range& range) { for (size_t i = range.begin(); i < range.end(); ++i) - { - int volume_id = frame[i].id(); - if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) - { - mutex.lock(); - idxs.insert(volume_id); - mutex.unlock(); - } - } - } - ); + if (frame[i].valid()) { + int volume_id = frame[i].id(); + if ((0 <= volume_id) && (volume_id < (int)m_volumes.volumes.size())) { + mutex.lock(); + idxs.insert(volume_id); + mutex.unlock(); + } + } + }); #else std::vector frame(4 * px_count); glsafe(::glReadPixels(left, top, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (void*)frame.data())); @@ -4040,42 +4044,27 @@ void GLCanvas3D::_render_volumes_for_picking() const // do not cull backfaces to show broken geometry, if any glsafe(::glDisable(GL_CULL_FACE)); - glsafe(::glEnable(GL_BLEND)); - glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); const Transform3d& view_matrix = m_camera.get_view_matrix(); - GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Opaque, view_matrix); - for (const GLVolumeWithIdAndZ& volume : to_render) - { - // Object picking mode. Render the object with a color encoding the object index. - unsigned int r = (volume.second.first & 0x000000FF) >> 0; - unsigned int g = (volume.second.first & 0x0000FF00) >> 8; - unsigned int b = (volume.second.first & 0x00FF0000) >> 16; - glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); - - if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) - volume.first->render(); - } - - to_render = volumes_to_render(m_volumes.volumes, GLVolumeCollection::Transparent, view_matrix); - for (const GLVolumeWithIdAndZ& volume : to_render) - { - // Object picking mode. Render the object with a color encoding the object index. - unsigned int r = (volume.second.first & 0x000000FF) >> 0; - unsigned int g = (volume.second.first & 0x0000FF00) >> 8; - unsigned int b = (volume.second.first & 0x00FF0000) >> 16; - glsafe(::glColor3f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255)); - - if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) - volume.first->render(); - } + for (size_t type = 0; type < 2; ++ type) { + GLVolumeWithIdAndZList to_render = volumes_to_render(m_volumes.volumes, (type == 0) ? GLVolumeCollection::Opaque : GLVolumeCollection::Transparent, view_matrix); + for (const GLVolumeWithIdAndZ& volume : to_render) + if (!volume.first->disabled && ((volume.first->composite_id.volume_id >= 0) || m_render_sla_auxiliaries)) { + // Object picking mode. Render the object with a color encoding the object index. + unsigned int id = volume.second.first; + unsigned int r = (id & (0x0000001F << 0)) << 3; + unsigned int g = (id & (0x0000001F << 5)) >> (5 - 3); + unsigned int b = (id & (0x0000001F << 10)) >> (10 - 3); + unsigned int a = (id & (0x0000001F << 15)) >> (15 - 3); + glsafe(::glColor4f((GLfloat)r * INV_255, (GLfloat)g * INV_255, (GLfloat)b * INV_255, (GLfloat)a * INV_255)); + volume.first->render(); + } + } glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glDisable(GL_BLEND)); glsafe(::glEnable(GL_CULL_FACE)); }