qmake for wasm unable to find opengl libraries
-
@shome Isn't this same question you already asked here: https://forum.qt.io/topic/155319/is-opengl-glu-glut-not-supported-in-qt-for-wasm?_=1710502214066 ?
-
@shome You should go through emscripten documentation about OpenGL support.
-
@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(); }
-
@8Observer8, @SGaist, @jsulm :
I tried to compile the above code for wasm. I get the following error. I tried googling/chatgpt to solve the error. It was suggested that my emscripten installation could be problematic.
However em++ --version yeilds: emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.37. I am using qt 6.6.2
My question is how do I get rid of the compilation errors for wasm. The same code compiled fine for qt (not for wasm)
/home/neo/Desktop/softwares/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/cmath:544:5: error: use of undeclared identifier '__promote' __promote<_A1, _A2, _A3> ^ /home/neo/Desktop/softwares/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/cmath:548:22: error: no template named '__promote' typedef typename __promote<_A1, _A2, _A3>::type __result_type; ^ /home/neo/Desktop/softwares/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1/cmath:552:12: error: call to 'hypot' is ambiguous return hypot((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z); ... ... /home/neo/Desktop/softwares/qt662_wasm/qt6/qtbase/src/corelib/text/qbytearrayalgorithms.h:134:68: error: unknown type name 'va_list' Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
I am attaching the main.cpp and test.pro:
#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 <cstdarg> class OpenGLWidget : public QOpenGLWidget { public: OpenGLWidget(QWidget *parent = nullptr) : QOpenGLWidget (parent) { setWindowTitle("Qt C++, OpenGL"); 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(); }
QT += core gui opengl openglwidgets
LIBS += -L/usr/lib/x86_64-linux-gnu/
LIBS += -lassimp
INCLUDEPATH += /usr/include
INCLUDEPATH += /usr/include/x86_64-linux-gnu
QMAKE_CXXFLAGS += -Wno-deprecated-declarations
TEMPLATE = app
TARGET = AssimpExample
CONFIG += c++11SOURCES += main.cpp
-
@shome Have you tried compiling an example into WASM that prints "Hello, World" to the console? Please, try to run this example: wasm-example-qt6-cpp.zip Open the browser console (for example, Ctrl+Shift+J in Chrome). It must print "Hello, World"
QT += core gui widgets CONFIG += c++17 SOURCES += \ main.cpp
main.cpp
#include <QtWidgets/QApplication> #include <QtWidgets/QWidget> class Widget : public QWidget { public: Widget() { qDebug() << "Hello, World"; } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); Widget w; w.show(); return app.exec(); }
-
@shome said in qmake for wasm unable to find opengl libraries:
LIBS += -lassimp
I think it's not possible to use Assimp with WASM. If I'm wrong, write about it. I see only one way to load 3D to use them with OpenGL for WASM - write your own parser from OBJ, COLLADA, glTF and so on. I prefer COLLADA because it allows you to save animations in Blender. OBJ is intended for static models only. glTF can store animation, but it is much more complex than COLLADA. COLLADA has XML format. Qt contains XML parser. Your own parser from COLLADA (OBJ, or glTF) will work on Android and WASM.
This Assimp example works on Desktop but it doesn't work when I build it to WASM: load-with-assimp-opengles2-qt6-cpp.zip
GitHub repo: https://github.com/8Observer8/load-with-assimp-opengl2-qt6-cpp
When I try to build this example to WASM I see this error:
load-with-assimp-opengles2-qt6-cpp.pro
QT += core gui openglwidgets widgets win32: LIBS += -lopengl32 INCLUDEPATH += $$PWD/libs/assimp-5.2.5-mingw-64-bit/include LIBS += -L$$PWD/libs/assimp-5.2.5-mingw-64-bit/lib LIBS += -lassimp CONFIG += c++11 SOURCES += \ main.cpp
main.cpp
#include <QtCore/QDebug> #include <QtGui/QMatrix4x4> #include <QtGui/QVector3D> #include <QtGui/QOpenGLFunctions> #include <QtOpenGL/QOpenGLBuffer> #include <QtOpenGL/QOpenGLShaderProgram> #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtWidgets/QApplication> #include <QtWidgets/QMessageBox> #include <assimp/Importer.hpp> #include <assimp/postprocess.h> #include <assimp/scene.h> class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions { public: OpenGLWidget() { setWindowTitle("OpenGL ES 2.0, Qt6, C++"); resize(400, 400); } private: QOpenGLBuffer m_vertPosBuffer; QOpenGLShaderProgram m_program; int m_numVertices; QMatrix4x4 m_modelMatrix; void initializeGL() override { initializeOpenGLFunctions(); glClearColor(0.1f, 0.1f, 0.1f, 1.f); glEnable(GL_DEPTH_TEST); Assimp::Importer importer; const char *path = "assets/models/plane-blender.dae"; 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; // qDebug() << "\n"; } m_vertPosBuffer.create(); m_vertPosBuffer.bind(); m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions)); const char *vertShaderSrc = "attribute vec3 aPosition;" "uniform mat4 uModelMatrix;" "void main()" "{" " gl_Position = uModelMatrix * vec4(aPosition, 1.0);" "}"; const char *fragShaderSrc = "void main()" "{" " gl_FragColor = vec4(0.5, 0.2, 0.7, 1.0);" "}"; m_program.create(); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc); m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc); m_program.link(); } void resizeGL(int w, int h) override { glViewport(0, 0, w, h); } void paintGL() override { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_modelMatrix.setToIdentity(); m_modelMatrix.scale(0.5); m_program.bind(); m_program.setUniformValue("uModelMatrix", m_modelMatrix); m_vertPosBuffer.bind(); m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 3); m_program.enableAttributeArray("aPosition"); glDrawArrays(GL_TRIANGLES, 0, m_numVertices); } }; int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL); QApplication app(argc, argv); OpenGLWidget w; w.show(); return app.exec(); }
-
You can try to add Assimp as source code. I made it for Box2D and Bullet Physics. Right click on the project in Qt Creator -> select "Add Existing Directory" -> select the source code folder of the Assimp library. If it will work you can build for WebAssembly, Android, and Desktop. The first build will be long (1-2 minutes), but the next ones will be much faster.
-
@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(); }
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