如何使OpenGL视口具有渲染到其中的我的QML项目的确切大小和位置?

时间:2019-06-24 22:34:37

标签: c++ qt opengl qml

我正在尝试在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
    }

}

,但是红色正方形占据了第三个网格,而不是第一个:

enter image description here

我可以通过进行glViewport(this->x, WINDOW_HEIGHT-this->y, this->width, this->height);(其中WINDOW_HEIGHT的值为720来{strong>轻松来解决此问题,但是我不认为我应该信任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 个答案:

答案 0 :(得分:2)

这是伪代码中的解决方案:

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 场景图-QML下的OpenGL 示例进行了测试。 这是我所做的更改:

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