Qt 6.6.1 WebAssembly Error. WebGL: INVALID_ENUM: bindFramebuffer: invalid target
-
Hi,
My example works on Desktop. It prints a color of a pixel with (0, 0) coordinates and OpenGL version:
But when I try to build it for WebAssembly the browser prints this message:
WebGL: INVALID_ENUM: bindFramebuffer: invalid target
main.cpp
#include <QtGui/QOpenGLExtraFunctions> #include <QtGui/QSurfaceFormat> #include <QtGui/QVector3D> #include <QtOpenGL/QOpenGLFramebufferObject> #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtWidgets/QWidget> #include <QtWidgets/QVBoxLayout> #include <QtOpenGLWidgets/QOpenGLWidget> class OpenGLWidget : public QOpenGLWidget, private QOpenGLExtraFunctions { Q_OBJECT public: OpenGLWidget() { QSurfaceFormat surfaceFormat; surfaceFormat.setSamples(4); setFormat(surfaceFormat); } signals: void showInfoSignal(const QString &openGLVersion, const QString &shadingVersion, const QString &vendor); void showPixelColorSignal(const QVector3D &color); private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.f, 1.f, 0.f, 1.f); m_fbo.reset(new QOpenGLFramebufferObject(1, 1)); QString version(QString("OpenGL version: %1").arg((const char*) glGetString(GL_VERSION))); QString shadingLanguageVersion(QString("GLSL version: %1") .arg((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION))); QString vendor(QString("Vendor: %1").arg((const char*) glGetString(GL_VENDOR))); emit showInfoSignal(version, shadingLanguageVersion, vendor); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); // Set draw buffer to be fbo. Read buffer is already the default one glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo->handle()); // Blit from the default MSAA buffer to non-MSAA fbo glBlitFramebuffer(0, 0, m_fbo->width(), m_fbo->height(), 0, 0, m_fbo->width(), m_fbo->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context()->defaultFramebufferObject()); // Set read buffer glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo->handle()); // Read the pixel GLubyte pixel[4]; glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); // Set read buffer back to default glBindBuffer(GL_READ_FRAMEBUFFER, context()->defaultFramebufferObject()); emit showPixelColorSignal(QVector3D(pixel[0] / 255.f, pixel[1] / 255.f, pixel[2] / 255.f)); } private: std::unique_ptr<QOpenGLFramebufferObject> m_fbo; }; class MainWindow : public QWidget { Q_OBJECT public: MainWindow() { resize(300, 300); setWindowTitle("Read Pixel Color"); m_openGLVersionLabel = new QLabel(); m_shadingLanguageVersionLabel = new QLabel(); m_vendorLabel = new QLabel(); m_pixelColorLabel = new QLabel(); OpenGLWidget *openGLWidget = new OpenGLWidget(); m_openGLVersionLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); m_shadingLanguageVersionLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); m_vendorLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); m_pixelColorLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_openGLVersionLabel); layout->addWidget(m_shadingLanguageVersionLabel); layout->addWidget(m_vendorLabel); layout->addWidget(m_pixelColorLabel); layout->addWidget(openGLWidget); setLayout(layout); connect(openGLWidget, &OpenGLWidget::showPixelColorSignal, this, &MainWindow::showPixelColorSlot); connect(openGLWidget, &OpenGLWidget::showInfoSignal, this, &MainWindow::showInfoSlot); } private slots: void showInfoSlot(const QString &openGLVersion, const QString &shadingVersion, const QString &vendor) { m_openGLVersionLabel->setText(openGLVersion); m_shadingLanguageVersionLabel->setText(shadingVersion); m_vendorLabel->setText(vendor); } void showPixelColorSlot(const QVector3D &color) { m_pixelColorLabel->setText(QString("Pixel Color: (r: %1, g: %2, b: %3)") .arg(color.x()).arg(color.y()).arg(color.x())); } private: QLabel *m_openGLVersionLabel; QLabel *m_shadingLanguageVersionLabel; QLabel *m_vendorLabel; QLabel *m_pixelColorLabel; }; #include "main.moc" int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow w; w.show(); return app.exec(); }
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
-
-
Dark_Photon answered here that it seams like WebAssembly uses WebGL 1.0 where there is no
GL_DRAW_FRAMEBUFFER
andGL_READ_FRAMEBUFFER
: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bindFramebuffer But WebGL 2.0 has them. This means that WebAssembly uses WebGL 1.0. To solve the problem, I need WebAssembly to use WebGL 2.0. But how to do that? -
I commented all lines of code except
glClear()
in thepaintGL()
method to show OpenGL version, GLSL version, and vendor:- OpenGL version:
OpenGL version: OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium))
- GLSL version:
GLSL version: OpenGL ES GLSL ES 1.00 (WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium))
- Vendor version:
Vendor: WebKit
How to activate WebGL 2.0 from WebAssembly?
- OpenGL version:
-
@8Observer8
Set the QSurfaceFormat version to 3.0 -
@lorn-potter said in Qt 6.6.1 WebAssembly Error. WebGL: INVALID_ENUM: bindFramebuffer: invalid target:
Set the QSurfaceFormat version to 3.0
I tried to set:
OpenGLWidget() { QSurfaceFormat surfaceFormat; surfaceFormat.setMajorVersion(3); surfaceFormat.setMinorVersion(0); surfaceFormat.setSamples(4); setFormat(surfaceFormat); }
But it didn't help:
-
I found a temporary solution that is good for me for now. I just deleted the sampling:
OpenGLWidget() { // QSurfaceFormat surfaceFormat; // surfaceFormat.setMajorVersion(3); // surfaceFormat.setMinorVersion(0); // surfaceFormat.setSamples(4); // setFormat(surfaceFormat); }
In this case I don't need to use
GL_DRAW_FRAMEBUFFER
andGL_READ_FRAMEBUFFER
to read a pixel color usingglReadPixels()
:void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); // // Set draw buffer to be fbo. Read buffer is already the default one // glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo->handle()); // // Blit from the default MSAA buffer to non-MSAA fbo // glBlitFramebuffer(0, 0, m_fbo->width(), m_fbo->height(), // 0, 0, m_fbo->width(), m_fbo->height(), // GL_COLOR_BUFFER_BIT, GL_NEAREST); // glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context()->defaultFramebufferObject()); // // Set read buffer // glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo->handle()); // Read the pixel GLubyte pixel[4]; glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); // Set read buffer back to default // glBindBuffer(GL_READ_FRAMEBUFFER, context()->defaultFramebufferObject()); qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f; emit showPixelColorSignal(QVector3D(pixel[0] / 255.f, pixel[1] / 255.f, pixel[2] / 255.f)); }
My applications works correctly on Android and WebAssembly. It read a pixel with green color (0, 1, 0):
Android:
WebAssembly: