Wed, 25 May 2022 20:36:34 +0300
Fix pick() picking from weird places on the screen with high DPI scaling
glReadPixels reads data from the frame buffer, which contains data after
high DPI scaling, so any reads to that need to take this scaling into account
src/gl/partrenderer.cpp | file | annotate | diff | comparison | revisions | |
src/gl/partrenderer.h | file | annotate | diff | comparison | revisions |
--- a/src/gl/partrenderer.cpp Wed May 25 18:33:38 2022 +0300 +++ b/src/gl/partrenderer.cpp Wed May 25 20:36:34 2022 +0300 @@ -352,15 +352,21 @@ viewportVector); } -ldraw::id_t PartRenderer::pick(const QPoint& where) +ldraw::id_t PartRenderer::pick(QPoint where) { + // y is flipped, take that into account + where.setY(this->height() - where.y()); + // Since we are dealing with pixel data right from the framebuffer, its size + // will be affected by High DPI scaling. We need to take this into account + // and multiply the pixel positions by the screen pixel scaling factor. + where *= this->devicePixelRatioF(); const gl::RenderStyle oldRenderStyle = this->renderPreferences.style; this->renderPreferences.style = gl::RenderStyle::PickScene; this->makeCurrent(); this->renderScene(); std::array<GLubyte, 3> data; this->checkForGLErrors(); - glReadPixels(where.x(), this->height() - where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]); + glfunc.glReadPixels(where.x(), where.y(), 1, 1, GL_RGB, GL_UNSIGNED_BYTE, &data[0]); this->checkForGLErrors(); this->renderPreferences.style = oldRenderStyle; this->update();
--- a/src/gl/partrenderer.h Wed May 25 18:33:38 2022 +0300 +++ b/src/gl/partrenderer.h Wed May 25 20:36:34 2022 +0300 @@ -24,7 +24,7 @@ void setRenderPreferences(const gl::RenderPreferences& newPreferences); ldraw::id_t getHighlightedObject() const; protected: - ldraw::id_t pick(const QPoint& where); + ldraw::id_t pick(QPoint where); void initializeGL() override; void resizeGL(int width, int height) override; void paintGL() override;