Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved Qt -platform webgl support in pyqt

    Qt for Python
    qt for python
    2
    10
    1144
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • McTob
      McTob last edited by

      Dear all,
      I recently realized that QT had an amazing feature related to webgl support:
      https://www.qt.io/blog/2018/11/23/qt-quick-webgl-release-512

      This feature is extremely important to me, to the point where I could eventually rewrite my application in C++ in case the feature is not supported in python. However that would save me a lot of time, if I could provide a -platform webgl option to my python app and get the webgl support.

      My main object is a: PyQt5.Qt3DExtras.Qt3DWindow is there anywhere I could find information of the webgl support for pyqt ?

      Thank you a lot for your help

      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi,

        Did you check whether the corresponding QPA plugin is provided with your installation ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 0
        • McTob
          McTob last edited by

          @SGaist said in Qt -platform webgl support in pyqt:

          QPA plugin

          Thank you very much for your input, it helps me to check for the right concepts in the right place.
          Here is what I have installer:

          venv/lib/python3.7/site-packages/PyQt5/Qt/plugins/platforms/
          libqeglfs.so libqminimalegl.so libqoffscreen.so libqwayland-egl.so libqwayland-xcomposite-egl.so libqwebgl.so
          libqlinuxfb.so libqminimal.so libqvnc.so libqwayland-generic.so libqwayland-xcomposite-glx.so libqxcb.so

          There seems to be a libqwebgl.so I'll now check where I need to go from there with the documentation: https://doc.qt.io/qt-5/qpa.html

          1 Reply Last reply Reply Quote 0
          • SGaist
            SGaist Lifetime Qt Champion last edited by

            Then you can either start your application with the QT_QPA_PLATFORM environnement variable set to the correct value or pass the -platform option when starting your application.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply Reply Quote 0
            • McTob
              McTob last edited by McTob

              @SGaist said in Qt -platform webgl support in pyqt:

              QT_QPA_PLATFORM

              Thank you so much for the help.
              Unfortunately, it looks like my application is probably not going to be compatible with webgl:

              qt.qpa.webgl: WebGL QPA platform plugin: Raster surfaces are not supported
              Erreur de segmentation (core dumped)
              

              @McTob said in Qt -platform webgl support in pyqt:

              qt.qpa.webgl: WebGL QPA platform plugin: Raster surfaces are not supported

              I can potentially remove some of the feature (getting webGL to work would really be a dream feature for me), from those, whoich are the one most likely generating the incompatibility:

              from PyQt5.Qt3DExtras import QDiffuseSpecularMaterial, QTextureMaterial
              from PyQt5.Qt3DExtras import QText2DEntity, QExtrudedTextMesh
              from PyQt5.Qt3DRender import QTexture2D, QTextureLoader, QMaterial, QEffect
              

              Is there a list of compatible feature somewhere ?

              Thank you again

              1 Reply Last reply Reply Quote 0
              • SGaist
                SGaist Lifetime Qt Champion last edited by

                What technology are you using for your application ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply Reply Quote 0
                • McTob
                  McTob last edited by

                  python + some bindings to external libraries. But the 3d aspects are fully written in pyqt. I can get rid of some funcitonalities if I can find a decent workaround

                  1 Reply Last reply Reply Quote 0
                  • McTob
                    McTob last edited by McTob

                    Ok so I tried to address the problem differently. I just tried to run the following demo code from https://github.com/zchen24/examples-Qt/blob/master/qt3d/qt3d-simple-example.py:
                    with

                    export QSG_INFO=1
                    export QT_QPA_EGLFS_DEBUG=1
                    export QT_LOGGING_RULES=qt.qpa.*=true
                    QT_QPA_PLATFORM=webgl:port=8998 python ./test.py

                    #!/usr/bin/env python
                    """
                    This is a Python port of Qt 3D: Simple C++ Example code
                    https://doc.qt.io/qt-5.10/qt3d-simple-cpp-example.html
                    Tested on
                    Anaconda Python 3.6
                    pip install PyQt5 (Version 5.10)
                    """
                    
                    import sys
                    from OpenGL import GL
                    from PyQt5 import QtCore
                    from PyQt5.QtCore import *
                    from PyQt5.QtGui import *
                    from PyQt5.Qt3DCore import *
                    from PyQt5.QtWidgets import *
                    from PyQt5.Qt3DExtras import *
                    
                    
                    class OrbitTransformController(QObject):
                        def __init__(self, parent):
                            super(OrbitTransformController, self).__init__(parent)
                            self.m_target = QTransform()
                            self.m_matrix = QMatrix4x4()
                            self.m_radius = 1.0
                            self.m_angle = 0
                    
                        def getTarget(self):
                            return self.m_target
                    
                        def setTarget(self, target):
                            if self.m_target != target:
                                self.m_target = target
                                self.targetChanged.emit()
                    
                        def getRadius(self):
                            return self.m_radius
                    
                        def setRadius(self, radius):
                            if not QtCore.qFuzzyCompare(self.m_radius, radius):
                                self.m_radius = radius
                                self.updateMatrix()
                                self.radiusChanged.emit()
                    
                        def getAngle(self):
                            return self.m_angle
                    
                        def setAngle(self, angle):
                            if not QtCore.qFuzzyCompare(angle, self.m_angle):
                                self.m_angle = angle
                                self.updateMatrix()
                                self.angleChanged.emit()
                    
                        def updateMatrix(self):
                            self.m_matrix.setToIdentity()
                            self.m_matrix.rotate(self.m_angle, QVector3D(0, 1, 0))
                            self.m_matrix.translate(self.m_radius, 0, 0)
                            self.m_target.setMatrix(self.m_matrix)
                    
                        # QSignal
                        targetChanged = pyqtSignal()
                        radiusChanged = pyqtSignal()
                        angleChanged = pyqtSignal()
                    
                        # Qt properties
                        target = pyqtProperty(QTransform, fget=getTarget, fset=setTarget)
                        radius = pyqtProperty(float, fget=getRadius, fset=setRadius)
                        angle = pyqtProperty(float, fget=getAngle, fset=setAngle)
                    
                    
                    def createScene():
                        # root
                        rootEntity = QEntity()
                        material = QPhongMaterial(rootEntity)
                    
                        # torus
                        torusEntity = QEntity(rootEntity)
                        torusMesh = QTorusMesh()
                        torusMesh.setRadius(5)
                        torusMesh.setMinorRadius(1)
                        torusMesh.setRings(100)
                        torusMesh.setSlices(20)
                    
                        torusTransform = QTransform()
                        torusTransform.setScale3D(QVector3D(1.5, 1.0, 0.5))
                        torusTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1, 0, 0), 45))
                    
                        torusEntity.addComponent(torusMesh)
                        torusEntity.addComponent(torusTransform)
                        torusEntity.addComponent(material)
                    
                        # sphere
                        sphereEntity = QEntity(rootEntity)
                        sphereMesh = QSphereMesh()
                        sphereMesh.setRadius(3)
                    
                        sphereTransform = QTransform()
                        controller = OrbitTransformController(sphereTransform)
                        controller.setTarget(sphereTransform)
                        controller.setRadius(20)
                    
                        sphereRotateTransformAnimation = QPropertyAnimation(sphereTransform)
                        sphereRotateTransformAnimation.setTargetObject(controller)
                        sphereRotateTransformAnimation.setPropertyName(b'angle')
                        sphereRotateTransformAnimation.setStartValue(0)
                        sphereRotateTransformAnimation.setEndValue(360)
                        sphereRotateTransformAnimation.setDuration(10000)
                        sphereRotateTransformAnimation.setLoopCount(-1)
                        sphereRotateTransformAnimation.start()
                    
                        sphereEntity.addComponent(sphereMesh)
                        sphereEntity.addComponent(sphereTransform)
                        sphereEntity.addComponent(material)
                    
                        return rootEntity
                    
                    # container = QWidget.createWindowContainer(view)
                    # container.show()
                    
                    app = QApplication(sys.argv)
                    view = Qt3DWindow()
                    
                    scene = createScene()
                    
                    # camera
                    camera = view.camera()
                    camera.lens().setPerspectiveProjection(45.0, 16.0/9.0, 0.1, 1000)
                    camera.setPosition(QVector3D(0, 0, 40))
                    camera.setViewCenter(QVector3D(0, 0, 0))
                    
                    # for camera control
                    camController = QOrbitCameraController(scene)
                    camController.setLinearSpeed( 50.0 )
                    camController.setLookSpeed( 180.0 )
                    camController.setCamera(camera)
                    
                    view.setRootEntity(scene)
                    view.show()
                    
                    sys.exit(app.exec_())
                    

                    Here are the logs on server side:
                    qt.qpa.webgl: WebGL QPA Plugin created
                    qt.qpa.input.methods.serialize: QIBusEngineDesc::fromDBusArgument() "(sa{sv}ssssssssussssssss)"
                    qt.qpa.input.methods: socketWatcher.addPath "/home/user/.config/ibus/bus/57acbc52de7a41f6bcba53d2d3273731-unix-1"
                    qt.qpa.webgl.httpserver: Listening in port 8998
                    qt.qpa.webgl: New offscreen surface 0x7ffcabece970
                    qt.qpa.webgl: 0x7ffcabece960
                    qt.qpa.webgl.context: Creating context 1
                    qt.qpa.webgl.context: 0x55d81a4eb2e0
                    qt.qpa.webgl: 0x7f02a40053b0
                    qt.qpa.webgl.context: Creating context 2
                    qt.qpa.webgl: 0x7f02a4005730
                    qt.qpa.webgl.context: Creating context 3
                    qt.qpa.webgl: Creating platform window for: 0x55d81a4d7100
                    qt.qpa.webgl: New offscreen surface 0x55d81a536160
                    qt.qpa.webgl.window: Destroying -1

                    On client side:
                    WebGL warning: getParameter: pname: Invalid enum value <enum 0x8f38>

                    In the end, I only see a green loading sign that cycles forever, and not the actual 3d webgl rendering I was expecting. Any idea ?

                    McTob 1 Reply Last reply Reply Quote 0
                    • McTob
                      McTob @McTob last edited by McTob

                      I also tried from my operating system (ubuntun 20.04) python3 and (sudo apt-get install python3-opengl), I got slightly different results (but the webpage is still hanging on the loading sign):

                      qt.qpa.webgl: WebGL QPA Plugin created
                      qt.qpa.input.methods.serialize: QIBusEngineDesc::fromDBusArgument() "(sa{sv}ssssssssussssssss)"
                      qt.qpa.input.methods: socketWatcher.addPath "/home/user/.config/ibus/bus/57acbc52de7a41f6bcba53d2d3273731-unix-1"
                      qt.qpa.webgl.httpserver: Listening in port 8998
                      qt.qpa.webgl: New offscreen surface 0x7ffdf3b88660
                      qt.qpa.webgl: 0x7ffdf3b88650
                      qt.qpa.webgl.context: Creating context 1
                      qt.qpa.webgl.context: 0x1784000
                      qt.qpa.webgl: 0x7f21840053b0
                      qt.qpa.webgl.context: Creating context 2
                      qt.qpa.webgl: 0x7f2184005730
                      qt.qpa.webgl.context: Creating context 3
                      qt.qpa.webgl: Creating platform window for: 0x17705f0
                      qt.qpa.webgl: New offscreen surface 0x17d8680
                      qt.qpa.webgl.window: Destroying -1
                      qt.qpa.webgl.httpserver: ::1 requested: /
                      qt.qpa.webgl.httpserver: ::1 requested: /webqt.js
                      qt.qpa.webgl.websocketserver: Sending connect to QWebSocket(0x7f218800c270) QMap(("debug", QVariant(bool, false))("loadingScreen", QVariant(QByteArray, ""))("mouseTracking", QVariant(QByteArray, ""))("supportedFunctions", QVariant(QStringList, ("activeTexture", "attachShader", "bindAttribLocation", "bindBuffer", "bindFramebuffer", "bindRenderbuffer", "bindTexture", "blendColor", "blendEquation", "blendEquationSeparate", "blendFunc", "blendFuncSeparate", "bufferData", "bufferSubData", "checkFramebufferStatus", "clear", "clearColor", "clearDepthf", "clearStencil", "colorMask", "compileShader", "compressedTexImage2D", "compressedTexSubImage2D", "copyTexImage2D", "copyTexSubImage2D", "createProgram", "createShader", "cullFace", "deleteBuffers", "deleteFramebuffers", "deleteProgram", "deleteRenderbuffers", "deleteShader", "deleteTextures", "depthFunc", "depthMask", "depthRangef", "detachShader", "disableVertexAttribArray", "drawArrays", "drawElements", "enableVertexAttribArray", "finish", "flush", "framebufferRenderbuffer", "framebufferTexture2D", "frontFace", "genBuffers", "genFramebuffers", "genRenderbuffers", "genTextures", "generateMipmap", "getActiveAttrib", "getActiveUniform", "getAttachedShaders", "getAttribLocation", "getString", "getIntegerv", "getBooleanv", "enable", "disable", "getBufferParameteriv", "getError", "getParameter", "getFramebufferAttachmentParameteriv", "getProgramInfoLog", "getProgramiv", "getRenderbufferParameteriv", "getShaderInfoLog", "getShaderPrecisionFormat", "getShaderSource", "getShaderiv", "getTexParameterfv", "getTexParameteriv", "getUniformLocation", "getUniformfv", "getUniformiv", "getVertexAttribPointerv", "getVertexAttribfv", "getVertexAttribiv", "hint", "isBuffer", "isEnabled", "isFramebuffer", "isProgram", "isRenderbuffer", "isShader", "isTexture", "lineWidth", "linkProgram", "pixelStorei", "polygonOffset", "readPixels", "releaseShaderCompiler", "renderbufferStorage", "sampleCoverage", "scissor", "shaderBinary", "shaderSource", "stencilFunc", "stencilFuncSeparate", "stencilMask", "stencilMaskSeparate", "stencilOp", "stencilOpSeparate", "texImage2D", "texParameterf", "texParameterfv", "texParameteri", "texParameteriv", "texSubImage2D", "uniform1f", "uniform1fv", "uniform1i", "uniform1iv", "uniform2f", "uniform2fv", "uniform2i", "uniform2iv", "uniform3f", "uniform3fv", "uniform3i", "uniform3iv", "uniform4f", "uniform4fv", "uniform4i", "uniform4iv", "uniformMatrix2fv", "uniformMatrix3fv", "uniformMatrix4fv", "useProgram", "validateProgram", "vertexAttrib1f", "vertexAttrib1fv", "vertexAttrib2f", "vertexAttrib2fv", "vertexAttrib3f", "vertexAttrib3fv", "vertexAttrib4f", "vertexAttrib4fv", "vertexAttribPointer", "viewport", "blitFramebufferEXT", "renderbufferStorageMultisampleEXT", "getTexLevelParameteriv", "makeCurrent", "swapBuffers")))("sysinfo", QVariant(QVariantMap, QMap(("buildAbi", QVariant(QString, "x86_64-little_endian-lp64"))("buildCpuArchitecture", QVariant(QString, "x86_64"))("currentCpuArchitecture", QVariant(QString, "x86_64"))("kernelType", QVariant(QString, "linux"))("machineHostName", QVariant(QString, "supercomputer"))("prettyProductName", QVariant(QString, "Ubuntu 20.04.2 LTS"))("productType", QVariant(QString, "ubuntu"))("productVersion", QVariant(QString, "20.04"))))))
                      qt.qpa.webgl: 0x7f218800c270, Size: 1848x912. Physical Size: 490.755838x242.191193
                      qt.qpa.webgl.httpserver: ::1 requested: /favicon.png
                      qt.qpa.webgl: Connecting first client in the queue (0x7f218800c270)
                      qt.qpa.webgl: Creating platform window for: 0x17705f0
                      qt.qpa.webgl.window: Window 1 created
                      qt.qpa.webgl: Created platform window 0x18192d0 for: 0x17705f0
                      qt.qpa.webgl.websocketserver: Sending create_canvas to QWebSocket(0x7f218800c270) QMap(("height", QVariant(int, 912))("title", QVariant(QString, "test.py"))("width", QVariant(int, 1848))("winId", QVariant(qulonglong, 1))("x", QVariant(int, 0))("y", QVariant(int, 0)))
                      qt.qpa.webgl.context: 0x18192d0
                      qt.qpa.webgl.websocketserver: Sending gl_command makeCurrent to 0x7f218800c270 with 4 parameters
                      qt.qpa.webgl.websocketserver: Sending gl_command glGetIntegerv to 0x7f218800c270 with 1 parameters
                      qt.qpa.webgl: gl_response message received QJsonObject({"id":1,"type":"gl_response","value":32})
                      qt.qpa.webgl.websocketserver: Sending gl_command glGetIntegerv to 0x7f218800c270 with 1 parameters
                      qt.qpa.webgl: gl_response message received QJsonObject({"id":2,"type":"gl_response","value":null})

                      1 Reply Last reply Reply Quote 0
                      • McTob
                        McTob last edited by

                        Looks like this problem goes deeper than a simple pyqt issue. I have posted my issue on SO:
                        https://stackoverflow.com/questions/66222702/how-to-get-webgl-support-in-pyqt5

                        And reported as a bug on qt jira:
                        https://bugreports.qt.io/browse/QTBUG-91162

                        With additional informations related to javascript logs.

                        1 Reply Last reply Reply Quote 1
                        • First post
                          Last post