Как сделать так, чтобы область просмотра OpenGL имела точный размер и позицию моего элемента QML, который отображается в нем? - PullRequest
4 голосов
/ 25 июня 2019

Я пытаюсь визуализировать 640x360 красный квадрат внутри 1280x720 окна. Проблема в том, что область просмотра OpenGL не будет автоматически находиться внутри области, занимаемой квадратом в оконной системе Qt. То есть, если мой видеообъект имеет размеры 640x360, область просмотра OpenGl по-прежнему имеет размеры 1280x720 (ПОЧЕМУ?).

В любом случае, я могу исправить это, используя glViewport(this->x, this->y, this->width, this->height);. Проблема в том, что в OpenGL система координат имеет начало координат в левом нижнем углу, а this->x, this->y, this->width, this->height от координат объекта в синтаксисе QML, где начало координат находится в верхнем левом углу. Результат таков:

main.qml

import QtQuick 2.0

import OpenGlVideoQtQuick2 1.0


Grid {
    columns: 2
    spacing: 2    
    width: 1280
    height: 720
    OpenGlVideoQtQuick2 {
        width: 640
        height: 360
    }

}

но красный квадрат занимает 3-ю сетку вместо 1-й:

enter image description here

Я мог бы легко исправить это, выполнив glViewport(this->x, WINDOW_HEIGHT-this->y, this->width, this->height);, где WINDOW_HEIGHT будет иметь значение 720, однако я не думаю, что я должен доверять окну просмотра OpenGL, чтобы всегда иметь размер окно, поэтому вместо этого я должен получить размеры окна просмотра OpenGl, но я не думаю, что это возможно.

Я пытался

GLint dims[2] = {9999, 9999};
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
std::cout << "dimenson x:" << dims[0] << " dimenson y:" << dims[1] << std::endl;

, что дает мне dimenson x:8192 dimenson y:8192, что не имеет смысла для меня.

Вот код рендеринга OpenGL: https://github.com/lucaszanella/QQuickPaintedItemBug/blob/0a8ef6b5229afa7113ec1e4e3838981042792329/OpenGlVideoQtQuick2.cpp

Вы можете просмотреть весь сборочный проект здесь: https://github.com/lucaszanella/QQuickPaintedItemBug/tree/0a8ef6b5229afa7113ec1e4e3838981042792329

1 Ответ

2 голосов
/ 28 июня 2019

Итак, вот решение в псевдокоде:

int w = item->width() * window->devicePixelRatio();
int h = item->height() * window->devicePixelRatio();
int x = item->x();
int y = window->height()* window->devicePixelRatio() - h - item->y()

glViewport(x, y, w, h);

Я тестировал с Qt График сцены - OpenGL под примером QML .Вот изменения, которые я сделал:

main.qml

Squircle {
    x: 80
    y: 120
    width: 160
    height: 240
    [...]
}

squircle.cpp

void Squircle::sync()
{
    if (!m_renderer) {
        m_renderer = new SquircleRenderer();
        connect(window(), &QQuickWindow::beforeRendering, m_renderer, &SquircleRenderer::paint, Qt::DirectConnection);
    }
    m_renderer->setViewportSize(this->size().toSize() * window()->devicePixelRatio());
    m_renderer->setPosition(this->position().toPoint());
    m_renderer->setT(m_t);
    m_renderer->setWindow(window());
}

void SquircleRenderer::paint()
{
    [...]
    int y = (m_window->size()* m_window->devicePixelRatio()).height() - m_viewportSize.height() -  m_position.y();
    glViewport(m_position.x(), y, m_viewportSize.width(), m_viewportSize.height());
    [...]
}

squircle.h

class SquircleRenderer : public QObject, protected QOpenGLFunctions
{
    Q_OBJECT
public:

    void setPosition(const QPoint &position) { m_position = position; }

    [...]

private:
    [...]
    QPoint m_position;
};

И вот результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...