From 45e88bbb6940e07d7cfb6658db0429dd3732185f Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 20 Apr 2011 12:37:21 +0200 Subject: Properly save and restore Ogre GL state. --- ogreitem.cpp | 1 + ogrenode.cpp | 86 ++++++++++++++++++++++++++++++++++++---------- ogrenode.h | 15 ++++++-- resources/GrassandSky.jpg | Bin 0 -> 345001 bytes resources/example.qml | 70 ++++++++++++++++++++++++++++++++----- 5 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 resources/GrassandSky.jpg diff --git a/ogreitem.cpp b/ogreitem.cpp index a527366..30f47d4 100644 --- a/ogreitem.cpp +++ b/ogreitem.cpp @@ -44,6 +44,7 @@ QSGNode *OgreItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) node = new OgreNode(); node->setSize(QSize(width(), height())); + node->setAAEnabled(smooth()); node->update(); m_camera = static_cast(node->camera()); diff --git a/ogrenode.cpp b/ogrenode.cpp index be6df62..467bd53 100644 --- a/ogrenode.cpp +++ b/ogrenode.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include "ogrenode.h" #include "cameranodeobject.h" @@ -27,8 +29,12 @@ OgreNode::OgreNode() : QSGGeometryNode() , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) , m_texture(0) + , m_samples(0) + , m_AAEnabled(false) + , m_renderTexture(0) + , m_ogreFBO(0) , m_initialized(false) - , m_dirtySize(false) + , m_dirtyFBO(false) { setMaterial(&m_materialO); setOpaqueMaterial(&m_material); @@ -955,38 +961,66 @@ static void printGLState() qDebug() << "============"; } -void OgreNode::preprocess() +void OgreNode::saveOgreState() { - glPopAttrib(); - const QGLContext *ctx = QGLContext::currentContext(); - ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 2); - ctx->functions()->glUseProgram(0); + m_ogreFBO = getOgreFBO(); - m_renderTexture->update(false); + const QGLContext *ctx = QGLContext::currentContext(); glPushAttrib(GL_ALL_ATTRIB_BITS); - ctx->functions()->glBindBuffer(GL_ARRAY_BUFFER, 0); ctx->functions()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); ctx->functions()->glBindRenderbuffer(GL_RENDERBUFFER, 0); ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); } +void OgreNode::restoreOgreState() +{ + const QGLContext *ctx = QGLContext::currentContext(); + glPopAttrib(); + ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_ogreFBO); + ctx->functions()->glUseProgram(0); +} + +GLuint OgreNode::getOgreFBO() +{ + if (!m_renderTexture) + return 0; + + Ogre::GLFrameBufferObject *ogreFbo = 0; + m_renderTexture->getCustomAttribute("FBO", &ogreFbo); + Ogre::GLFBOManager *manager = ogreFbo->getManager(); + manager->bind(m_renderTexture); + + GLint id; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &id); + + const QGLContext *ctx = QGLContext::currentContext(); + ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + + return id; +} + +void OgreNode::preprocess() +{ + restoreOgreState(); + m_renderTexture->update(true); + saveOgreState(); +} + void OgreNode::update() { + restoreOgreState(); + if (!m_initialized) init(); - if (m_dirtySize) - updateSize(); + if (m_dirtyFBO) + updateFBO(); - const QGLContext *ctx = QGLContext::currentContext(); - ctx->functions()->glBindBuffer(GL_ARRAY_BUFFER, 0); - ctx->functions()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - ctx->functions()->glBindRenderbuffer(GL_RENDERBUFFER, 0); - ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + saveOgreState(); } -void OgreNode::updateSize() +void OgreNode::updateFBO() { if (m_renderTexture) Ogre::TextureManager::getSingleton().remove("RttTex"); @@ -998,7 +1032,8 @@ void OgreNode::updateSize() m_size.height(), 0, Ogre::PF_R8G8B8A8, - Ogre::TU_RENDERTARGET); + Ogre::TU_RENDERTARGET, 0, false, + m_AAEnabled ? m_samples : 0); m_renderTexture = rtt_texture->getBuffer()->getRenderTarget(); @@ -1014,7 +1049,6 @@ void OgreNode::updateSize() QRectF(0, 0, m_size.width(), m_size.height()), QRectF(0, 0, 1, 1)); - Ogre::GLTexture *nativeTexture = static_cast(rtt_texture.get()); delete m_texture; @@ -1033,12 +1067,26 @@ void OgreNode::setSize(const QSize &size) return; m_size = size; - m_dirtySize = true; + m_dirtyFBO = true; markDirty(DirtyGeometry); } +void OgreNode::setAAEnabled(bool enable) +{ + if (m_AAEnabled == enable) + return; + + m_AAEnabled = enable; + m_dirtyFBO = true; + markDirty(DirtyMaterial); +} + void OgreNode::init() { + const QGLContext *ctx = QGLContext::currentContext(); + QGLFormat format = ctx->format(); + m_samples = format.sampleBuffers() ? format.samples() : 0; + m_root = new Ogre::Root; m_root->loadPlugin(Ogre::String(OGRE_PLUGIN_DIR) + "/RenderSystem_GL"); diff --git a/ogrenode.h b/ogrenode.h index 5da7c66..83cb63a 100644 --- a/ogrenode.h +++ b/ogrenode.h @@ -31,13 +31,20 @@ public: void setSize(const QSize &size); QSize size() const { return m_size; } + void setAAEnabled(bool enable); + CameraNodeObject *camera() const { return m_cameraObject; } void update(); - void updateSize(); + void updateFBO(); void init(); + GLuint getOgreFBO(); + + void saveOgreState(); + void restoreOgreState(); + void preprocess(); private: @@ -46,6 +53,8 @@ private: QSGGeometry m_geometry; QSGPlainTexture *m_texture; + int m_samples; + bool m_AAEnabled; QSize m_size; Ogre::Root *m_root; @@ -56,10 +65,12 @@ private: Ogre::TexturePtr rtt_texture; Ogre::RenderWindow *m_window; + GLuint m_ogreFBO; + CameraNodeObject *m_cameraObject; bool m_initialized; - bool m_dirtySize; + bool m_dirtyFBO; }; #endif // OGRENODE_H diff --git a/resources/GrassandSky.jpg b/resources/GrassandSky.jpg new file mode 100644 index 0000000..95f7991 Binary files /dev/null and b/resources/GrassandSky.jpg differ diff --git a/resources/example.qml b/resources/example.qml index c7be670..87603ee 100644 --- a/resources/example.qml +++ b/resources/example.qml @@ -5,15 +5,14 @@ Rectangle { id: ogre width: 1024 height: 768 - gradient: Gradient { - GradientStop { position: 0.0; color: "#000000" } - GradientStop { position: 0.40; color: "#232323" } - GradientStop { position: 0.55; color: "#232323" } - GradientStop { position: 0.85; color: "#000000" } - GradientStop { position: 1.0; color: "#000000" } - } - + color: "black" + Image { + id: back + anchors.fill: parent + source: "GrassandSky.jpg" + Behavior on opacity { NumberAnimation { } } + } OgreItem { id: ogreitem @@ -42,11 +41,20 @@ Rectangle { y: -toolbar1.height - 6 } + PropertyChanges { + target: toolbar4 + anchors.top: ogreitem.top + anchors.topMargin: 5 + } PropertyChanges { target: toolbar3 anchors.top: ogreitem.top anchors.topMargin: 5 } + PropertyChanges { + target: back + opacity: 0 + } } ] } @@ -151,6 +159,52 @@ Rectangle { border.width: 2 } + Rectangle { + id: toolbar4 + width: 25 + height: 25 + radius: 5 + gradient: Gradient { + GradientStop { + position: 0 + color: "#c83e3e3e" + } + + GradientStop { + position: 1 + color: "#c8919191" + } + } + anchors.top: toolbar1.top + anchors.right: toolbar3.left + anchors.rightMargin: 6 + border.color: "#1a1a1a" + + MouseArea { + anchors.fill: parent + onClicked: { ogreitem.smooth = !ogreitem.smooth } + } + + Text { + anchors.fill: parent + text: "AA" + font.bold: true + font.pixelSize: parent.height * 0.55 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + Rectangle { + height: parent.height + width: 2 + anchors.centerIn: parent + color: "#BB1111" + rotation: 40 + visible: !ogreitem.smooth + } + } + border.width: 2 + } + Rectangle { id: toolbar3 width: 25 -- cgit v1.2.3