diff --git a/example/qml/page/T_OpenGL.qml b/example/qml/page/T_OpenGL.qml new file mode 100644 index 00000000..8582fb3e --- /dev/null +++ b/example/qml/page/T_OpenGL.qml @@ -0,0 +1,32 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Window 2.15 +import QtQuick.Controls 2.15 +import FluentUI 1.0 +import example 1.0 +import "../component" + +FluContentPage{ + + title: qsTr("OpenGL") + + + FluFrame{ + anchors.fill: parent + + OpenGLItem{ + width: 320 + height: 480 + SequentialAnimation on t { + NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad } + NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad } + loops: Animation.Infinite + running: true + } + } + + } + + + +} diff --git a/example/src/component/OpenGLItem.cpp b/example/src/component/OpenGLItem.cpp new file mode 100644 index 00000000..60c6bdee --- /dev/null +++ b/example/src/component/OpenGLItem.cpp @@ -0,0 +1,93 @@ +#include "OpenGLItem.h" + +#include +#include + +class FBORenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions { +public: + explicit FBORenderer(const OpenGLItem *item); + + void render() override; + + QOpenGLFramebufferObject *createFramebufferObject(const QSize &size) override; + + QOpenGLShaderProgram program; + const OpenGLItem *item = nullptr; +}; + +FBORenderer::FBORenderer(const OpenGLItem *item) { + this->item = item; + initializeOpenGLFunctions(); + program.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, + "attribute highp vec4 vertices;" + "varying highp vec2 coords;" + "void main() {" + " gl_Position = vertices;" + " coords = vertices.xy;" + "}"); + program.addCacheableShaderFromSourceCode(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);" + "}"); + + program.bindAttributeLocation("vertices", 0); + program.link(); +} + +QOpenGLFramebufferObject *FBORenderer::createFramebufferObject(const QSize &size) { + QOpenGLFramebufferObjectFormat format; + format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); + format.setSamples(4); + return new QOpenGLFramebufferObject(size, format); +} + +void FBORenderer::render() { + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_DEPTH_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + program.bind(); + program.enableAttributeArray(0); + float values[] = { + -1, -1, + 1, -1, + -1, 1, + 1, 1 + }; + glBindBuffer(GL_ARRAY_BUFFER, 0); + program.setAttributeArray(0, GL_FLOAT, values, 2); + program.setUniformValue("t", (float) item->t()); + glViewport(0, 0, qRound(item->width()), qRound(item->height())); + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + program.disableAttributeArray(0); + program.release(); +} + + +OpenGLItem::OpenGLItem(QQuickItem *parent) : QQuickFramebufferObject(parent) { + setMirrorVertically(true); + startTimer(1); +} + +void OpenGLItem::timerEvent(QTimerEvent *) { + update(); +} + +void OpenGLItem::setT(qreal t) { + if (t == m_t) + return; + m_t = t; + emit tChanged(); +} + + +QQuickFramebufferObject::Renderer *OpenGLItem::createRenderer() const { + return new FBORenderer(this); +} diff --git a/example/src/component/OpenGLItem.h b/example/src/component/OpenGLItem.h new file mode 100644 index 00000000..0aac13f4 --- /dev/null +++ b/example/src/component/OpenGLItem.h @@ -0,0 +1,33 @@ +#pragma once +#pragma clang diagnostic push +#pragma ide diagnostic ignored "NotImplementedFunctions" + +#include +#include +#include + +class FBORenderer; + +class OpenGLItem : public QQuickFramebufferObject, protected QOpenGLFunctions { +Q_OBJECT + Q_PROPERTY(qreal t READ t WRITE setT NOTIFY tChanged) +public: + explicit OpenGLItem(QQuickItem *parent = nullptr); + + [[nodiscard]] QQuickFramebufferObject::Renderer *createRenderer() const override; + + void timerEvent(QTimerEvent *) override; + + [[nodiscard]] qreal t() const { return m_t; } + + void setT(qreal t); + +signals: + + void tChanged(); + +private: + qreal m_t{}; +}; + +#pragma clang diagnostic pop \ No newline at end of file