Horde3D

Next-Generation Graphics Engine
It is currently 22.11.2024, 14:45

All times are UTC + 1 hour




Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: 25.02.2012, 16:48 
Offline

Joined: 09.02.2012, 22:38
Posts: 26
Hi,

I have a working implementation of Horde3D along with QtQuick 1.0 (see stripped code snipped below). There is a very fundamental problem with this implementation: The Horde3DViewport won't render correctly if flipped or rotated by QML (think of taking the result image and putting it inside a Flippable). To make this work properly I think Horde3D should be rendering to an FBO. This FBO should then be rendered to a quad - with proper rotation and projection matrices.

I have thought about using h3dGetRenderTargetData(...), but I think that won't perform well, because it will copy every frame from VRAM to RAM and back again. Any hints how to get this working?

Code:
class Horde3DViewport : public QDeclarativeItem
{
    Q_OBJECT
public:
    Horde3DViewport(QDeclarativeItem *parent)
        : QDeclarativeItem(parent), m_initialized(false), m_animation(this)
    {
        setFlag(QGraphicsItem::ItemHasNoContents, false);
        // XXX: start redraw animation (a timer, that calls QDeclarativeItem::update()).
    }

    ~Horde3DViewport()
    {
        // XXX: destroy scene and release Horde3D.
    }
       
protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        Q_UNUSED(option);
        QPaintEngine::Type engineType = painter->paintEngine()->type();
        if (engineType == QPaintEngine::OpenGL || engineType == QPaintEngine::OpenGL2) {
            painter->beginNativePainting();
            // Initialize.
            if (!m_initialized) {
                // XXX: initialize Horde3D and create a scene
                m_initialized = true;
            }
            // Render.
            h3dRender(m_camera);
            h3dFinalizeFrame();
            // Restore render state.
            glBindBuffer(GL_ARRAY_BUFFER, 0);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
            glBindRenderbuffer(GL_RENDERBUFFER, 0);
            glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
            painter->endNativePainting();
        }
    }
   

private:
    // XXX: Pipeline, etc.
    H3DNode m_camera;
};


Top
 Profile  
Reply with quote  
PostPosted: 25.02.2012, 19:54 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
One of the last changes to the SVN trunk was that Horde does not bind 0 as the main render target anymore but does retain the currently bound FBO and use that to render the main output into. So if you create an bind an FBO outside of Horde and then call it's render function you should get what you want.


Top
 Profile  
Reply with quote  
PostPosted: 26.02.2012, 02:18 
Offline

Joined: 09.02.2012, 22:38
Posts: 26
Thanks alot. I had to work around one thing: GL_CULL_FACE, GL_DEPTH_TEST and GL_MULTISAMPLE dont get restored (had to brute-force-check the OpenGL state using glIsEnabled :mrgreen: ).

A simplified (untested) version of my code is below (Header+Source+QDeclarativeView usage). Steal it if you want to :)

Cheers,
Christoph

Code:
#ifndef HORDEVIEWPORT_H
#define HORDEVIEWPORT_H

#include <QtDeclarative/QDeclarativeItem>
#include <QtCore/QBasicTimer>
#include <Horde3D.h>

class QGLFramebufferObject;
class HordeViewport;

class HordeViewportAnimation : public QAbstractAnimation
{
    Q_OBJECT
public:
    HordeViewportAnimation(HordeViewport *parent = 0);
    ~HordeViewportAnimation();

    int duration() const;

protected:
    void updateCurrentTime(int currentTime);

private:
    HordeViewport* m_viewport;
};

class HordeViewport : public QDeclarativeItem
{
    Q_OBJECT
public:
    HordeViewport(QDeclarativeItem *parent = 0);
    ~HordeViewport();

protected:
    void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    void validateGL(int deviceWidth, int deviceHeight);
    void paintGL();

   bool m_firstRun;
    bool m_valid;
    QGLFramebufferObject *m_fbo;
    HordeViewportAnimation m_animation;
    H3DNode m_camera;
};

QML_DECLARE_TYPE(HordeViewport)

#endif


Code:
#include "hordeviewport.h"
#include <QGLFramebufferObject>

HordeViewportAnimation::HordeViewportAnimation(HordeViewport *parent)
    : QAbstractAnimation(parent), m_viewport(parent)
{
    // Do nothing.
}

HordeViewportAnimation::~HordeViewportAnimation()
{
    // Do nothing.
}

int HordeViewportAnimation::duration() const
{
    // Duration is undefined (infinite).
    return -1;
}

void HordeViewportAnimation::updateCurrentTime(int currentTime)
{
    // Schedule redraw.
    m_viewport->update();
}

HordeViewport::HordeViewport(QDeclarativeItem *parent)
    : QDeclarativeItem(parent), m_firstRun(true), m_valid(false),
      m_fbo(0), m_animation(this), m_camera(0)
{
    setFlag(QGraphicsItem::ItemHasNoContents, false);
    m_animation.start();
}

HordeViewport::~HordeViewport()
{
    h3dRelease();
    m_animation.stop();
    if (m_fbo) {
        delete m_fbo;
    }
}

void HordeViewport::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(option);
    QPaintEngine::Type engineType = painter->paintEngine()->type();
    if (engineType == QPaintEngine::OpenGL || engineType == QPaintEngine::OpenGL2) {
        painter->beginNativePainting();
        // Validate if required.
        if (!m_valid) {
            validateGL(painter->device()->width(),
                       painter->device()->height());
            m_valid = true;
        }
        // Render to FBO.
        m_fbo->bind();
        paintGL();
        m_fbo->release();
        // Render FBO to quad.
        glEnable(GL_TEXTURE_2D);
        m_fbo->drawTexture(QPointF(0, 0), m_fbo->texture());
        painter->endNativePainting();
    }
}

void HordeViewport::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
    QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
    m_valid = false;
}

void HordeViewport::validateGL(int deviceWidth, int deviceHeight)
{
   if (m_firstRun) {
      if (!h3dInit()) {
         qCritical() << "h3dInit failed";
      }
      // XXX: other init code
        m_firstRun = false;
   }
    if (m_fbo) {
        delete m_fbo;
    }
    m_fbo = new QGLFramebufferObject(deviceWidth, deviceHeight);
    if (m_camera) {
        // Resize viewport
        h3dSetNodeParamI(m_camera, H3DCamera::ViewportXI, 0);
        h3dSetNodeParamI(m_camera, H3DCamera::ViewportYI, 0);
        h3dSetNodeParamI(m_camera, H3DCamera::ViewportWidthI, deviceWidth);
        h3dSetNodeParamI(m_camera, H3DCamera::ViewportHeightI, deviceHeight);
        // Set virtual camera parameters
        float aspectRatio = static_cast<float>(deviceWidth) / deviceHeight;
        h3dSetupCameraView(m_camera, 45.0f, aspectRatio, 0.1f, 1000.0f);
        H3DRes cameraPipeRes = h3dGetNodeParamI(m_camera, H3DCamera::PipeResI);
        h3dResizePipelineBuffers(cameraPipeRes, deviceWidth, deviceHeight);
    }
}

void HordeViewport::paintGL()
{
    if (...camera changed...) {
        m_camera = // XXX: get camera.
        m_valid = false;
    }
    // XXX: Update scene.
    // Render scene.
    if (m_camera) {
        // Render.
        h3dRender(m_camera);
        h3dFinalizeFrame();
        // Restore render state.
        glDisable(GL_CULL_FACE);
        glDisable(GL_DEPTH_TEST);
    }
}


Code:
QDeclarativeView *m_view
qmlRegisterType<HordeViewport>("HordeComponents", 1, 0, "HordeViewport");
// Setup view.
m_view->setViewport(new QGLWidget(QGLFormat::defaultFormat()));
m_view->setRenderHint(QPainter::SmoothPixmapTransform);
m_view->setRenderHint(QPainter::Antialiasing);
m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView);


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group