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.
Aucun commentaire:
Enregistrer un commentaire