Reply
Thread Tools
bbns's Avatar
Posts: 101 | Thanked: 129 times | Joined on Oct 2009 @ Los Angeles, CA
#1
Hi all,

I found N900 has been the most amazing game design device so far, yet not many people tell you how to do it. I try to give a start for people who are interested in how to blend QML and OpenGL together.

My background is software architecture and game engine. I have written game engine on iPhone but now I found N900 is easier and have more varieties to achieve the same goal, especially with the help of QML.

If you don't know what QML is, you can visit the Qt4.6 Kinetic online document here.

Now, let's take a look how to write a OpenGL program in Qt and also use QML as UI like this (it's a simple camera application powered by OpenGL).

To write a OpenGL program, we can simply use QGLWidget. However, since we want to blend with QML, directly using QGLWidget is not a good option. Instead, we want to use QGraphicsScene, that's the the fundamental element for Qt rendering objects. Note that QGraphicsScene does not discriminate OpenGL or non-OpenGL. It's decided by QPaintEngine, which later on we will use QGraphicsView to tell Qt to use OpenGL as backend.

In my first introduction of QML, I used QmlView to load QML. Although QmlView allows you to load QML quickly and easily; however, it will intercept all touch events even you click on non-interactive area. Thus, you will not be able to interact with your OpenGL content (for instance, circle a group of soldiers on the field). In this case, we will use QmlEngine directly (QmlView's backend). One more benefit, it's also faster because we just reduce a layer of wrapping.

Enough of talking, let see some code then you will know how it works in nature.

Code:
#include <QtGui>
#include <QtOpenGL>
#include <QtDeclarative>

class MyGraphicsScene: public QGraphicsScene {
public:
  MyGraphicsScene()
  {
     // load your QML before drawBackground being called.
     QmlEngine *engine = new QmlEngine();
     QmlComponent component(engine, QUrl::fromLocalFile(qmlfilename));
     QGraphicsObject *object = qobject_cast<QGraphicsObject*>(component.create());

     addItem(object);
     // done! that's all.
  }
  void drawBackground(QPainter *painter, const QRectF &)
  {
      if (painter->paintEngine()->type() != QPaintEngine::OpenGL) {
          qWarning("OpenGLScene: drawBackground needs a QGLWidget to be set as viewport on the graphics view");
            return;
      }
      // beginning of OpenGL instructions
      glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      // end of OpenGL instructions
      QTimer::singleShot(20, this, SLOT(update()));
   }
}
That's it. It's simpler than my first though.

Now, we want to trigger our QGraphicsScene class in main.cpp:

Code:
#include "mygraphicsscene.h"

#include <QtGui>
#include <QGLWidget>
class GraphicsView : public QGraphicsView
{
    public:
        GraphicsView()
        {
            setWindowTitle(tr("Hello QML and OpenGL"));
        }
    
    protected:
        void resizeEvent(QResizeEvent *event) {
            if (scene())
                scene()->setSceneRect(
                    QRect(QPoint(0, 0), event->size()));
            QGraphicsView::resizeEvent(event);
        }
};

int main(int argc, char **argv)
{
        QApplication app(argc, argv);
    
        GraphicsView view;
        QGLFormat format = QGLFormat::defaultFormat();
        // disable AA.
        format.setSampleBuffers(false); 
        view.setViewport(new QGLWidget(QGLFormat(format)));
        view.setViewportUpdateMode(
                QGraphicsView::FullViewportUpdate);
        view.setScene(new MyGraphicsScene);
        view.showFullScreen();
        view.show();
        return app.exec();
}
That's it. You shall be able to see your QML UI overlay works perfectly with OpenGL content. The background is default to what you have been drawn within drawBackground. There are a few guideline regarding performance:
1. Try to avoid non-opaque UI (i.e. alpha blending). It hurts performance also may bring rendering issues (because QML is rendered via pixmap to texture within EGL).
2. Avoid complex animation. It's not necessary to bring nice user experience as well.
3. Solid and linear gradient color on UI element is acceptable. But more than that, you might witness performance being hurt badly.
4. Clutter your OpenGL instruction together as much as possible.

If you are a game developer, you will be happy to see how QML help you avoid complex UI design! The only thing you need is focus on your OpenGL content (i.e. the 3D graphics itself). If you just want to write a 2D or pseudo-3D game, it's even easier. All you need is QML itself. See Samegame demo.

Last edited by bbns; 2010-01-10 at 03:50.
 

The Following 19 Users Say Thank You to bbns For This Useful Post:
Posts: 2,014 | Thanked: 1,581 times | Joined on Sep 2009
#2
Thanks for this - while I am not much into game development - any examples are beneficial and worth looking over purely as a learning experience.
__________________
Class .. : Power Poster, Potential Coder
Humor .. : [*********] Alignment: Chaotic Evil
Patience : [***-------] Weapon(s): +2 Logic Mace
Agro ... : |*****-----] Relic(s) : G1, N900

 
VDVsx's Avatar
Posts: 1,070 | Thanked: 1,604 times | Joined on Sep 2008 @ Helsinki
#3
Thanks for this nice tutorial, but please don't forget that we've a very nice wiki, where these tutorials should reside, in order to not be forgotten.
I would appreciate if you double post these tuts here and in the wiki. If you can't/don't have time, ask for a wikification and someone will do it for you.

Keep up the good work
__________________
Valério Valério
www.valeriovalerio.org
 

The Following User Says Thank You to VDVsx For This Useful Post:
Posts: 90 | Thanked: 48 times | Joined on Dec 2009 @ Montpellier, France
#4
Thanks too for this tuto.

You said that rendering OpenGL via QT can cause some problems with performance. What is the advantage to use QT for rendering OpenGL so far ? Especially in a game, where it will not use QT UI, and where the performance has to be important ?

Is it easier to implement ?
__________________
Smash is the way you deal with your life, like an outcast you're smashing your strife
 
bbns's Avatar
Posts: 101 | Thanked: 129 times | Joined on Oct 2009 @ Los Angeles, CA
#5
@ravioli156

The advantage of using QML and Qt is that you have network transparency, and other OS service like D-Bus with easy integration. And UI design becomes so much easier when using QML.

You don't need to create a VBO just to draw a button. You don't need sophisticated timer to create fade-in/out animation for the UI.

So that you can just focus on the 3D content without bothering extra effort of those UI (especially menu / HUD), etc.

Yes, convenient comes with price, that is performance. Pure Qt-OpenGL binding can run up to 50 FPS if you are careful. Pure full-screen QML can also enjoy the same speed. The problem is that when you mix them together, then probably 50% of performance drops (20 FPS). Major bottle neck is that EGL pixmap to texture consumes a lot of memory bandwidth. However, situation will only get improved since Qt has a task force team to address performance issue (if you check their blog daily).
__________________
Hi, I am from Nokia Research Center, Hollywood.
 

The Following User Says Thank You to bbns For This Useful Post:
Reply


 
Forum Jump


All times are GMT. The time now is 22:32.