Qt5.6: suporte a altos DPI e OpenGL (OpenSceneGraph)
Eu tenho um aplicativo mínimo que usaQOpenGLWidget
que integra uma biblioteca de wrappers OpenGL (OpenSceneGraph). Estou tentando descobrir como usar corretamente o suporte Qt5.6 para telas de alto DPI ao lidar com conteúdo OpenGL como eu uso.
Minhasmain()
A função possui o seguinte código:
int main(int argc, char** argv)
{
// DPI support is on
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QMainWindow window;
// QOpenGLWidget with OpenSceneGraph content
QtOSGWidget* widget = new QtOSGWidget();
window.setCentralWidget(widget);
window.show();
return app.exec();
}
oQtOSGWidget
é derivado deQOpenGLWidget
com conteúdo OpenSceneGraph: eu usoosgViewer::GraphicsWindowEmbedded
para renderizar minha cena simples.
Para mesclar OSG com Qt, redefino o*GL()
métodos:paintGL()
, resizeGL()
einitializeGL()
. Sigo os documentos Qt sobre o que cada um dos*GL()
métodos devem conter, ou seja:
paintGL()
garante que o visualizador seja atualizadoresizeGL()
garante que a janela de desenho seja redimensionada corretamente (junto com a câmera e a janela de visualização);initializeGL()
garante que o estado OpenGL seja inicializado.Também redefini os eventos do mouse Qt para passar os eventos para o OSGQuando executo meu exemplo na tela de resolução normal, ou comQApplication::setAttribute(Qt::AA_DisableHighDpiScaling);
, a cena parece que deveria:
Além disso, quando manipulo a visualização da câmera, as coordenadas do mouse são capturadas corretamente.
No entanto, quando eu ativo a opção de DPI alto, é isso que recebo:
As coordenadas do mouse para eventos também são dimensionadas e não são passadas para o manipulador de eventos do OpenSceneGraph corretamente.
Como você pode ver, o tamanho da janela de desenho não é dimensionado pelo Qt. Provavelmente é por causa da maneira como eu configuro o dimensionamento:
virtual void resizeGL( int width, int height )
{
// resize event is passed to OSG
this->getEventQueue()->windowResize(this->x(), this->y(), width, height);
// graphics window resize
m_graphicsWindow->resized(this->x(), this->y(), width, height);
// camera viewport
osg::Camera* camera = m_viewer->getCamera();
camera->setViewport(0, 0, this->width(), this->height());
}
Esse dimensionamento não é dimensionado pelo Qt. O mesmo acontece com as coordenadas dos eventos do mouse.
Minha pergunta: existe uma maneira de saber em que tamanho a escala será executada para queresizeGL()
corretamente? Ou qual é a maneira correta de lidar com o problema?
Atualização / solução usando o dimensionamento manualmente: graças à resposta do @AlexanderVX, descobri a solução de dimensionamento. No começo, preciso conhecer alguns valores de referência de DPI nas dimensões X e Y. Então eu calculo as coordenadas de escala com base nisso e as passo para o meu widgetQtOSGWidget
. Então, o código domain()
deve conter:
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
int x = QApplication::desktop()->physicalDpiX();
int y = QApplication::desktop()->physicalDpiY();
// values 284 and 285 are the reference values
double scaleX = 284.0/double(x);
double scaleY = 285.0/double(y);
QMainWindow window;
QtOSGWidget* widget = new QtOSGWidget(scaleX, scaleY, &window);
// etc.
Então, sempre que me refiro às funções de dimensionamento que precisavam ser passadas para o conteúdo do OpenSceneGraph (OpenGL), preciso fazer o dimensionamento, por exemplo:
// resizeGL example
this->getEventQueue()->windowResize(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);
// mouse event example
this->getEventQueue()->mouseButtonPress(event->x()*m_scaleX, event->y()*m_scaleY, button);
Atualização final: como a plataforma de destino do meu aplicativo é o Windows 7-10, faz muito mais sentido seguir a resposta proposta por @AlexanderV (segunda parte), ou seja, usarSetProcessDPIAware()
função.