Skip to content

Qt for WebAssembly

Specific issues when using Qt for WebAssembly

437 Topics 1.7k Posts
  • How to extend the Cube OpenGL ES 2.0 example for 3D meshes?

    Unsolved
    6
    0 Votes
    6 Posts
    394 Views
    8Observer88

    I created this bug report about the problem above with anti-aliasing on QOpenGLWidget: The setSamples() method doesn't work on QOpenGLWidget for WebAssembly

    @Even-Oscar-Andersen answered in the bug report comments:

    reproduced on 6.6.2,

    This might be fixed in the not yet released 6.8.x (you will have to build yourself from dev)

    I think that rebuilding Qt dev from source may be useful for those who want to use QOpenGLWidget with Qt GUI on WASM with anti-aliasing. Maybe some people don’t need anti-aliasing. I don't need Qt GUI for my current tasks but I need anti-aliasing. I prefer to use QOpenGLWindow because it allows to make smooth animation for WASM without QTimer (animation with timer isn't smooth) using the setSwapInterval(1) method and the frameSwapped signal:

    OpenGLWindow.cpp

    OpenGLWindow::OpenGLWindow() { setTitle("OpenGL ES 2.0, Qt6, C++"); resize(m_initialWindowWidth, m_initialWindowHeight); QSurfaceFormat surfaceFormat; surfaceFormat.setDepthBufferSize(24); surfaceFormat.setSamples(4); surfaceFormat.setSwapInterval(1); connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); setFormat(surfaceFormat); }

    OpenGLWindow.h

    #include <QtCore/QElapsedTimer> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { private: QElapsedTimer m_elapsedTimer; } void OpenGLWindow::paintGL() { float dt = m_elapsedTimer.elapsed() / 1000.f; m_elapsedTimer.restart(); qDebug() << dt; }
  • How to set up Assimp for Qt6 MinGW 64-bit

    Solved
    11
    0 Votes
    11 Posts
    844 Views
    8Observer88

    Botje wrote the next comment on Stack Overflow:

    libassimp.a does not contain zlib. If you inspect the makefile generated by cmake you will see it just collects all the object files and does not add libz in any way. That is reserved for the final step where your application links to libassimp.a, because other dependencies might also need zlib and if each brings its own copy you get conflicts.

  • 0 Votes
    2 Posts
    365 Views
    E

    For windows, visual studio build with Qt 6.6.2 installed in C:\Qt

    Note the two different ways of running cmake

    vcvars64 (for msvc build) git clone https://github.com/msorvig/qt-webassembly-examples.git cd qt-webassembly-examples\gui_webgltest C:\Qt\6.6.2\wasm_singlethread\bin\qt-cmake .
    (creates openglwindow.html) cmake --build .
    (creates .js, .wasm) start emrun openglwindow.html
  • Empty headers in WASM 6.6.2.

    Unsolved
    3
    0 Votes
    3 Posts
    237 Views
    D

    @doumdi said in Empty headers in WASM 6.6.2.:

    I have the exact same problem, C++ code for requests generates unusable headers (empty or non ISO-8859-1). Any way to fix this problem ?

    I think this might be fixed in the new release : https://bugreports.qt.io/browse/QTBUG-122893

  • qmake for wasm unable to find opengl libraries

    Unsolved
    11
    0 Votes
    11 Posts
    651 Views
    S

    @8Observer8, @SGaist, @jsulm :

    qt 6.6.2, emscripten: 3.1.37, ubuntu: 22.04

    i am trying to compile the code for loading obj using assimp (for wasm). I get error qglobal.h: fatal error: 'type_traits' file not found.

    My question is how to avoid this error?

    /home/neo/Desktop/softwares/qt662_wasm/qt6/qtbase/src/corelib/global/qglobal.h:13:12: fatal error: 'type_traits' file not found # include <type_traits>

    However, I have /usr/include/c++/11/type_traits file. The file at /home/neo/Desktop/softwares/qt662_wasm/qt6/qtbase/src/corelib/global/qglobal.h reads:

    #ifdef __cplusplus # include <type_traits> ... #endif

    I think this problem has been faced before as documented in type_traits-file-not-found-while-building-qwt6-1-4. This is occuring if we compile for wasm too.

    My main.cpp and test.pro are as below. I use assimp to load 3D meshes, which I have built using emscripten using the following steps:

    git clone https://github.com/assimp/assimp.git cd assimp && mkdir build && cd build emcmake cmake .. emmake make

    main.cpp

    #include <QtWidgets/QApplication> //#include <QtGui/QOpenGLWidget> #include <QOpenGLWidget> #include <QtWidgets/QMessageBox> //#include <QtGui/QOpenGLBuffer> #include <QOpenGLBuffer> //#include <QtGui/QOpenGLShaderProgram> #include <QOpenGLShaderProgram> #include <QtGui/QMatrix4x4> #include <QtGui/QVector3D> #include <QtCore/QDebug> #include <assimp/Importer.hpp> #include <assimp/scene.h> #include <assimp/postprocess.h> #include <QMouseEvent> //#include <cstdarg> class OpenGLWidget : public QOpenGLWidget { public: OpenGLWidget(QWidget *parent = nullptr) : QOpenGLWidget (parent) { setWindowTitle("Qt load obj using shaders"); resize(600, 600); } private: QOpenGLBuffer m_vertPosBuffer; QOpenGLShaderProgram m_program; int m_numVertices; void initializeGL() override { glClearColor(0.1f, 0.1f, 0.1f, 1.f); glEnable(GL_DEPTH_TEST); Assimp::Importer importer; const char *path = "./REC-3MxwG6i6jfG8ig2.obj"; const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) { qDebug() << "Assimp Error:" << importer.GetErrorString(); QMessageBox::critical(this, "Assimp Error:", importer.GetErrorString()); return; } m_numVertices = scene->mMeshes[0]->mNumVertices; float vertPositions[m_numVertices * 3]; int vertPosIndex = 0; for (int i = 0; i < m_numVertices; i++) { vertPositions[vertPosIndex++] = scene->mMeshes[0]->mVertices[i].x; vertPositions[vertPosIndex++] = scene->mMeshes[0]->mVertices[i].y; vertPositions[vertPosIndex++] = scene->mMeshes[0]->mVertices[i].z; // qDebug() << scene->mMeshes[0]->mVertices[i].x << ", " // << scene->mMeshes[0]->mVertices[i].y << ", " // << scene->mMeshes[0]->mVertices[i].z; } m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); const char *vertShaderSrc = "#version 330 core\n" "in vec3 aPosition;" "uniform mat4 uModelMatrix;" "void main()" "{" " gl_Position = uModelMatrix * vec4(aPosition, 1.0);" "}"; const char *fragShaderSrc = "#version 330 core\n" "out vec4 fragColor;" "void main()" "{" " fragColor = vec4(0.8, 0.2, 0.2, 1.0);" "}"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertShaderSrc); m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShaderSrc); m_program.link(); QMatrix4x4 modelMatrix; modelMatrix.scale(0.5); m_program.bind(); m_program.setUniformValue("uModelMatrix", modelMatrix); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 3); m_program.enableAttributeArray("aPosition"); } void resizeGL(int w, int h) override { glViewport(0, 0, w, h); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, m_numVertices); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); OpenGLWidget w; w.show(); return a.exec(); }

    test.pro

    QT += core gui opengl openglwidgets # Add the path to the Assimp library directory if needed LIBS += -L/home/neo/Desktop/softwares/assimp/build/lib # Link against the Assimp library LIBS += -lassimp # Add the path to the Assimp header files if needed INCLUDEPATH += /home/neo/Desktop/softwares/assimp/include INCLUDEPATH += /usr/include/x86_64-linux-gnu INCLUDEPATH += /usr/include/linux # Add include path to Emscripten's C++ standard library headers INCLUDEPATH += /home/neo/Desktop/softwares/emsdk/upstream/emscripten/system/include # the system's C++ standard library QMAKE_CXXFLAGS += -stdlib=libstdc++ # Additional compiler options for Assimp QMAKE_CXXFLAGS += -Wno-deprecated-declarations TEMPLATE = app TARGET = AssimpExample CONFIG += c++11 SOURCES += main.cpp
  • Dealing with keyboard layout for input on Qt WebAssembly

    Unsolved
    2
    2 Votes
    2 Posts
    283 Views
    8Observer88

    All resources (sprites, music and sounds) have been replaced with free ones. You can see a list of free resources here. For example, I took the sprites here: https://webfussel.itch.io/more-bit-8-bit-mario

    itch.io page Click this link to play in the browser (use WAD or arrow keys to move and jump) Download EXE for Windows 10, 64-bit APK-file for Android

    mario-2d-jumps-webfussel-opengles2-qt6-cpp-android.gif

  • Is openGL, GLU, GLUT not supported in qt for wasm

    Unsolved
    7
    0 Votes
    7 Posts
    560 Views
    8Observer88

    @shome said in Is openGL, GLU, GLUT not supported in qt for wasm:

    My actual code uses the opengl functions gluPerspective, glShadeModel, glLightModelfv, glLightfv, glColorMaterial, glMaterialfv, glLightModeli, glTranslatef, and glMultMatrixd.

    WebGL doesn't support these functions. You should use OpenGL ES, shaders and QMatrix4x4 instead.

    My example can help you. It draws a triangle. You can run it in the browser: https://65fb01d024b197009c29122c--lustrous-croissant-656612.netlify.app/ It is a free hosting: netlify.com My example uses QOpenGLWindow instead of QOpenGLWidget. QOpenGLWindow is better for WebAssembly.

    pro:

    QT += core gui opengl widgets win32: LIBS += -lopengl32 CONFIG += c++17 SOURCES += \ main.cpp

    main.cpp

    #include <QtGui/QOpenGLFunctions> #include <QtGui/QSurfaceFormat> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLWindow> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtWidgets/QApplication> class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions { public: OpenGLWindow() { resize(350, 350); setTitle("OpenGL ES 2.0 Triangle"); } private: void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.4f, 0.8f, 0.9f, 1.f); qDebug() << "OpenGL Version:" << (const char*) glGetString(GL_VERSION) << "\n"; qDebug() << "GLSL Version:" << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n"; qDebug() << "OpenGL Vendor:" << (const char*) glGetString(GL_VENDOR) << "\n"; 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::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication app(argc, argv); OpenGLWindow w; w.show(); return app.exec(); }
  • Keyboard on chrome android always pop up.

    Unsolved
    1
    0 Votes
    1 Posts
    132 Views
    No one has replied
  • My experience using OpenGL on the WASM platform

    Solved
    3
    1 Votes
    3 Posts
    759 Views
    JasonWongJ

    @shome
    This is the GLSL code for this demo, which uses vertex shaders and fragment shaders.

    vert

    // 输入变量 attribute vec4 rawVertex; attribute vec3 rawNormal; attribute vec3 rawTangent; attribute vec2 rawTexture; // 输出变量 varying vec4 currentVertex; varying vec3 currentNormal; varying vec3 currentTangent; varying vec2 currentTexture; varying float currentDepth; // 绘制参数 uniform mat4 paintMatrix; uniform sampler2D waveTexture; uniform float timeOffset; void main() { currentDepth = 1.0 - ( rawVertex.z / -0.6 ); vec4 wave = texture2D( waveTexture, rawTexture + vec2( timeOffset, -timeOffset ) * 0.0001 ); vec4 newVertex = rawVertex; const float amplitude = 0.05; const float frequency = 6.0; newVertex.x += ( wave.r * 0.05 ) * currentDepth; newVertex.y += ( wave.b * 0.05 ) * currentDepth; newVertex.z += amplitude * sin( frequency * ( newVertex.x - newVertex.y ) + timeOffset * 0.001 ) * currentDepth; currentVertex = paintMatrix * newVertex; currentNormal = normalize( mat3( paintMatrix[ 0 ].xyz, paintMatrix[ 1 ].xyz, paintMatrix[ 2 ].xyz ) * rawNormal ); currentTangent = normalize( mat3( paintMatrix[ 0 ].xyz, paintMatrix[ 1 ].xyz, paintMatrix[ 2 ].xyz ) * rawTangent ); currentTexture = rawTexture; gl_Position = currentVertex; gl_Position.z /= 5.0; // 防止被视景体裁剪 }

    frag

    // 输入参数 varying vec4 currentVertex; varying vec3 currentNormal; varying vec3 currentTangent; varying vec2 currentTexture; varying float currentDepth; // 绘制参数 uniform sampler2D normalTexture; uniform sampler2D foamTexture; uniform sampler2D specularTexture; uniform mat4 paintMatrix; vec3 processColor1(vec3 color, vec3 normal) { const vec3 ambientColor = vec3( 1.0, 1.0, 1.0 ); // 环境光参数 const vec3 lightPos = vec3( 0.0, 0.4, 1.4 ); // 光源位置 const vec3 viewPos = vec3( 0.0, 0.0, 1.0 ); // 观察位置 const vec3 lightColor = vec3( 0.5, 0.5, 0.5 ); // 光源颜色 const float shininess = 48.0; // 镜面反射强度 float specularStrength = texture2D( specularTexture, currentTexture ).x; // 镜面反射颜色系数 // 计算方向向量 vec3 lightDir = normalize( lightPos - viewPos ); vec3 viewDir = normalize( -viewPos ); // 环境光照 vec3 ambient = ambientColor * color; // 漫反射光照 float diff = max( dot( normal, lightDir ), 0.0 ); vec3 diffuse = diff * lightColor * color; // 镜面反射光照 vec3 reflectDir = reflect( -lightDir, normal ); float spec = pow( max( dot( viewDir, reflectDir ), 0.0 ), shininess ); vec3 specular = specularStrength * spec * lightColor; vec3 result = ambient + diffuse + ( ( spec <= 1.0 ) ? ( specular ) : ( vec3( 0.0, 0.0, 0.0 ) ) ); // 合并光照效果 return result; } void main() { const vec3 defaultColor = vec3( 0.15, 0.35, 0.50 ); if ( currentDepth < 0.999 ) { gl_FragColor = vec4( defaultColor * currentDepth * 1.5, 1.0 ); return; } vec4 foamColor = texture2D( foamTexture, currentTexture ); vec3 currentColor = defaultColor + foamColor.xyz / 3.5; vec3 normalFromTexture = texture2D( normalTexture, currentTexture ).xyz * 2.0 - 1.0; vec3 currentBitangent = cross( currentTangent, currentNormal ); mat3 TBN = mat3( currentTangent, currentBitangent, currentNormal ); vec3 normal = normalize( TBN * normalFromTexture ); gl_FragColor = vec4( processColor1( currentColor, normal ) * currentDepth, 1.0 ); }
  • boiler plate code for opengl ES wasm

    Unsolved
    2
    0 Votes
    2 Posts
    160 Views
    SGaistS

    Hi,

    The sources of the examples are linked at the bottom of their detailed explanation. See here the cube example.

  • Touch controls

    Unsolved
    2
    0 Votes
    2 Posts
    186 Views
    K

    Interesting, I also now tested the same app with Qt 5.15 WASM and found that there double-tap with one finger behaved as a double-click. Why was it changed? I'd say the double-tap in 5.15 was much more intuitive than two-finger tap in 6.6.

  • dockerfile to compile qt6.5 for webassembly on ubuntu 18.04

    Unsolved
    11
    0 Votes
    11 Posts
    830 Views
    SGaistS

    @shome AFAIK, yes it should.

  • I have to touch the edittext to start entering text

    Unsolved
    2
    0 Votes
    2 Posts
    134 Views
    Axel SpoerlA

    @monettes
    That looks like a bug. Please report it at https://bugreports.qt.io

  • QOpenGLWidget is not supported on this platform.

    Unsolved
    5
    0 Votes
    5 Posts
    510 Views
    SGaistS

    @shome since you are targeting wasm, I would recommend to port your code to 6.5 at least. There's not much sense in trying to build it using an outdated version of Qt for such a new platform.

  • 0 Votes
    2 Posts
    247 Views
    F

    For testing I have patched out QWasmClipboard::initClipboardPermissions and bootstrapCheckPermissions (which also spawns async operations), now I am getting the same error for qtStdWebEventCallbackActivate, which looks like this bug:

    https://github.com/emscripten-core/emscripten/issues/18412 https://bugreports.qt.io/browse/QTBUG-102827
  • cmake configuration not found

    Unsolved
    1
    0 Votes
    1 Posts
    122 Views
    No one has replied
  • Opening keyboard on android chrome breaks html

    Solved
    2
    0 Votes
    2 Posts
    213 Views
    MesrineM

    @Mesrine

    The issue is not related to Qt for webassembly.
    The issue is related to opening a keyboard on mobile browsers triggers the window's resize event.
    The latter was used by my app to hide and show elements.

  • This topic is deleted!

    Unsolved
    1
    0 Votes
    1 Posts
    63 Views
    No one has replied
  • How to compile qt program to WebAssembly with cmake

    Solved
    3
    0 Votes
    3 Posts
    240 Views
    _

    @jsulm Thank you, I solved it .

    CMakeLists needs to contain :
    qt_standard_project_setup();
    qt_add_executable

  • 0 Votes
    3 Posts
    840 Views
    8Observer88

    It is a Chrome issue. Read Botje's comments: https://stackoverflow.com/questions/77951574/webgl-this-extension-has-very-low-support-on-mobile-devices