Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. About QSGGeometryNode and WebAssembly in QT

About QSGGeometryNode and WebAssembly in QT

Scheduled Pinned Locked Moved Solved QML and Qt Quick
2 Posts 1 Posters 285 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Junyu Ke
    wrote on last edited by
    #1

    I'm trying to deploy my project on the Web with WebAssembly and encountered some problems.

    The project made a custom rendering with QSGRenderNode and ran on the web.

    And I'm getting error "INVALID OPERATION insufficient buffer size".

    Here's my code bellow.

    openglerenderer.h

    #ifndef OPENGLRENDERER_H
    #define OPENGLRENDERER_H
    
    #include <qsgrendernode.h>
    #include <QQuickItem>
    #include "webaccess/render/baserender.h"
    
    #if QT_CONFIG(opengl)
    
    
    class OpenGLRenderNode : public QSGRenderNode
    {
    public:
        ~OpenGLRenderNode();
    
        void render(const RenderState *state) override;
        void releaseResources() override;
        StateFlags changedStates() const override;
        RenderingFlags flags() const override;
        QRectF rect() const override;
    
        void sync(QQuickItem *item);
    
    private:
        void init();
        int m_width = 0;
        int m_height = 0;
        bool beInit = false;
        BaseRender* m_render = nullptr;
    };
    
    #endif
    
    #endif // OPENGLRENDERER_H
    

    openglerenderer.cpp

    #include "openglrenderer.h"
    #include <QQuickItem>
    
    #if QT_CONFIG(opengl)
    
    #include <QOpenGLFunctions>
    #include <QOpenGLExtraFunctions>
    #include <QQuickWindow>
    
    #include "webaccess/render/tutorial/les1.h"
    #include "webaccess/render/tutorial/les2.h"
    #include "webaccess/render/tutorial/les3.h"
    #include "webaccess/render/tutorial/les4.h"
    
    OpenGLRenderNode::~OpenGLRenderNode()
    {
        releaseResources();
    }
    
    void OpenGLRenderNode::releaseResources()
    {
        if (m_render) {
            m_render->releaseResources();
        }
    }
    
    void OpenGLRenderNode::init()
    {
        if (m_render) {
            m_render->init();
            beInit = true;
        }
    }
    
    void OpenGLRenderNode::render(const RenderState *state)
    {
        if (!beInit)
            init();
        if (m_render) {
            m_render->render(state);
        }
    }
    
    QSGRenderNode::StateFlags OpenGLRenderNode::changedStates() const
    {
        return BlendState | ScissorState | StencilState;
    }
    
    QSGRenderNode::RenderingFlags OpenGLRenderNode::flags() const
    {
        return BoundedRectRendering | DepthAwareRendering;
    }
    
    QRectF OpenGLRenderNode::rect() const
    {
        return QRect(0, 0, m_width, m_height);
    }
    
    void OpenGLRenderNode::sync(QQuickItem *item)
    {
        m_width = static_cast<int>(item->width());
        m_height = static_cast<int>(item->height());
        if (!m_render) {
            m_render = static_cast<BaseRender*>(new les4{});
            if (m_render) {
                QObject::connect(item->window(), &QQuickWindow::beforeRendering, m_render, [&]() { m_render->beforeRender(); }, Qt::DirectConnection);
            }
        }
        if (m_render) {
            m_render->sync(item);
            m_render->setViewportSize(item->size().toSize() * item->window()->devicePixelRatio());
            m_render->setPosition(item->position().toPoint());
            m_render->setWindow(item->window());
        }
    }
    
    #endif
    

    les4.h

    #ifndef LES4_H
    #define LES4_H
    
    #include "../baserender.h"
    
    class QOpenGLTexture;
    class QOpenGLShaderProgram;
    class QOpenGLBuffer;
    class QOpenGLVertexArrayObject;
    
    class les4 : public BaseRender
    {
    public:
        les4();
    
        ~les4() override;
        virtual void init() override;
        virtual void render(const QSGRenderNode::RenderState *state) override;
        virtual void sync(QQuickItem *item) override;
        virtual void releaseResources() override;
    
        virtual void setViewportSize(QSize size) override { m_viewportSize = size; }
        virtual void setPosition(QPoint point) override { m_position = point; }
        virtual void setWindow(QQuickWindow* window) override { m_window = window; }
        virtual void beforeRender() override;
    
    private:
        QSize m_viewportSize{};
        QPoint m_position{};
        QQuickWindow* m_window{};
    
        QOpenGLShaderProgram *m_program = nullptr;
        QOpenGLVertexArrayObject *m_vao = nullptr;
        QOpenGLBuffer *m_vbo = nullptr;
        QOpenGLBuffer *m_ibo = nullptr;
    
        int m_width = 0;
        int m_height = 0;
    };
    
    #endif // LES4_H
    

    les4.cpp

    #include "les4.h"
    #include <QQuickWindow>
    #include <QOpenGLContext>
    #include <QOpenGLTexture>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLBuffer>
    #include <QOpenGLVertexArrayObject>
    #include <QOpenGLFunctions>
    #include <QGuiApplication>
    
    static const char *vertexShaderSource =
            "#version 100\n"
            "attribute vec3 aPos;\n"
            "attribute vec3 aColor;\n"
            "varying vec3 ourColor;\n"
            "void main() {\n"
            "   gl_Position = vec4(aPos.xyz, 1.0);\n"
            "   ourColor = aColor;\n"
            "}";
    
    static const char *fragmentShaderSource =
            "#version 100\n"
    #if defined(Q_OS_HTML5) or defined(Q_OS_WASM) or defined(__EMSCRIPTEN__)
            "precision mediump float;\n"
    #endif
            "varying vec3 ourColor;\n"
            "void main() {\n"
            "   gl_FragColor = vec4(ourColor, 1.0);\n"
            "}";
    
    static float vertices[] {
        // 位置              // 顏色
         0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
        -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
         0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 頂部
    };
    
    static unsigned int indices[] {
        0, 1, 2
    };
    
    les4::les4()
    {
    
    }
    
    les4::~les4()
    {
    
    }
    
    void les4::init() {
        QSurfaceFormat fmt;
        fmt.setVersion(2, 0);
        fmt.setRenderableType(QSurfaceFormat::OpenGLES);
        fmt.setMajorVersion(2);
        fmt.setMinorVersion(0);
        fmt.setRedBufferSize(5);
        fmt.setGreenBufferSize(6);
        fmt.setBlueBufferSize(5);
        fmt.setAlphaBufferSize(0);
        fmt.setDepthBufferSize(0);
    
        QSurfaceFormat::setDefaultFormat(fmt);
    
        QOpenGLContext *ctx = QOpenGLContext::currentContext();
        ctx->setFormat(fmt);
    }
    
    void les4::releaseResources() {
        delete m_program;
        m_program = nullptr;
    
        delete m_vbo;
        m_vbo = nullptr;
    
        delete m_ibo;
        m_ibo = nullptr;
    
        delete m_vao;
        m_vao = nullptr;
    }
    
    void les4::beforeRender() {
    
    }
    
    void les4::render(const QSGRenderNode::RenderState*) {
    
        QOpenGLContext *ctx = QOpenGLContext::currentContext();
    
    #if defined(Q_OS_HTML5) or defined(Q_OS_WASM) or defined(__EMSCRIPTEN__)
    const bool isCoreProfile  = false;
    #else
    const bool isCoreProfile  = ctx->format().profile() == QSurfaceFormat::CoreProfile;
    #endif
    
        QOpenGLFunctions *f = ctx->functions();
    
        int y = (m_window->size()* m_window->devicePixelRatio()).height() - m_viewportSize.height() - m_position.y();
        f->glViewport(m_position.x(), y, m_viewportSize.width(), m_viewportSize.height());
        f->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        f->glClear(GL_COLOR_BUFFER_BIT);
    
        auto setupVertAttrs = [this, f] {
            m_vbo->bind();
            f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)0);
            f->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (void*)(3*sizeof(float)));
            f->glEnableVertexAttribArray(0);
            f->glEnableVertexAttribArray(1);
        };
    
        if (!m_program) {
            m_program = new QOpenGLShaderProgram;
            m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
            m_program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
            m_program->bindAttributeLocation("aPos", 0);
            m_program->bindAttributeLocation("aColor", 1);
            m_program->link();
    
            m_vao = new QOpenGLVertexArrayObject;
            m_vao->create();
    
            m_vbo = new QOpenGLBuffer;
            m_vbo->create();
    
            m_ibo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
            m_ibo->create();
        }
    
        // non-premultiplied alpha
        f->glEnable(GL_BLEND);
        f->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        // no backface culling
        f->glDisable(GL_CULL_FACE);
        // still need depth test to test against the items rendered in the opaque pass
        f->glEnable(GL_DEPTH_TEST);
        // but no need to write out anything to the depth buffer
        f->glDepthMask(GL_FALSE);
        // do not write out alpha
        f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
        // will always scissor
        f->glEnable(GL_SCISSOR_TEST);
    
        if (m_vao->isCreated())
            m_vao->bind();
    
        m_program->bind();
    
        m_vbo->bind();
        m_vbo->allocate(vertices, sizeof(vertices));
        m_ibo->bind();
        m_ibo->allocate(indices, sizeof(indices));
    
        setupVertAttrs();
    
        //scissor...
        //texture...
        f->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
        f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    }
    
    void les4::sync(QQuickItem *item) {
      //  qDebug() << "w:" << item->width() << " h:" << item->height();
        m_width = static_cast<int>(item->width());
        m_height = static_cast<int>(item->height());
    }
    

    Please help me. I'm stuck here for a long time.

    1 Reply Last reply
    0
    • J Offline
      J Offline
      Junyu Ke
      wrote on last edited by
      #2

      I figure out the solution.
      First there is supposed to be three indices in my elements. The second argument of the function glDrawElements should be 3.
      Second there's a limitation in webgl that the type of element supposed to be GL_UNSIGNED_SHORT.

      1 Reply Last reply
      1

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved