Qt 6.6.1 WebAssembly: Triangle disappears when it was clicked
-
I created a bug report about the problem above on Desktop:
Drawing a triangle doesn't work on laptop Asus K53SV with Mesa using Qt 6.7.0 beta1
: https://bugreports.qt.io/browse/QTBUG-120949 -
I created a separated topic for the problem above on Desktop: Drawing a triangle doesn't work on laptop Asus K53SV with Mesa using Qt 6.7.0 beta1
-
@Christian-Ehrlicher solved the problem above for Desktop. I forgot to activate (bind) the program in paintGL():
void paintGL() override { m_program.bind(); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 4); }
This program works on Desktop but it still doesn't work on WebAssembly. I use
Qt 6.7.0 beta1
. But now it doesn't print this messageWebGL: INVALID_OPERATION: drawArrays: no valid shader program in use
to the browser console. The window is black on browser.pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp
main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtWidgets/QApplication> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { resize(350, 350); setWindowTitle("OpenGL Triangle"); } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.4f, 0.8f, 0.9f, 1.f); qDebug() << "OpenGL Version:" << (const char*) glGetString(GL_VERSION); qDebug() << "GLSL Version:" << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); qDebug() << "OpenGL Vendor:" << (const char*) glGetString(GL_VENDOR); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "//out vec4 fragColor;\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2); m_program.enableAttributeArray("aPosition"); } void paintGL() override { m_program.bind(); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 4); } private: QOpenGLShaderProgram m_program; QOpenGLBuffer m_vertPosBuffer; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWidget w; w.show(); return app.exec(); }
-
I made a bug report for drawing a triangle without clicking. It draws a black screen. I attacked a zip here: https://bugreports.qt.io/browse/QTBUG-120954
-
The solution for drawing a triangle with
Qt 6.7.0 beta1
is to add bind() for the vertex buffer:  void paintGL() override   {     m_program.bind();     m_vertPosBuffer.bind();     m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2);     m_program.enableAttributeArray("aPosition");     glClear(GL_COLOR_BUFFER_BIT);     glDrawArrays(GL_TRIANGLES, 0, 3);   }
But why a background is black?
I set it to blue. If I switch to Desktop I see the blue background:
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp
main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtWidgets/QApplication> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { resize(350, 350); setWindowTitle("OpenGL Triangle"); } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.4f, 0.8f, 0.9f, 1.f); qDebug() << "OpenGL Version:" << (const char*) glGetString(GL_VERSION); qDebug() << "GLSL Version:" << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); qDebug() << "OpenGL Vendor:" << (const char*) glGetString(GL_VENDOR); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); } void paintGL() override { m_program.bind(); m_vertPosBuffer.bind(); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2); m_program.enableAttributeArray("aPosition"); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); } private: QOpenGLShaderProgram m_program; QOpenGLBuffer m_vertPosBuffer; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWidget w; w.show(); return app.exec(); }
-
So when I run an example above on WebAssembly it draws a background in black color. I created a bug report: https://bugreports.qt.io/browse/QTBUG-120956
-
I found a way how to draw a custom background color. In the example above I set a background color in the
initializeGL()
method:void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.4f, 0.8f, 0.9f, 1.f);
But now I moved the setting of background color to the
paintGL()
method:void paintGL() override { // ... glClearColor(0.4f, 0.8f, 0.9f, 1.f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); }
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp
main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtWidgets/QApplication> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { resize(350, 350); setWindowTitle("OpenGL Triangle"); } private: void initializeGL() override { initializeOpenGLFunctions(); qDebug() << "OpenGL Version:" << (const char*) glGetString(GL_VERSION); qDebug() << "GLSL Version:" << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); qDebug() << "OpenGL Vendor:" << (const char*) glGetString(GL_VENDOR); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); } void paintGL() override { m_program.bind(); m_vertPosBuffer.bind(); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2); m_program.enableAttributeArray("aPosition"); glClearColor(0.4f, 0.8f, 0.9f, 1.f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); } private: QOpenGLShaderProgram m_program; QOpenGLBuffer m_vertPosBuffer; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWidget w; w.show(); return app.exec(); }
-
This is a solution of the topic with picking color of a triangle. I didn't test it in
Qt 6.6.1
. It works inQt 6.7.0 beta1
.- The shader program must be bind before drawing
- The vertex buffer must be bind before drawing
glClearColor
must be called beforeglClear
inpaintGL
for WebAssembly
This example prints a color in the point of mouse click using the
glReadPixles
method:void paintGL() override { glClearColor(0.2f, 0.2f, 0.2f, 1.f); glClear(GL_COLOR_BUFFER_BIT); m_program.bind(); m_vertPosBuffer.bind(); m_program.setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2); m_program.enableAttributeArray(m_aPositionLocation); glDrawArrays(GL_TRIANGLES, 0, 3); // qDebug() << glGetError() << "\n"; if (m_mouseClicked) { // Read the pixel GLubyte pixel[4]; glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); // qDebug() << glGetError() << "\n"; qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f; m_mouseClicked = false; } }
pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtGui/QMouseEvent> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QWidget> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { Q_OBJECT private: void initializeGL() override { initializeOpenGLFunctions(); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); m_aPositionLocation = m_program.attributeLocation("aPosition"); } void paintGL() override { glClearColor(0.2f, 0.2f, 0.2f, 1.f); glClear(GL_COLOR_BUFFER_BIT); m_program.bind(); m_vertPosBuffer.bind(); m_program.setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2); m_program.enableAttributeArray(m_aPositionLocation); glDrawArrays(GL_TRIANGLES, 0, 3); // qDebug() << glGetError() << "\n"; if (m_mouseClicked) { // Read the pixel GLubyte pixel[4]; glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); // qDebug() << glGetError() << "\n"; qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f; m_mouseClicked = false; } } void mousePressEvent(QMouseEvent *event) override { m_mouseX = event->pos().x(); m_mouseY = height() - event->pos().y() - 1; m_mouseClicked = true; update(); } private: int m_mouseX; int m_mouseY; bool m_mouseClicked = false; QOpenGLBuffer m_vertPosBuffer; QOpenGLShaderProgram m_program; int m_aPositionLocation; }; class MainWindow : public QWidget { Q_OBJECT public: MainWindow() { setWindowTitle("Pick a red or green triangle"); resize(350, 350); m_nameLabel = new QLabel("Click on a triangle or background"); m_nameLabel->setSizePolicy(QSizePolicy::Policy::Fixed, QSizePolicy::Policy::Fixed); OpenGLWidget *openGLWidget = new OpenGLWidget(); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_nameLabel); layout->addWidget(openGLWidget); setLayout(layout); } private: QLabel *m_nameLabel; }; #include "main.moc" int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow w; w.show(); return app.exec(); }
-
8 8Observer8 has marked this topic as solved on
-
Piotr WierciĆski wrote here: https://bugreports.qt.io/browse/QTBUG-120956 that it is better to use QOpenGLWindow instead of QOpenGLWidget with WebAssembly:
If separate context is needed, consider using QOpenGLWindow , which will have it's own canvas in DOM and it's own WebGL context, instead of QOpenGLWidget
I tried it and he is right. With QOpenGLWindow I can call
glClearColor
ininitializeGL
:#include <QtGui/QOpenGLFunctions> #include <QtOpenGL/QOpenGLWindow> #include <QtWidgets/QApplication> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.2f, 0.5f, 0.3f, 1.f); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWindow w; w.show(); return app.exec(); }
background-color-qopenglwindow-webassembly-qt6-cpp.pro
QT += core gui opengl widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
-
I even must not bind a shader program (
m_program.bind()
) and a vertex buffer (m_vertPosBuffer.bind()
) inside ofpaintGL
with QOpenGLWindow:main.cpp
#include <QtGui/QOpenGLFunctions> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtOpenGL/QOpenGLWindow> #include <QtWidgets/QApplication> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { QOpenGLBuffer m_vertPosBuffer; QOpenGLShaderProgram m_program; void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.2f, 0.5f, 0.3f, 1.f); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2); m_program.enableAttributeArray("aPosition"); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWindow w; w.show(); return app.exec(); }
simple-triangle-qopenglwindow-qt6-cpp.pro
QT += core gui opengl widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
-
Color picking with
glReadPixels
works without problems on WebAssembly withQOpenGLWindow
andQOpenGLWidget
:main.cpp
#include <QtGui/QMouseEvent> #include <QtGui/QOpenGLFunctions> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtOpenGL/QOpenGLWindow> #include <QtWidgets/QApplication> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { int m_mouseX; int m_mouseY; bool m_mouseClicked = false; QOpenGLBuffer m_vertPosBuffer; QOpenGLShaderProgram m_program; void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.2f, 0.2f, 0.2f, 1.f); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2); m_program.enableAttributeArray("aPosition"); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); if (m_mouseClicked) { // Read the pixel GLubyte pixel[4]; glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); // qDebug() << glGetError() << "\n"; qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f; m_mouseClicked = false; } } void mousePressEvent(QMouseEvent *event) override { m_mouseX = event->pos().x(); m_mouseY = height() - event->pos().y() - 1; m_mouseClicked = true; update(); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWindow w; w.show(); return app.exec(); }
pick-color-of-simple-triangle-qopenglwindow-qt6-cpp.pro
QT += core gui opengl widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
-
Color picking with
glReadPixels
works without problems on WebAssembly withQOpenGLWindow
andQOpenGLWidget
:main.cpp
#include <QtGui/QMouseEvent> #include <QtGui/QOpenGLFunctions> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtOpenGL/QOpenGLWindow> #include <QtWidgets/QApplication> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { int m_mouseX; int m_mouseY; bool m_mouseClicked = false; QOpenGLBuffer m_vertPosBuffer; QOpenGLShaderProgram m_program; void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.2f, 0.2f, 0.2f, 1.f); QString vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; QString fragmentShaderSource = "#ifdef GL_ES\n" "precision mediump float;\n" "#endif\n" "void main()\n" "{\n" " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" "}\n"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertexShaderSource); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragmentShaderSource); m_program.link(); m_program.bind(); float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2); m_program.enableAttributeArray("aPosition"); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); if (m_mouseClicked) { // Read the pixel GLubyte pixel[4]; glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); // qDebug() << glGetError() << "\n"; qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f; m_mouseClicked = false; } } void mousePressEvent(QMouseEvent *event) override { m_mouseX = event->pos().x(); m_mouseY = height() - event->pos().y() - 1; m_mouseClicked = true; update(); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); OpenGLWindow w; w.show(); return app.exec(); }
pick-color-of-simple-triangle-qopenglwindow-qt6-cpp.pro
QT += core gui opengl widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp TARGET = app
@8Observer8 said in Qt 6.6.1 WebAssebly: Triangle disappears when it was clicked:
Color picking with glReadPixels works without problems on WebAssembly with QOpenGLWindow and QOpenGLWidget
I had a problem with color picking on Android but it was solved here: https://forum.qt.io/post/787931