diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2013-04-15 11:52:24 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-04-16 15:41:31 +0200 |
commit | 5c7225572746201cc60496530f410178cdb4283b (patch) | |
tree | 23acb1618e7bef65b502be39b323e9318ef66dba /src/quick/scenegraph/util/qsgsimpletexturenode.cpp | |
parent | a6ccf8b484596091b9a38ac37dac43c456cdc730 (diff) |
Add a way of transforming texture coordinates of a simple textured quad
This commit introduces the enum TextureCoordinatesTransformFlag and
corresponding QFlags OR combination TextureCoordinatesTransformMode.
This enum is used to control the orientation of texture coordinates
relative to window/item coordinates.
The common use case addressed by this commit is when rendering to a
texture via an FBO using some 3rd party OpenGL library. Some libraries
do not offer a way to orient the rendered output which results in the
texture being displayed upside down when used in conjunction with
QSGSimpleTextureNode.
There are a number of possible solutions to this:
1 Mirror the item by scaling by -1 in the y-direction in QML document
2 Use a custom material (shader) that transforms texture coordinates
in GLSL
3 Generate texture coordinates differently
This commit opts for approach 3. Approach 1 is ugly and visible to the
end user and also causes more work when other transformations interact
with the necessary scaling. Approach 2 has a performance cost in both
switching material (shader) and also in additional per-vertex or per-
fragment operations. The chosen approach hides it from the end user
and has zero runtime cost delta compared to any other textured quad.
Change-Id: I95870da50a09d113aeff2681bfd458669ec7a5a4
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src/quick/scenegraph/util/qsgsimpletexturenode.cpp')
-rw-r--r-- | src/quick/scenegraph/util/qsgsimpletexturenode.cpp | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 318120e4bf..86e0d36f6c 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -41,18 +41,44 @@ #include "qsgsimpletexturenode.h" +#include <private/qsgnode_p.h> QT_BEGIN_NAMESPACE +class QSGSimpleTextureNodePrivate : public QSGGeometryNodePrivate +{ +public: + QSGSimpleTextureNodePrivate() + : QSGGeometryNodePrivate() + , m_texCoordMode(QSGSimpleTextureNode::NoTransform) + {} + + QSGSimpleTextureNode::TextureCoordinatesTransformMode m_texCoordMode; +}; + static void qsgsimpletexturenode_update(QSGGeometry *g, QSGTexture *texture, - const QRectF &rect) + const QRectF &rect, + QSGSimpleTextureNode::TextureCoordinatesTransformMode texCoordMode) { if (!texture) return; QSize ts = texture->textureSize(); QRectF sourceRect(0, 0, ts.width(), ts.height()); + + // Maybe transform the texture coordinates + if (texCoordMode.testFlag(QSGSimpleTextureNode::MirrorHorizontally)) { + float tmp = sourceRect.left(); + sourceRect.setLeft(sourceRect.right()); + sourceRect.setRight(tmp); + } + if (texCoordMode.testFlag(QSGSimpleTextureNode::MirrorVertically)) { + float tmp = sourceRect.top(); + sourceRect.setTop(sourceRect.bottom()); + sourceRect.setBottom(tmp); + } + QSGGeometry::updateTexturedRectGeometry(g, rect, texture->convertToNormalizedSourceRect(sourceRect)); } @@ -71,7 +97,8 @@ static void qsgsimpletexturenode_update(QSGGeometry *g, Constructs a new simple texture node */ QSGSimpleTextureNode::QSGSimpleTextureNode() - : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) + : QSGGeometryNode(*new QSGSimpleTextureNodePrivate) + , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4) { setGeometry(&m_geometry); setMaterial(&m_material); @@ -112,7 +139,8 @@ void QSGSimpleTextureNode::setRect(const QRectF &r) if (m_rect == r) return; m_rect = r; - qsgsimpletexturenode_update(&m_geometry, texture(), m_rect); + Q_D(QSGSimpleTextureNode); + qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->m_texCoordMode); markDirty(DirtyGeometry); } @@ -144,7 +172,8 @@ void QSGSimpleTextureNode::setTexture(QSGTexture *texture) return; m_material.setTexture(texture); m_opaque_material.setTexture(texture); - qsgsimpletexturenode_update(&m_geometry, texture, m_rect); + Q_D(QSGSimpleTextureNode); + qsgsimpletexturenode_update(&m_geometry, texture, m_rect, d->m_texCoordMode); markDirty(DirtyMaterial); } @@ -158,4 +187,48 @@ QSGTexture *QSGSimpleTextureNode::texture() const return m_material.texture(); } +/*! + \enum QSGSimpleTextureNode::TextureCoordinatesTransformFlag + + The TextureCoordinatesTransformFlag enum is used to specify the + mode used to generate texture coordinates for a textured quad. + + \value NoTransform Texture coordinates are oriented with window coordinates + i.e. with origin at top-left. + + \value MirrorHorizontally Texture coordinates are inverted in the horizontal axis with + respect to window coordinates + + \value MirrorVertically Texture coordinates are inverted in the vertical axis with + respect to window coordinates + */ + +/*! + Sets the method used to generate texture coordinates to \a mode. This can be used to obtain + correct orientation of the texture. This is commonly needed when using a third party OpenGL + library to render to texture as OpenGL has an inverted y-axis relative to Qt Quick. + + \sa textureCoordinatesTransform() + */ +void QSGSimpleTextureNode::setTextureCoordinatesTransform(QSGSimpleTextureNode::TextureCoordinatesTransformMode mode) +{ + Q_D(QSGSimpleTextureNode); + if (d->m_texCoordMode == mode) + return; + d->m_texCoordMode = mode; + qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->m_texCoordMode); + markDirty(DirtyMaterial); +} + +/*! + Returns the mode used to generate texture coordinates for this node. + + \sa setTextureCoordinatesTransform() + */ +QSGSimpleTextureNode::TextureCoordinatesTransformMode QSGSimpleTextureNode::textureCoordinatesTransform() const +{ + Q_D(const QSGSimpleTextureNode); + return d->m_texCoordMode; +} + QT_END_NAMESPACE |