Qt 3D的研究(二)

Qt 3D的研究(二)

       上一篇文章给大家看了很多Qt 3D的例子,如果大家有Qt 3D的源代码,就会发现,开发这些例子,花费的代码还真不少。这就是不一样的地方,Qt 3D毕竟和三维图形打交道,多了一个维度,问题的难度变得更大了。

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

       研究了多日的Qt 3D,我了解到为了适应跨平台、不同的着色器编译器标准、多重渲染目标,Qt 3D提出了很多的方案,创新了许多的概念,这多多少少让初学者感到困难重重。在与Qt开发者经过jira以及IRC等交流后,我了解到了如何使用Qt 3D构建一个简单的程序。

       这个程序呢,虽然说简单,但是是Qt 3D中精简的最少代码了。让我们首先看看main.qml。

import Qt3D 2.0
import Qt3D.Render 2.0

Entity
{
    components: FrameGraph
    {
        ForwardRenderer
        {
            clearColor: Qt.rgba( 0.2, 0, 0, 1 )
        }
    }
}

       Qt 3D和其它的库不一样,它的main.qml放的是Entity,而不是我们常见的Window或者ApplicationWindow。其次,我们看到他里面没有QtQuick的引用。这个可能因为Qt3D不直接建立在QtQuick上,而是建立在了QtQml模块上,所以提供了QML的语法,但是我们看不见常见的QtQuick类型比如说Item什么的。这两个变化是第一眼看出来比较明显的。

       接下来介绍一下Qt 3D的FrameGraph,前段时间我为了深入研究QtQuick的渲染,曾经研究了Qt的SceneGraph框架。后面发现在SceneGraph下进行渲染,还是有种种限制,无法更好地渲染出漂亮的3D图形出来。于是,我开始离开Scene Graph,转向使用原生OpenGL进行渲染,以及开始接触Qt3D的FrameGraph。在介绍Qt3D的英文博客中,作者更是说明,SceneGraph能让我们用数据驱动的方式告诉我们要渲染什么东西,而Frame Graph能让我们用数据驱动的方式告诉我们怎样渲染。这是一个比较大,也比较难的转变。尝试做一个Qt 3D框架的人都有此感。想要拥有一个什么都可以configurable(可配置)的框架,自己制作起来是多么难。FrameGraph,则是告诉底层渲染器,我们需要怎样渲染,效果是怎么样的。在FrameGraph中,只有ForwardRenderer,告诉我们按照普通前向渲染的方式进行。里面我们指定了一个刷新的颜色。估计是采用glClearColor这个API指定的吧。

       接下来我们转向C++。C++这边也和普通的Quick程序不一样了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 

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

    Qt3D::Window window;
    Qt3D::Quick::QQmlAspectEngine engine;
    engine.aspectEngine( )->registerAspect( new Qt3D::QRenderAspect );
    engine.aspectEngine( )->registerAspect( new Qt3D::QInputAspect );
    engine.aspectEngine( )->initialize( );

    QVariantMap data;
    data.insert( QStringLiteral( "surface" ),
                 QVariant::fromValue( static_cast( &window ) ) );
    data.insert( QStringLiteral( "eventSource" ),
                 QVariant::fromValue( &window ) );
    engine.aspectEngine( )->setData( data );

    engine.aspectEngine( )->initialize( );
    engine.setSource( QUrl( "qrc:/main.qml" ) );

    // 让窗口以一定的大小居中显示
    int clientWidth = app.desktop( )->availableGeometry( ).width( );
    int clientHeight = app.desktop( )->availableGeometry( ).height( );
    int windowWidth = 480;
    int windowHeight = 320;

    window.setGeometry( ( clientWidth - windowWidth ) / 2,
                        ( clientHeight - windowHeight ) / 2,
                        windowWidth,
                        windowHeight );
    window.show( );

    return app.exec( );
}

 
  

       我们使用的引擎不是简单的QQmlApplicationEngine类,而是Qt3D::Quick::QqmlAspectEngine类。这里有一个重要的概念——面向方面。所以在其中你看到很多Aspect字眼。这是因为我们将一个实体(Entity)分成很多组件(Component),其中有很多组件组合起来成为一个方面,剩下的组成另外一个方面。比如说Qt 3D有核心方面、渲染方面、声音方面、输入方面、Quick渲染方面。它们被组成一个个库,根据用户的需求来链接。

       当然,作为Qt 3D的核心,Qt 3D必须要一个窗口来显示。Qt3D自己封装了一个窗口,名叫Qt3D::Window,它也不继承QQuickWindow,而是继承它的父类QWindow。目前window的信息,还是需要显式写入引擎的data中。最后引擎设置一下qml文件,接下来设置一下窗口大小和方位就可以正常显示了。

       程序的截图如下所示:

Qt 3D的研究(二)_第1张图片

       虽然不是那么激动人心,但是这的确是能运行Qt 3D程序最少的代码了。

       想要了解更多Qt 3D的介绍,推荐大家看KDAB的博客。

Overview of Qt3D 2.0 –Part 1

Overview of Qt3D 2.0 –Part 2

你可能感兴趣的:(Qt3D,Qt)