Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for WebAssembly
  4. My experience using OpenGL on the WASM platform
Forum Updated to NodeBB v4.3 + New Features

My experience using OpenGL on the WASM platform

Scheduled Pinned Locked Moved Solved Qt for WebAssembly
3 Posts 2 Posters 1.4k Views 1 Watching
  • 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.
  • J Offline
    J Offline
    JasonWong
    wrote on 18 Mar 2024, 02:50 last edited by
    #1

    I've noticed that many people are asking questions related to OpenGL. Based on my experience, I'd like to share some insights to help everyone get started more quickly.

    • In WASM, you can normally develop 3D programs using OpenGL, with the same logic and process as when you develop on the Windows platform or the Android platform. And we only need to adapt to the WASM platform, whether your web is running on x86 Windows or ARM Android.
    • On the WASM platform, we need to use WebGL, not OpenGL. They have similar syntax, but overall, WebGL has been trimmed down and is more streamlined. It's like how we use OpenGL/ES on iOS, which also has fewer features than OpenGL. Of course, for simplicity, you can refer to all these collectively as OpenGL, but be mindful to differentiate them when searching for resources.
    • Although it's called WebGL, at the Qt programming level, we still use the QOpenGLXXX classes.
    • Try to use QOpenGLFunctions instead of directly calling OpenGL functions, as this reduces a lot of library inclusion issues. For example, the glDrawArrays interface, a commonly used interface, has been wrapped by QOpenGLFunctions in Qt.
    • When developing WebGL programs for WASM, you don't need to include any LIBS in the pro file or add header file paths. Qt has already taken care of library inclusion, and we simply need QT += opengl.
    • We can use the same glsl file across all platforms. For WebGL and OpenGL/ES, you might need to add "precision highp float;" at the beginning, but the rest of the code can be the same.
    • WebGL lacks an important feature: setting the line width (glLineWidth), which unfortunately, is not supported by browsers.
    • If you're developing with QML, we can use the same OpenGL context as QML, allowing OpenGL to be drawn at the very bottom or top layer. Qt provides examples for this. You can also use FBO, which is QOpenGLFramebufferObject. Both methods allow you to use OpenGL in your QML programs.

    Here are two small programs related to WASM/OpenGL that I've written for your reference:

    • Rolling waves, modified based on a Qt example: https://web.jasonserver.com:10035/PBViewerDemo/PBViewerDemo.html
    • Using FBO in QML: https://github.com/188080501/JQImageItem
    S 1 Reply Last reply 18 Mar 2024, 11:45
    1
    • J JasonWong has marked this topic as solved on 18 Mar 2024, 02:51
    • J JasonWong
      18 Mar 2024, 02:50

      I've noticed that many people are asking questions related to OpenGL. Based on my experience, I'd like to share some insights to help everyone get started more quickly.

      • In WASM, you can normally develop 3D programs using OpenGL, with the same logic and process as when you develop on the Windows platform or the Android platform. And we only need to adapt to the WASM platform, whether your web is running on x86 Windows or ARM Android.
      • On the WASM platform, we need to use WebGL, not OpenGL. They have similar syntax, but overall, WebGL has been trimmed down and is more streamlined. It's like how we use OpenGL/ES on iOS, which also has fewer features than OpenGL. Of course, for simplicity, you can refer to all these collectively as OpenGL, but be mindful to differentiate them when searching for resources.
      • Although it's called WebGL, at the Qt programming level, we still use the QOpenGLXXX classes.
      • Try to use QOpenGLFunctions instead of directly calling OpenGL functions, as this reduces a lot of library inclusion issues. For example, the glDrawArrays interface, a commonly used interface, has been wrapped by QOpenGLFunctions in Qt.
      • When developing WebGL programs for WASM, you don't need to include any LIBS in the pro file or add header file paths. Qt has already taken care of library inclusion, and we simply need QT += opengl.
      • We can use the same glsl file across all platforms. For WebGL and OpenGL/ES, you might need to add "precision highp float;" at the beginning, but the rest of the code can be the same.
      • WebGL lacks an important feature: setting the line width (glLineWidth), which unfortunately, is not supported by browsers.
      • If you're developing with QML, we can use the same OpenGL context as QML, allowing OpenGL to be drawn at the very bottom or top layer. Qt provides examples for this. You can also use FBO, which is QOpenGLFramebufferObject. Both methods allow you to use OpenGL in your QML programs.

      Here are two small programs related to WASM/OpenGL that I've written for your reference:

      • Rolling waves, modified based on a Qt example: https://web.jasonserver.com:10035/PBViewerDemo/PBViewerDemo.html
      • Using FBO in QML: https://github.com/188080501/JQImageItem
      S Offline
      S Offline
      shome
      wrote on 18 Mar 2024, 11:45 last edited by
      #2

      @JasonWong : Can you kindly provide the link to your rolling waves demo? I need to use it as a boiler plate code.

      J 1 Reply Last reply 19 Mar 2024, 03:13
      0
      • S shome referenced this topic on 18 Mar 2024, 14:01
      • S shome
        18 Mar 2024, 11:45

        @JasonWong : Can you kindly provide the link to your rolling waves demo? I need to use it as a boiler plate code.

        J Offline
        J Offline
        JasonWong
        wrote on 19 Mar 2024, 03:13 last edited by
        #3

        @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 );
        }
        
        1 Reply Last reply
        0

        2/3

        18 Mar 2024, 11:45

        • Login

        • Login or register to search.
        2 out of 3
        • First post
          2/3
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • Users
        • Groups
        • Search
        • Get Qt Extensions
        • Unsolved