Qt Scene Graph渲染方式在不同系统的差异

本文探讨了Qt Scene Graph在Windows、Android和Ubuntu系统上的渲染差异,特别是Animator类在不同平台上的表现。在Windows上,使用Threaded Render Loop的Qt Scene Graph能保证界面流畅,而在Ubuntu上使用的基本渲染循环会导致 Animator在执行复杂运算时卡顿。通过设置环境变量,作者揭示了这些行为背后的机制,并提供了相关代码示例和系统输出信息。
摘要由CSDN通过智能技术生成

Qt Scene Graph渲染方式在不同系统的差异

       Qt Scene Graph是Qt5提出的新渲染底层,它是Qt Quick在绝大多数平台上渲染的基础(Qt4的是依赖Qt Graphics View)。了解和学习Qt的SceneGraph,怎么也不为过。最近我发现一个现象,那就是Qt Scene Graph在不同平台上的渲染流程是不一样的。通常情况下这没什么,可是它会影响Qt Quick的一些特定的类,比如说Animator。

蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/48278951。欢迎同行前来探讨。

       首先来认识一下Qt5.2引入的一个类(事实上Qt 5.5我才看到它),叫Animator,它的作用和Animation非常相似,除了不能反向运动、值不在中途更新等。它的原理是将动画分配到不同的渲染线程来完成,借助OpenGL的着色器设置,将渲染的压力分摊到其它的线程中了,听起来很好,不过我们在使用的过程中,和Animation类相差无几。那差别究竟在哪儿呢?下面我来制作一个小的例子,这个例子将模拟复杂的运算,然后看复杂运算究竟会不会影响Animator的操作。

       首先是C++的部分,很简单的一个类,以上下文变量的方式注入QML环境中:

// TestObject.h
#ifndef TESTOBJECT_H
#define TESTOBJECT_H

#include <QObject>

class TestObject : public QObject
{
    Q_OBJECT
public:
    explicit TestObject(QObject *parent = 0);
    Q_INVOKABLE void longOperation( void );
signals:
public slots:
};

#endif // TESTOBJECT_H
// TestObject.cpp
#include <QCoreApplication>
#include "TestObject.h"

TestObject::TestObject(QObject *parent) : QObject(parent)
{

}

void TestObject::longOperation( void )
{
    for ( int i = 3; i < 100000; ++i )
    {
        srand( i++ );
        int output = rand( );
        qDebug( "rand output is: %d", output );
    }
}
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "TestObject.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    qmlRegisterType<TestObject>( "Test",
                                 0,
                                 1,
                                 "TestObject" );

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

       这里使用TestObject::longOperation( )来模拟复杂的运算,然后我们在QML中找一个按钮触发这个运算:

// main.qml
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import Test 0.1

Window
{
    visible: true
    width: 270
    height: 480

    Rectangle
    {
        id: rotatingBox
        width: 150
        height: 150
        color: "lightsteelblue"
        RotationAnimator
        {
            target: rotatingBox
            from: 0
            to: 360
            duration: 1000
            loops: Animator.Infinite
            running: true
        }
    }

    Button
    {
        anchors.centerIn: parent
        text: "A long operation"
        onClicked:
        {
            to.longOperation( );
        }
    }

    TestObject
    {
        id: to
    }
}
 

         对,我们对名为“long operation”的按钮进行复杂运算的模拟。在按下这个按钮的时候,将会执行复杂的运算。我们首先在Windows上测试:结果是这样的:

         实际运行时我们发现&

以下是一个使用 OpenSceneGraphQt多线程渲染代码示例: ```cpp #include <QApplication> #include <QThread> #include <osg/Node> #include <osgViewer/Viewer> #include <osgViewer/ViewerEventHandlers> #include <osgGA/TrackballManipulator> #include <osgQt/GraphicsWindowQt> class RenderThread : public QThread { public: RenderThread(osgQt::GraphicsWindowQt* gw) : _gw(gw) {} protected: void run() { osgViewer::Viewer viewer; viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); viewer.setUpViewInWindow(0, 0, _gw->width(), _gw->height()); viewer.setSceneData(getScene()); viewer.setCameraManipulator(new osgGA::TrackballManipulator); viewer.addEventHandler(new osgViewer::StatsHandler); _gw->setTouchEventsEnabled(true); viewer.setCameraManipulator(new osgGA::TrackballManipulator); viewer.realize(); while (!viewer.done()) { _gw->makeCurrent(); viewer.frame(); _gw->swapBuffers(); } } private: osg::ref_ptr<osg::Node> getScene() { // TODO: create your scene graph here } osgQt::GraphicsWindowQt* _gw; }; int main(int argc, char** argv) { QApplication app(argc, argv); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 0; traits->y = 0; traits->width = 800; traits->height = 600; traits->windowDecoration = true; traits->doubleBuffer = true; traits->sharedContext = 0; traits->sampleBuffers = 4; traits->samples = 4; osgQt::GraphicsWindowQt* gw = new osgQt::GraphicsWindowQt(traits.get()); RenderThread thread(gw); thread.start(); gw->show(); gw->raise(); int ret = app.exec(); thread.quit(); thread.wait(); return ret; } ``` 该示例中,`RenderThread` 类是一个继承自 `QThread` 的渲染线程类。在 `run()` 函数中,我们设置了 OSG 的渲染器,并不断地进行场景渲染,直到渲染完成。`getScene()` 函数用于创建场景图。 在 `main()` 函数中,我们创建了一个 `osgQt::GraphicsWindowQt` 对象作为渲染窗口,并将其传递给 `RenderThread`。然后启动线程并显示窗口。在应用程序退出时,我们终止线程并等待其完成。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值