- Qt 5.5
- Qt Quick
- Scene Graph - OpenGL Under QML
- squircle.cpp Example File
- Qt 5.5.1 Reference Documentation

# squircle.cpp Example File

scenegraph/openglunderqml/squircle.cpp

    /****************************************************************************
    **
    ** Copyright (C) 2015 The Qt Company Ltd.
    ** Contact: http://www.qt.io/licensing/
    **
    ** This file is part of the demonstration applications of the Qt Toolkit.
    **
    ** $QT_BEGIN_LICENSE:LGPL21$
    ** Commercial License Usage
    ** Licensees holding valid commercial Qt licenses may use this file in
    ** accordance with the commercial license agreement provided with the
    ** Software or, alternatively, in accordance with the terms contained in
    ** a written agreement between you and The Qt Company. For licensing terms
    ** and conditions see http://www.qt.io/terms-conditions. For further
    ** information use the contact form at http://www.qt.io/contact-us.
    **
    ** GNU Lesser General Public License Usage
    ** Alternatively, this file may be used under the terms of the GNU Lesser
    ** General Public License version 2.1 or version 3 as published by the Free
    ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
    ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
    ** following information to ensure the GNU Lesser General Public License
    ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
    ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    **
    ** As a special exception, The Qt Company gives you certain additional
    ** rights. These rights are described in The Qt Company LGPL Exception
    ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
    **
    ** $QT_END_LICENSE$
    **
    ****************************************************************************/

    #include "squircle.h"

    #include <QtQuick/qquickwindow.h>
    #include <QtGui/QOpenGLShaderProgram>
    #include <QtGui/QOpenGLContext>

    Squircle::Squircle()
        : m_t(0)
        , m_renderer(0)
    {
        connect(this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
    }

    void Squircle::setT(qreal t)
    {
        if (t == m_t)
            return;
        m_t = t;
        emit tChanged();
        if (window())
            window()->update();
    }

    void Squircle::handleWindowChanged(QQuickWindow *win)
    {
        if (win) {
            connect(win, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
            connect(win, SIGNAL(sceneGraphInvalidated()), this, SLOT(cleanup()), Qt::DirectConnection);
            // If we allow QML to do the clearing, they would clear what we paint
            // and nothing would show.
            win->setClearBeforeRendering(false);
        }
    }

    void Squircle::cleanup()
    {
        if (m_renderer) {
            delete m_renderer;
            m_renderer = 0;
        }
    }

    SquircleRenderer::~SquircleRenderer()
    {
        delete m_program;
    }

    void Squircle::sync()
    {
        if (!m_renderer) {
            m_renderer = new SquircleRenderer();
            connect(window(), SIGNAL(beforeRendering()), m_renderer, SLOT(paint()), Qt::DirectConnection);
        }
        m_renderer->setViewportSize(window()->size() * window()->devicePixelRatio());
        m_renderer->setT(m_t);
    }

    void SquircleRenderer::paint()
    {
        if (!m_program) {
            initializeOpenGLFunctions();

            m_program = new QOpenGLShaderProgram();
            m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,
                                               "attribute highp vec4 vertices;"
                                               "varying highp vec2 coords;"
                                               "void main() {"
                                               "    gl_Position = vertices;"
                                               "    coords = vertices.xy;"
                                               "}");
            m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,
                                               "uniform lowp float t;"
                                               "varying highp vec2 coords;"
                                               "void main() {"
                                               "    lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));"
                                               "    i = smoothstep(t - 0.8, t + 0.8, i);"
                                               "    i = floor(i * 20.) / 20.;"
                                               "    gl_FragColor = vec4(coords * .5 + .5, i, i);"
                                               "}");

            m_program->bindAttributeLocation("vertices", 0);
            m_program->link();

        }
        m_program->bind();

        m_program->enableAttributeArray(0);

        float values[] = {
            -1, -1,
            1, -1,
            -1, 1,
            1, 1
        };
        m_program->setAttributeArray(0, GL_FLOAT, values, 2);
        m_program->setUniformValue("t", (float) m_t);

        glViewport(0, 0, m_viewportSize.width(), m_viewportSize.height());

        glDisable(GL_DEPTH_TEST);

        glClearColor(0, 0, 0, 1);
        glClear(GL_COLOR_BUFFER_BIT);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        m_program->disableAttributeArray(0);
        m_program->release();
    }