diff options
author | Antti Määttä <antti.maatta@qt.io> | 2019-10-11 12:10:54 +0300 |
---|---|---|
committer | Antti Määttä <antti.maatta@qt.io> | 2019-10-18 11:08:03 +0300 |
commit | da27e66f578e845eab3f73e1cd023a8dbb12ac27 (patch) | |
tree | 43d425bff50aafc83957e60e6b1303fdb6c07bbb | |
parent | b6115ead6793e3943a111ab2729cdabb737a35e9 (diff) |
Add support for antialiasingv5.14.0-beta2
- Allow ideal format functions to select multisample format to support
MSAA in direct render modes
- Add multisample and supersample AA modes for Texture render mode
Task-number: QTBUG-76692
Change-Id: Iddcac437391656c3c933b42c4d23cfc6b1758022
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | examples/quick3d/simple/main.cpp | 2 | ||||
-rw-r--r-- | examples/quick3d/simple/main.qml | 14 | ||||
-rw-r--r-- | src/quick3d/qquick3dscenerenderer.cpp | 81 | ||||
-rw-r--r-- | src/quick3d/qquick3dscenerenderer_p.h | 8 | ||||
-rw-r--r-- | src/quick3d/qquick3dviewport.cpp | 59 | ||||
-rw-r--r-- | src/quick3d/qquick3dviewport_p.h | 2 | ||||
-rw-r--r-- | src/render/qssgrendertexturebase_p.h | 1 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp | 4 | ||||
-rw-r--r-- | tests/manual/runtimerender/testbed/renderwindow.cpp | 2 |
9 files changed, 151 insertions, 22 deletions
diff --git a/examples/quick3d/simple/main.cpp b/examples/quick3d/simple/main.cpp index 8e886b61..5743c575 100644 --- a/examples/quick3d/simple/main.cpp +++ b/examples/quick3d/simple/main.cpp @@ -60,7 +60,7 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); - QSurfaceFormat::setDefaultFormat(QQuick3DViewport::idealSurfaceFormat()); + QSurfaceFormat::setDefaultFormat(QQuick3DViewport::idealSurfaceFormat(4)); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); diff --git a/examples/quick3d/simple/main.qml b/examples/quick3d/simple/main.qml index 59784d15..130d90a8 100644 --- a/examples/quick3d/simple/main.qml +++ b/examples/quick3d/simple/main.qml @@ -59,10 +59,21 @@ Window { height: 720 visible: true + MouseArea { + anchors.fill: parent + property bool msenab: true + onClicked: { + environ.multisampleAAMode = msenab ? SceneEnvironment.NoAA : SceneEnvironment.X4 + msenab = !msenab + console.log("aa enabled: " + msenab) + } + } + View3D { id: layer1 anchors.fill: parent camera: camera + renderMode: View3D.Texture // Light always points the same direction as camera // Light { @@ -76,12 +87,14 @@ Window { // } environment: SceneEnvironment { + id: environ probeBrightness: 1000 clearColor: "green" backgroundMode: SceneEnvironment.Color lightProbe: Texture { source: "maps/OpenfootageNET_garage-1024.hdr" } + multisampleAAMode: SceneEnvironment.X4 } Node { @@ -193,6 +206,7 @@ Window { } Model { + visible: layer1.renderMode == View3D.Texture position: Qt.vector3d(-300, 0, 0) source: "#Cube" materials: [ FrostedGlassMaterial { diff --git a/src/quick3d/qquick3dscenerenderer.cpp b/src/quick3d/qquick3dscenerenderer.cpp index 306dff77..c4955179 100644 --- a/src/quick3d/qquick3dscenerenderer.cpp +++ b/src/quick3d/qquick3dscenerenderer.cpp @@ -41,6 +41,7 @@ #include <QtQuick3DRender/private/qssgrenderframebuffer_p.h> #include <QtQuick3DRuntimeRender/private/qssgrenderlayer_p.h> +#include <QtQuick3DRuntimeRender/private/qssgrendererutil_p.h> #include <QtQuick/QQuickWindow> QT_BEGIN_NAMESPACE @@ -141,6 +142,9 @@ void SGFramebufferObjectNode::handleScreenChange() QQuick3DSceneRenderer::QQuick3DSceneRenderer(QWindow *window) : m_window(window) + , m_multisampleFbo(nullptr) + , m_supersampleFbo(nullptr) + , m_fbo(nullptr) { QOpenGLContext *openGLContext = QOpenGLContext::currentContext(); @@ -167,6 +171,8 @@ QQuick3DSceneRenderer::~QQuick3DSceneRenderer() { delete m_layer; delete m_fbo; + delete m_multisampleFbo; + delete m_supersampleFbo; } GLuint QQuick3DSceneRenderer::render() @@ -174,16 +180,45 @@ GLuint QQuick3DSceneRenderer::render() if (!m_layer) return 0; + const bool ssaaEnabled = this->m_layer->multisampleAAMode == QSSGRenderLayer::AAMode::SSAA; + const bool msaaEnabled = this->m_layer->multisampleAAMode > QSSGRenderLayer::AAMode::SSAA; + m_sgContext->beginFrame(); - m_renderContext->setRenderTarget(m_fbo->fbo); - m_sgContext->renderList()->setViewport(QRect(0, 0, m_surfaceSize.width(), m_surfaceSize.height())); + + // select correct fbo for aa + auto fbo = m_multisampleFbo ? m_multisampleFbo : m_fbo; + fbo = m_supersampleFbo ? m_supersampleFbo : fbo; + fbo = ssaaEnabled || msaaEnabled ? fbo : m_fbo; + + m_renderContext->setRenderTarget(fbo->fbo); + QSize surfaceSize = m_surfaceSize; + if (ssaaEnabled && m_supersampleFbo) + surfaceSize *= SSAA_Multiplier; + m_sgContext->renderList()->setViewport(QRect(0, 0, surfaceSize.width(), surfaceSize.height())); m_sgContext->setWindowDimensions(m_surfaceSize); - m_sgContext->renderer()->prepareLayerForRender(*m_layer, m_surfaceSize, false, nullptr, true); + m_sgContext->renderer()->prepareLayerForRender(*m_layer, surfaceSize, false, nullptr, true); m_sgContext->runRenderTasks(); - m_sgContext->renderer()->renderLayer(*m_layer, m_surfaceSize, true, QVector3D(0, 0, 0), false); + m_sgContext->renderer()->renderLayer(*m_layer, surfaceSize, true, QVector3D(0, 0, 0), false); m_sgContext->endFrame(); + if ((msaaEnabled && m_multisampleFbo) || (ssaaEnabled && m_supersampleFbo)) { + m_renderContext->setRenderTarget(m_fbo->fbo); + m_renderContext->setReadTarget(m_supersampleFbo ? m_supersampleFbo->fbo + : m_multisampleFbo->fbo); + if (m_supersampleFbo) { + m_renderContext->blitFramebuffer(0, 0, surfaceSize.width(), surfaceSize.height(), + 0, 0, m_surfaceSize.width(), m_surfaceSize.height(), + QSSGRenderClearValues::Color, + QSSGRenderTextureMagnifyingOp::Linear); + } else { + m_renderContext->blitFramebuffer(0, 0, m_surfaceSize.width(), m_surfaceSize.height(), + 0, 0, m_surfaceSize.width(), m_surfaceSize.height(), + QSSGRenderClearValues::Color, + QSSGRenderTextureMagnifyingOp::Nearest); + } + } + if (dumpPerfTiming) { if (++frameCount == 60) { m_sgContext->performanceTimer()->dump(); @@ -285,6 +320,27 @@ void QQuick3DSceneRenderer::synchronize(QQuick3DViewport *item, const QSize &siz if (m_fbo) delete m_fbo; + auto msaaModeSamples = [](QSSGRenderLayer::AAMode mode) -> int { + switch (mode) { + case QSSGRenderLayer::AAMode::X2: + return 2; + case QSSGRenderLayer::AAMode::X4: + case QSSGRenderLayer::AAMode::X8: + return 4; + case QSSGRenderLayer::AAMode::NoAA: + default: + break; + } + return 1; + }; + if (msaaModeSamples(m_layer->multisampleAAMode) > 1) { + m_multisampleFbo + = new FramebufferObject(m_surfaceSize, m_renderContext, + msaaModeSamples(m_layer->multisampleAAMode)); + } else if (m_layer->multisampleAAMode == QSSGRenderLayer::AAMode::SSAA) { + m_supersampleFbo = new FramebufferObject(m_surfaceSize * SSAA_Multiplier, + m_renderContext); + } m_fbo = new FramebufferObject(m_surfaceSize, m_renderContext); m_layerSizeIsDirty = false; } @@ -403,18 +459,25 @@ void QQuick3DSceneRenderer::addNodeToLayer(QSSGRenderNode *node) m_layer->addChild(*node); } -QQuick3DSceneRenderer::FramebufferObject::FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context) +QQuick3DSceneRenderer::FramebufferObject::FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context, int msaaSamples) { size = s; renderContext = context; + samples = msaaSamples; depthStencil = new QSSGRenderTexture2D(renderContext); - depthStencil->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::Depth24Stencil8); + if (samples > 1) + depthStencil->setTextureDataMultisample(samples, size.width(), size.height(), QSSGRenderTextureFormat::Depth24Stencil8); + else + depthStencil->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::Depth24Stencil8); color0 = new QSSGRenderTexture2D(renderContext); - color0->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::RGBA8); + if (samples > 1) + color0->setTextureDataMultisample(samples, size.width(), size.height(), QSSGRenderTextureFormat::RGBA8); + else + color0->setTextureData(QSSGByteView(), 0, size.width(), size.height(), QSSGRenderTextureFormat::RGBA8); fbo = new QSSGRenderFrameBuffer(renderContext); - fbo->attach(QSSGRenderFrameBufferAttachment::Color0, color0); - fbo->attach(QSSGRenderFrameBufferAttachment::DepthStencil, depthStencil); + fbo->attach(QSSGRenderFrameBufferAttachment::Color0, color0, color0->target()); + fbo->attach(QSSGRenderFrameBufferAttachment::DepthStencil, depthStencil, depthStencil->target()); } QQuick3DSceneRenderer::FramebufferObject::~FramebufferObject() diff --git a/src/quick3d/qquick3dscenerenderer_p.h b/src/quick3d/qquick3dscenerenderer_p.h index 891c47a5..31e75584 100644 --- a/src/quick3d/qquick3dscenerenderer_p.h +++ b/src/quick3d/qquick3dscenerenderer_p.h @@ -61,13 +61,15 @@ class QQuick3DSceneRenderer { public: struct FramebufferObject { - FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context); + FramebufferObject(const QSize &s, const QSSGRef<QSSGRenderContext> &context, + int msaaSamples = 1); ~FramebufferObject(); QSize size; QSSGRef<QSSGRenderContext> renderContext; QSSGRef<QSSGRenderFrameBuffer> fbo; QSSGRef<QSSGRenderTexture2D> color0; QSSGRef<QSSGRenderTexture2D> depthStencil; + int samples; }; QQuick3DSceneRenderer(QWindow *window); @@ -94,11 +96,15 @@ private: void *data = nullptr; bool m_layerSizeIsDirty = true; QWindow *m_window = nullptr; + FramebufferObject *m_multisampleFbo = nullptr; + FramebufferObject *m_supersampleFbo = nullptr; FramebufferObject *m_fbo = nullptr; QSSGRenderNode *m_sceneRootNode = nullptr; QSSGRenderNode *m_referencedRootNode = nullptr; + const int SSAA_Multiplier = 2; + friend class SGFramebufferObjectNode; friend class QQuick3DSGRenderNode; friend class QQuick3DSGDirectRenderer; diff --git a/src/quick3d/qquick3dviewport.cpp b/src/quick3d/qquick3dviewport.cpp index 5bcbe98b..1b3e43ee 100644 --- a/src/quick3d/qquick3dviewport.cpp +++ b/src/quick3d/qquick3dviewport.cpp @@ -436,26 +436,46 @@ void QQuick3DViewport::setEnableWireframeMode(bool enableWireframeMode) update(); } -static QSurfaceFormat findIdealGLVersion() +static QSurfaceFormat findIdealGLVersion(int samples) { QSurfaceFormat fmt; + int defaultSamples = fmt.samples(); + const bool multisampling = samples > 1; fmt.setProfile(QSurfaceFormat::CoreProfile); // Advanced: Try 4.3 core (so we get compute shaders for instance) fmt.setVersion(4, 3); + fmt.setSamples(multisampling ? samples : defaultSamples); QOpenGLContext ctx; ctx.setFormat(fmt); if (ctx.create() && ctx.format().version() >= qMakePair(4, 3)) { qDebug("Requesting OpenGL 4.3 core context succeeded"); return ctx.format(); + } else if (multisampling) { + // try without multisampling + fmt.setSamples(defaultSamples); + ctx.setFormat(fmt); + if (ctx.create() && ctx.format().version() >= qMakePair(4, 3)) { + qDebug("Requesting OpenGL 4.3 core context succeeded without multisampling"); + return ctx.format(); + } } // Basic: Stick with 3.3 for now to keep less fortunate, Mesa-based systems happy fmt.setVersion(3, 3); + fmt.setSamples(multisampling ? samples : defaultSamples); ctx.setFormat(fmt); if (ctx.create() && ctx.format().version() >= qMakePair(3, 3)) { qDebug("Requesting OpenGL 3.3 core context succeeded"); return ctx.format(); + } else if (multisampling) { + // try without multisampling + fmt.setSamples(defaultSamples); + ctx.setFormat(fmt); + if (ctx.create() && ctx.format().version() >= qMakePair(3, 3)) { + qDebug("Requesting OpenGL 3.3 core context succeeded without multisampling"); + return ctx.format(); + } } qDebug("Impending doom"); @@ -485,13 +505,16 @@ static bool isBlackListedES3Driver(QOpenGLContext &ctx) } -static QSurfaceFormat findIdealGLESVersion() +static QSurfaceFormat findIdealGLESVersion(int samples) { QSurfaceFormat fmt; + int defaultSamples = fmt.samples(); + const bool multisampling = samples > 1; // Advanced: Try 3.1 (so we get compute shaders for instance) fmt.setVersion(3, 1); fmt.setRenderableType(QSurfaceFormat::OpenGLES); + fmt.setSamples(multisampling ? samples : defaultSamples); QOpenGLContext ctx; ctx.setFormat(fmt); @@ -504,38 +527,62 @@ static QSurfaceFormat findIdealGLESVersion() if (ctx.create() && ctx.format().version() >= qMakePair(3, 1)) { qDebug("Requesting OpenGL ES 3.1 context succeeded"); return ctx.format(); + } else if (multisampling) { + fmt.setSamples(defaultSamples); + ctx.setFormat(fmt); + if (ctx.create() && ctx.format().version() >= qMakePair(3, 1)) { + qDebug("Requesting OpenGL ES 3.1 context succeeded without multisampling"); + return ctx.format(); + } } // Basic: OpenGL ES 3.0 is a hard requirement at the moment since we can // only generate 300 es shaders, uniform buffers are mandatory. fmt.setVersion(3, 0); + fmt.setSamples(multisampling ? samples : defaultSamples); ctx.setFormat(fmt); qDebug("Testing OpenGL ES 3.0"); if (ctx.create() && ctx.format().version() >= qMakePair(3, 0) && !isBlackListedES3Driver(ctx)) { qDebug("Requesting OpenGL ES 3.0 context succeeded"); return ctx.format(); + } else if (multisampling) { + fmt.setSamples(defaultSamples); + ctx.setFormat(fmt); + if (ctx.create() && ctx.format().version() >= qMakePair(3, 0) + && !isBlackListedES3Driver(ctx)) { + qDebug("Requesting OpenGL ES 3.0 context succeeded without multisampling"); + return ctx.format(); + } } fmt.setVersion(2, 0); + fmt.setSamples(multisampling ? samples : defaultSamples); ctx.setFormat(fmt); qDebug("Testing OpenGL ES 2.0"); if (ctx.create()) { qDebug("Requesting OpenGL ES 2.0 context succeeded"); return fmt; + } else if (multisampling) { + fmt.setSamples(defaultSamples); + ctx.setFormat(fmt); + if (ctx.create()) { + qDebug("Requesting OpenGL ES 2.0 context succeeded without multisampling"); + return fmt; + } } qDebug("Impending doom"); return fmt; } -QSurfaceFormat QQuick3DViewport::idealSurfaceFormat() +QSurfaceFormat QQuick3DViewport::idealSurfaceFormat(int samples) { - static const QSurfaceFormat f = [] { + static const QSurfaceFormat f = [samples] { QSurfaceFormat fmt; if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { // works in dynamic gl builds too because there's a qguiapp already - fmt = findIdealGLVersion(); + fmt = findIdealGLVersion(samples); } else { - fmt = findIdealGLESVersion(); + fmt = findIdealGLESVersion(samples); } fmt.setDepthBufferSize(24); fmt.setStencilBufferSize(8); diff --git a/src/quick3d/qquick3dviewport_p.h b/src/quick3d/qquick3dviewport_p.h index e25678e3..38b327fe 100644 --- a/src/quick3d/qquick3dviewport_p.h +++ b/src/quick3d/qquick3dviewport_p.h @@ -97,7 +97,7 @@ public: QSGTextureProvider *textureProvider() const override; void releaseResources() override; - static QSurfaceFormat idealSurfaceFormat(); + static QSurfaceFormat idealSurfaceFormat(int samples = -1); Q_INVOKABLE QVector3D mapFrom3DScene(const QVector3D &scenePos) const; Q_INVOKABLE QVector3D mapTo3DScene(const QVector3D &viewPos) const; diff --git a/src/render/qssgrendertexturebase_p.h b/src/render/qssgrendertexturebase_p.h index 68d17ecc..112eec38 100644 --- a/src/render/qssgrendertexturebase_p.h +++ b/src/render/qssgrendertexturebase_p.h @@ -123,6 +123,7 @@ public: bool isMultisampleTexture() const { return (m_texTarget == QSSGRenderTextureTargetType::Texture2D_MS); } qint32 sampleCount() const { return m_sampleCount; } bool isImmutable() const { return m_immutable; } + QSSGRenderTextureTargetType target() const { return m_texTarget; } /** * @brief Bind a texture for shader access diff --git a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp index 5ea2e146..74706d37 100644 --- a/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp +++ b/src/runtimerender/rendererimpl/qssgrendererimpllayerrenderdata.cpp @@ -1753,9 +1753,7 @@ void QSSGLayerRenderData::runnableRenderToViewport(const QSSGRef<QSSGRenderFrame theContext->setRenderTarget(theFB); // Multisampling - if (sampleCount > 1) { - theContext->setMultisampleEnabled(true); - } + theContext->setMultisampleEnabled(sampleCount > 1 ? true : false); // Start Operations on Viewport theContext->setViewport(layerPrepResult->viewport().toRect()); diff --git a/tests/manual/runtimerender/testbed/renderwindow.cpp b/tests/manual/runtimerender/testbed/renderwindow.cpp index 6d0b9476..bd4400ed 100644 --- a/tests/manual/runtimerender/testbed/renderwindow.cpp +++ b/tests/manual/runtimerender/testbed/renderwindow.cpp @@ -265,6 +265,6 @@ void RenderWindow::buildTestScene() m_layer->addChild(*m_cube); // Default Material - auto material = new QSSGRenderDefaultMaterial(); + auto material = new QSSGRenderDefaultMaterial(QSSGRenderGraphObject::Type::DefaultMaterial); m_cube->materials.append(material); } |