首页 > 代码库 > Qt新渲染底层Scene Graph研究(二)

Qt新渲染底层Scene Graph研究(二)

Qt新渲染底层Scene Graph研究(二)

       上一篇文章初步介绍了Qt新渲染底层Scene Graph,我们该如何利用这个框架为应用程序增添绚丽的效果呢?首先,我们要明确利用Scene Graph开发的目的是什么。如果是简单的,纯粹的显示2D图形界面,那么直接利用构建在Scene Graph之上的Qt Quick和Qt Quick Widget即可。如果觉得Qt Quick为我们提供的功能不够,在QML这一层无法很好地实现,那么我们或许需要考虑更低一层的Scene Graph了。一个使用Scene Graph的常见需求就是实现3D模型的渲染以及2D图元在其上的叠加(Overlay)。

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

       本文难度偏大,适合有经验的Qt开发同行学习交流。

       目前我发现了两种和Scene Graph整合渲染3D的方法。第一是采用Scene Graph提供的相关类,比如说QSGNode等一类和 QSGGeometry等一类进行渲染,此方法在Qt的例子中对应customgeometry例子,这个例子显示了2D的三次贝塞尔曲线是如何显示的;第二种是完全使用OpenGL相关的API进行渲染(为了和Qt兼容,还是建议使用QOpenGL*来包裹之),对应的例子是OpenGL under QML。我大概半年前也写了一个类似的例子(参见《Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染》)。两个例子对比下来,发现第二种方法,对于第三方库整合更容易一些,因为仅需知道OpenGL的API以及着色器的知识就好了。当然,最近我对第一种方法进行了探索,了解了SceneGraph的一些知识。

       好了,大家可以拿出自己的Qt Quick程序进行实验(如果没有的话,我的独立游戏《十日驱鬼记》和《吃药了》的Windows独立运行版可以免费下载进行实验),Windows下进入cmd,设定QSG_VISUALIZE为overdraw,大家来观察一下显示的情况。我们发现一个立方体在窗口内部晃悠,其实呢,并不是立方体在晃悠,而是Qt设定的摄像机在晃悠,场景是不动的。而这个立方体则是正常情况下我们要显示的视景体(又称平截头体)。在Qt Quick中,渲染2D使用的是正交投影而不是透视投影,所以我们看到这个是一个立方体而不是立方台。但是注意,这其中和我们建立的OpenGL场景有些微的差别。我们发现,在Qt Quick中,x向右递增,y向下递增,这和OpenGL的x向右递增,y向上递增是不一样的,而QtQuick又使用了OpenGL,也就是遵循了右手坐标系,那么它的坐标系又是怎么摆放的呢?上篇文章讲到了这个立方体的的范围是x∈[0,Screen.width],y∈[0,Screen.height],z∈[0,1],我们可以通过一张图来了解坐标系:

技术分享

       现在用右手四指指向x,大拇指指向y,那么手掌的指向就是z了。没错,这就是OpenGL右手坐标系,只不过Qt将它倒置了。同时,overdraw模式的摄像机是处在z轴的负半轴,看的大体位置在z的正半轴。而图中从左到右两个纹理的z值分别为-1和0。

在了解这一点后,我们的目标就是让我们绘制的图元尽可能地落在x∈[0,Screen.width],y∈[0,Screen.height],z∈[0,1]的范围内。这就需要我们在VBO里面详细地设定每一个顶点的位置。此外,Qt Quick中的Item::z值和OpenGL的z不是一个概念,Item::z表示叠放顺序,值越大就越摆在前面,OpenGL的z值如图,越小的越表示在前。此外,场景叠放了n层,那么就对整个视景体n等分,各层显示在前面。这个可能不好理解,还是看图吧。

技术分享

对应QML代码:

Window
{
    title: qsTr( "Scene Graph TexturedObject" )
    width: 480
    height: 320
    visible: true
 
    Rectangle
    {
        anchors.fill: parent
        color: "orange"
 
        Rectangle
        {
            anchors.centerIn: parent
            width: 100
            height: 100
            color: "blue"
        }
       }
}

技术分享

对应QML代码:

Window
{
    title: qsTr( "Scene Graph TexturedObject" )
    width: 480
    height: 320
    visible: true
 
    Rectangle
    {
        anchors.fill: parent
        color: "orange"
 
        Rectangle
        {
            anchors.centerIn: parent
            width: 100
            height: 100
            color: "blue"
 
            Rectangle
            {
                anchors.centerIn: parent
                width: 20
                height: 20
                color: "red"
            }
        }
       }
}

       下篇文章将要介绍我在Scene Graph中显示3D物体的尝试。

Qt新渲染底层Scene Graph研究(二)