Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Game Development
  4. Small examples for game development in Qt, OpenGL, Box2D, Bullet Physics, and OpenAL

Small examples for game development in Qt, OpenGL, Box2D, Bullet Physics, and OpenAL

Scheduled Pinned Locked Moved Game Development
41 Posts 2 Posters 7.2k Views
  • 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.
  • 8Observer88 Offline
    8Observer88 Offline
    8Observer8
    wrote on last edited by 8Observer8
    #9

    Draw a few rectangles with different colors

    I have replaced the following code in the Transformed rectangle example:

        def paintGL(self):
            glClear(GL_COLOR_BUFFER_BIT)
            self.modelMatrix.setToIdentity()
            self.modelMatrix.translate(QVector3D(50, 50, 0))
            self.modelMatrix.rotate(10, QVector3D(0, 0, 1))
            self.modelMatrix.scale(QVector3D(80, 10, 1))
            self.mvpMatrix = self.projViewMatrix * self.modelMatrix
            self.program.setUniformValue(self.uMvpMatrixLocation, self.mvpMatrix)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
    

    with this one:

        def paintGL(self):
            glClear(GL_COLOR_BUFFER_BIT)
            self.drawRectangle(x = 50, y = 50, w = 80, h = 10, angle = 10,
                color = QVector3D(0.62, 0.04, 0.18))
            self.drawRectangle(x = 30, y = 20, w = 50, h = 20, angle = 0,
                color = QVector3D(0.3, 0.07, 0.5))
            self.drawRectangle(x = 50, y = 80, w = 40, h = 15, angle = -20,
                color = QVector3D(0.2, 0.3, 0.1))
    
        def drawRectangle(self, x, y, w, h, angle, color):
            self.modelMatrix.setToIdentity()
            self.modelMatrix.translate(QVector3D(x, y, 0))
            self.modelMatrix.rotate(angle, QVector3D(0, 0, 1))
            self.modelMatrix.scale(QVector3D(w, h, 1))
            self.mvpMatrix = self.projViewMatrix * self.modelMatrix
            self.program.setUniformValue(self.uMvpMatrixLocation, self.mvpMatrix)
            self.program.setUniformValue(self.uColorLocation, color)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
    

    PySide6, Python:

    cbfc2063-187c-454a-a99e-b99ef52c615c-image.png

    import sys
    
    import numpy as np
    from OpenGL.GL import (GL_COLOR_BUFFER_BIT, GL_FLOAT, GL_TRIANGLE_STRIP,
                           glClear, glClearColor, glDrawArrays)
    from PySide6.QtCore import Qt
    from PySide6.QtGui import QMatrix4x4, QSurfaceFormat, QVector3D
    from PySide6.QtOpenGL import (QOpenGLBuffer, QOpenGLShader,
                                  QOpenGLShaderProgram, QOpenGLWindow)
    from PySide6.QtWidgets import QApplication
    
    
    class OpenGLWindow(QOpenGLWindow):
    
        def __init__(self):
            super().__init__()
    
            self.setTitle("OpenGL ES 2.0, PySide6, Python")
            self.initialWindowWidth = 380
            self.initialWindowHeight = 380
            self.resize(self.initialWindowWidth, self.initialWindowHeight)
            self.worldWidth = 100
            self.worldHeight = 100
    
            surfaceFormat = QSurfaceFormat()
            surfaceFormat.setDepthBufferSize(24)
            surfaceFormat.setSamples(4)
            self.setFormat(surfaceFormat)
    
        def initializeGL(self):
            glClearColor(0.04, 0.62, 0.48, 1)
    
            vertShaderSrc = """
                attribute vec2 aPosition;
                uniform mat4 uMvpMatrix;
                void main()
                {
                    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);
                }
            """
    
            fragShaderSrc = """
                #ifdef GL_ES
                precision mediump float;
                #endif
                uniform vec3 uColor;
                void main()
                {
                    gl_FragColor = vec4(uColor, 1.0);
                }
            """
    
            self.program = QOpenGLShaderProgram()
            self.program.addShaderFromSourceCode(QOpenGLShader.ShaderTypeBit.Vertex, vertShaderSrc)
            self.program.addShaderFromSourceCode(QOpenGLShader.ShaderTypeBit.Fragment, fragShaderSrc)
            self.program.link()
            self.program.bind()
    
            vertPositions = np.array([
                -0.5, -0.5,
                0.5, -0.5,
                -0.5, 0.5,
                0.5, 0.5], dtype=np.float32)
            self.vertPosBuffer = QOpenGLBuffer()
            self.vertPosBuffer.create()
            self.vertPosBuffer.bind()
            self.vertPosBuffer.allocate(vertPositions, len(vertPositions) * 4)
            self.program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2)
            self.program.enableAttributeArray("aPosition")
    
            self.uColorLocation = self.program.uniformLocation("uColor")
            self.uMvpMatrixLocation = self.program.uniformLocation("uMvpMatrix")
    
            self.viewMatrix = QMatrix4x4()
            self.viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0),
                QVector3D(0, 1, 0))
    
            self.projMatrix = QMatrix4x4()
            self.projViewMatrix = QMatrix4x4()
            self.modelMatrix = QMatrix4x4()
            self.mvpMatrix = QMatrix4x4()
    
        def resizeGL(self, w, h):
            coofWidth = w / self.initialWindowWidth
            coofHeight = h / self.initialWindowHeight
    
            self.projMatrix.setToIdentity()
            self.projMatrix.ortho(0, self.worldWidth * coofWidth,
                0, self.worldHeight * coofHeight, 1, -1)
            self.projViewMatrix = self.projMatrix * self.viewMatrix
    
        def paintGL(self):
            glClear(GL_COLOR_BUFFER_BIT)
            self.drawRectangle(x = 50, y = 50, w = 80, h = 10, angle = 10,
                color = QVector3D(0.62, 0.04, 0.18))
            self.drawRectangle(x = 30, y = 20, w = 50, h = 20, angle = 0,
                color = QVector3D(0.3, 0.07, 0.5))
            self.drawRectangle(x = 50, y = 80, w = 40, h = 15, angle = -20,
                color = QVector3D(0.2, 0.3, 0.1))
    
        def drawRectangle(self, x, y, w, h, angle, color):
            self.modelMatrix.setToIdentity()
            self.modelMatrix.translate(QVector3D(x, y, 0))
            self.modelMatrix.rotate(angle, QVector3D(0, 0, 1))
            self.modelMatrix.scale(QVector3D(w, h, 1))
            self.mvpMatrix = self.projViewMatrix * self.modelMatrix
            self.program.setUniformValue(self.uMvpMatrixLocation, self.mvpMatrix)
            self.program.setUniformValue(self.uColorLocation, color)
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)
    
    if __name__ == "__main__":
        QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL)
        app = QApplication(sys.argv)
        w = OpenGLWindow()
        w.show()
        sys.exit(app.exec())
    

    Qt6, C++:

    23e91e95-267a-4ea9-9068-c0cb10fa0298-image.png

    main.cpp

    #include <QtGui/QMatrix4x4>
    #include <QtGui/QOpenGLFunctions>
    #include <QtGui/QSurfaceFormat>
    #include <QtGui/QVector3D>
    #include <QtOpenGL/QOpenGLBuffer>
    #include <QtOpenGL/QOpenGLShader>
    #include <QtOpenGL/QOpenGLShaderProgram>
    #include <QtOpenGL/QOpenGLWindow>
    #include <QtWidgets/QApplication>
    
    class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
    {
    public:
        OpenGLWindow()
        {
            setTitle("OpenGL ES 2.0, Qt6, C++");
            resize(380, 380);
    
            QSurfaceFormat surfaceFormat;
            surfaceFormat.setDepthBufferSize(24);
            surfaceFormat.setSamples(4);
            setFormat(surfaceFormat);
        }
    
        void initializeGL() override
        {
            initializeOpenGLFunctions();
            glClearColor(0.04f, 0.62f, 0.48f, 1.f);
    
            QString vertShaderSrc =
                "attribute vec2 aPosition;\n"
                "uniform mat4 uMvpMatrix;"
                "void main()\n"
                "{\n"
                "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                "}\n";
    
            QString fragShaderSrc =
                "#ifdef GL_ES\n"
                "precision mediump float;\n"
                "#endif\n"
                "uniform vec3 uColor;\n"
                "void main()\n"
                "{\n"
                "    gl_FragColor = vec4(uColor, 1.0);\n"
                "}\n";
    
            m_program.create();
            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
            m_program.link();
            m_program.bind();
    
            float vertPositions[] = {
                -0.5f, -0.5f,
                0.5f, -0.5f,
                -0.5f, 0.5f,
                0.5f, 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");
    
            m_uColorLocation = m_program.uniformLocation("uColor");
            m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
            m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
        }
    
        void resizeGL(int w, int h) override
        {
            const float coofWidth = w / (float)m_initialWindowWidth;
            const float coofHeight = h / (float)m_initialWindowHeight;
    
            m_projMatrix.setToIdentity();
            m_projMatrix.ortho(0.f, m_worldWidth * coofWidth,
                0.f, m_worldHeight * coofHeight, 1.f, -1.f);
            m_projViewMatrix = m_projMatrix * m_viewMatrix;
        }
    
        void paintGL() override
        {
            glClear(GL_COLOR_BUFFER_BIT);
            drawRectangle(50, 50, 80, 10, 10, QVector3D(0.62, 0.04, 0.18));
            drawRectangle(30, 20, 50, 20, 0, QVector3D(0.3, 0.07, 0.5));
            drawRectangle(50, 80, 40, 15, -20, QVector3D(0.2, 0.3, 0.1));
        }
    
        void drawRectangle(float x, float y, float w, float h,
            float angle, const QVector3D& color)
        {
            m_modelMatrix.setToIdentity();
            m_modelMatrix.translate(QVector3D(x, y, 0));
            m_modelMatrix.rotate(angle, QVector3D(0, 0, 1));
            m_modelMatrix.scale(QVector3D(w, h, 1));
            m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
            m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
            m_program.setUniformValue(m_uColorLocation, color);
            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        }
    
    private:
        QOpenGLBuffer m_vertPosBuffer;
        QOpenGLShaderProgram m_program;
        int m_uColorLocation;
        int m_uMvpMatrixLocation;
        QMatrix4x4 m_mvpMatrix;
        QMatrix4x4 m_projMatrix;
        QMatrix4x4 m_viewMatrix;
        QMatrix4x4 m_projViewMatrix;
        QMatrix4x4 m_modelMatrix;
        const int m_initialWindowWidth = 380;
        const int m_initialWindowHeight = 380;
        const float m_worldWidth = 100.f;
        const float m_worldHeight = 100.f;
    };
    
    int main(int argc, char *argv[])
    {
        QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
        QApplication app(argc, argv);
        OpenGLWindow w;
        w.show();
        return app.exec();
    }
    

    draw-a-few-rectangles-opengles2-qt6-cpp.pro

    QT += core gui openglwidgets
    
    CONFIG += c++17
    
    SOURCES += \
        main.cpp
    

    WebAssembly demo on the free Netlify hosting

    649cd735-7cd9-4e7a-ad15-a6f69d245acb-image.png

    How it looks on Android 7 with scrcpy:

    e9cdbec2-9f60-491e-99b0-f15bedc07014-image.png

    2f7bcf63-1a99-4e2e-b223-e7f7ec6615ab-image.png

    1 Reply Last reply
    0
    • 8Observer88 Offline
      8Observer88 Offline
      8Observer8
      wrote on last edited by 8Observer8
      #10

      Fit scale

      Scale the game world in the center of the screen.

      WebAssembly demo on the free Netlify hosting

      e655a73d-915a-4fe3-9a32-d86450bff84d-image.png

      scale-the-world-in-the-center-opengles2-pyside6-python.gif

      QOpenGLWidget:

      • PyQt6
      • PySide6
      • Qt6 C++

      QOpenGLWindow:

      • PyQt6
      • PySide6
      • Qt6 C++

      WebGL and JavaScript:

      • Playground
      • Source code

      How it looks on Android:

      ba632ca3-b4d3-415c-97b3-6c738f7cd5f3-image.png

      a353713a-c272-4355-a4ce-cc701aa28ca1-image.png

      1 Reply Last reply
      0
      • 8Observer88 Offline
        8Observer88 Offline
        8Observer8
        wrote on last edited by 8Observer8
        #11

        Place QLabel over QOpenGLWidget

        PySide6, Python:

        fe2ce83d-3eb7-4144-9459-751fa9c9c565-image.png

        main.py

        import sys
        
        from OpenGL.GL import (GL_COLOR_BUFFER_BIT, GL_SCISSOR_TEST, glClear,
                               glClearColor, glDisable, glEnable, glScissor,
                               glViewport)
        from PySide6.QtCore import Qt
        from PySide6.QtGui import QSurfaceFormat
        from PySide6.QtOpenGLWidgets import QOpenGLWidget
        from PySide6.QtWidgets import QApplication, QLabel
        
        
        class OpenGLWidget(QOpenGLWidget):
        
            def __init__(self):
                super().__init__()
        
                self.setWindowTitle("OpenGL ES 2.0, PySide6, Python")
                self.resize(380, 380)
                self.worldWidth = 200
                self.worldHeight = 100
                self.worldAspect = self.worldHeight / self.worldWidth
        
                surfaceFormat = QSurfaceFormat()
                surfaceFormat.setDepthBufferSize(24)
                surfaceFormat.setSamples(4)
                self.setFormat(surfaceFormat)
        
                self.scoreLabel = QLabel("Score: 0", self)
                self.scoreLabel.setStyleSheet("font-size: 24px;")
        
            def initializeGL(self):
                pass
        
            def resizeGL(self, w, h):
                deviceW = w * self.devicePixelRatio()
                deviceH = h * self.devicePixelRatio()
                deviceAspect = deviceH / deviceW
        
                if deviceAspect > self.worldAspect:
                    self.viewportWidth = int(deviceW)
                    self.viewportHeight = int(deviceW * self.worldAspect)
                    self.viewportX = 0
                    self.viewportY = int((deviceH - self.viewportHeight) / 2)
                else:
                    self.viewportWidth = int(deviceH / self.worldAspect)
                    self.viewportHeight = int(deviceH)
                    self.viewportX = int((deviceW - self.viewportWidth) / 2)
                    self.viewportY = 0
        
            def paintGL(self):
                glClearColor(0.2, 0.2, 0.2, 1)
                glClear(GL_COLOR_BUFFER_BIT)
                glViewport(self.viewportX, self.viewportY, self.viewportWidth, self.viewportHeight)
                glScissor(self.viewportX, self.viewportY, self.viewportWidth, self.viewportHeight)
                glClearColor(0.04, 0.62, 0.48, 1)
                glEnable(GL_SCISSOR_TEST)
                glClear(GL_COLOR_BUFFER_BIT)
                glDisable(GL_SCISSOR_TEST)
        
                self.scoreLabel.move(self.viewportX / self.devicePixelRatio() + 10,
                    self.viewportY / self.devicePixelRatio() + 10);
        
        if __name__ == "__main__":
            QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseDesktopOpenGL)
            app = QApplication(sys.argv)
            w = OpenGLWidget()
            w.show()
            sys.exit(app.exec())
        

        Qt6, C++:

        e6099583-2553-492d-965e-a9f63d9f4aeb-image.png

        main.cpp

        #include <QtGui/QOpenGLFunctions>
        #include <QtGui/QSurfaceFormat>
        #include <QtWidgets/QApplication>
        #include <QtWidgets/QLabel>
        #include <QtOpenGLWidgets/QOpenGLWidget>
        
        class OpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions
        {
        public:
            OpenGLWidget()
            {
                setWindowTitle("OpenGL ES 2.0, Qt6, C++");
                resize(380, 380);
        
                QSurfaceFormat surfaceFormat;
                surfaceFormat.setDepthBufferSize(24);
                surfaceFormat.setSamples(4);
                setFormat(surfaceFormat);
        
                m_pScoreLabel = new QLabel("Score: 0", this);
                m_pScoreLabel->setStyleSheet("font-size: 24px;");
            }
        
            void initializeGL() override
            {
                initializeOpenGLFunctions();
            }
        
            void resizeGL(int w, int h) override
            {
                int deviceW = w * devicePixelRatio();
                int deviceH = h * devicePixelRatio();
                float deviceAspect = deviceH / (float) deviceW;
        
                if (deviceAspect > m_worldAspect)
                {
                    m_viewportWidth = deviceW;
                    m_viewportHeight = (int) deviceW * m_worldAspect;
                    m_viewportX = 0;
                    m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                    qDebug() << deviceH << m_viewportHeight << m_viewportY;
                }
                else
                {
                    m_viewportWidth = (int) deviceH / m_worldAspect;
                    m_viewportHeight = deviceH;
                    m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                    m_viewportY = 0;
                }
            }
        
            void paintGL() override
            {
                glClear(GL_COLOR_BUFFER_BIT);
                glClearColor(0.2, 0.2, 0.2, 1);
                glClear(GL_COLOR_BUFFER_BIT);
                glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                glClearColor(0.04, 0.62, 0.48, 1);
                glEnable(GL_SCISSOR_TEST);
                glClear(GL_COLOR_BUFFER_BIT);
                glDisable(GL_SCISSOR_TEST);
        
                m_pScoreLabel->move(m_viewportX / devicePixelRatio() + 10,
                    m_viewportY / devicePixelRatio() + 10);
            }
        
        private:
            const float m_worldWidth = 200.f;
            const float m_worldHeight = 100.f;
            float m_worldAspect = m_worldHeight / m_worldWidth;
            int m_viewportX;
            int m_viewportY;
            int m_viewportWidth;
            int m_viewportHeight;
            QLabel *m_pScoreLabel;
        };
        
        int main(int argc, char *argv[])
        {
            QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
            QApplication app(argc, argv);
            OpenGLWidget w;
            w.show();
            return app.exec();
        }
        

        qlabel-over-qopenglwidget-opengles2-qt6-cpp.pro

        QT += core gui openglwidgets
        
        CONFIG += c++17
        
        SOURCES += \
            main.cpp
        

        It doesn't work on WebAssembly: see demo. Because of this bug: https://bugreports.qt.io/browse/QTBUG-120651 But you can use the patch from the "Gerrit Reviews" (read the comments on the bug report)

        But it works on Android:

        ada173ff-cfc0-4a44-86a5-be4e530c7cc7-image.png

        f7c0e069-3337-4391-8232-cf0676306689-image.png

        1 Reply Last reply
        0
        • BondrusiekB Offline
          BondrusiekB Offline
          Bondrusiek
          wrote on last edited by Bondrusiek
          #12

          @8Observer8 Hi! I tested your example with QOpenGLWindow
          For my Mac I can compile project using :

          QT       += core gui openglwidgets
          

          instead of :

          QT += core gui opengl widgets
          
          win32: LIBS += -lopengl32 # I don't set it for Mac
          

          I think it can be similar on Windows.

          8Observer88 1 Reply Last reply
          1
          • BondrusiekB Bondrusiek

            @8Observer8 Hi! I tested your example with QOpenGLWindow
            For my Mac I can compile project using :

            QT       += core gui openglwidgets
            

            instead of :

            QT += core gui opengl widgets
            
            win32: LIBS += -lopengl32 # I don't set it for Mac
            

            I think it can be similar on Windows.

            8Observer88 Offline
            8Observer88 Offline
            8Observer8
            wrote on last edited by 8Observer8
            #13

            @Bondrusiek said in Small examples for game development in Qt, OpenGL, Box2D, Bullet Physics, and OpenAL:

            I think it can be similar on Windows.

            I confirm that it works on Windows. I'm guessing that the openglwidgets module includes the opengl and widgets modules. I've modified the examples to be the same for QOpenGLWindow and QOpenGLWidget. Thank you very much!

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

            win32: means that it is used on Windows only and it will be ignored on other OS like Android, iOS, macOS and so on. When I use glDrawArrays in separated file and if I don't add this line win32: LIBS += -lopengl32, I have this error on Windows:

            line_drawer.cpp:74: error: undefined reference to `__imp_glDrawArrays'
            

            It can be solved by adding this line of code to pro-file:

            win32: LIBS += -lopengl32
            

            What is interesting, I can delete the line above after recompilation and it will run. But when I change something in the code and recompile it I will have the same error. So the win32: LIBS += -lopengl32 must be in pro-file if you don't call glDrawArrays in the same file.

            1 Reply Last reply
            0
            • 8Observer88 Offline
              8Observer88 Offline
              8Observer8
              wrote on last edited by 8Observer8
              #14

              I have made the next demo for WebAssembly, Android, and Desktop using: Qt C++, OpenGL ES 2.0, OpenAL-Soft (this is a library for music and sounds), Box2D (for jumps, collision detections, and ray casting), Hiero (this is an application to create a font with distance field from TTF), Free Texture Packer (to pack images to one texture atlas), and Tiled map editor (to position sprites and Box2D static colliders).

              • Click to run in your browser (it is a link to itch where you can download EXE for Windows 10 64 bit and APK for Android 7-14)
              • Click to run in your browser (it is a link to the Netlify free hosting)

              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

              I have made a custom joystick for Android in pure OpenGL ES 2.0 (this is an animation from the real phone that I made using scrcpy):

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

              1 Reply Last reply
              0
              • 8Observer88 Offline
                8Observer88 Offline
                8Observer8
                wrote on last edited by
                #15

                Setting English as system language

                If a user system language is not English it will not work:

                void OpenGLWindow::keyPressEvent(QKeyEvent *event)
                {
                    switch (event->key())
                    {
                        case Qt::Key::Key_W:
                        case Qt::Key::Key_Up:
                        {
                                break;
                        {
                

                The following command is a solution for Windows. You can set English as system language:

                OpenGLWindow::OpenGLWindow()
                {
                    setTitle("OpenGL ES 2.0, Qt6, C++");
                    resize(400, 400);
                
                // Set English as system language
                #ifdef _WIN32
                    PostMessage(GetForegroundWindow(), WM_INPUTLANGCHANGEREQUEST, 1, 0x04090409);
                #endif
                

                You don't need to include <windows.h> because Qt is included it by default:

                #ifdef _WIN32
                #include <windows.h>
                #endif
                
                1 Reply Last reply
                0
                • 8Observer88 Offline
                  8Observer88 Offline
                  8Observer8
                  wrote on last edited by 8Observer8
                  #16

                  Printing OpenGL version to the Debug console

                  The following commands print OpenGL and GLSL version and vendor:

                  qDebug() << "OpenGL version:" << (const char*) glGetString(GL_VERSION);
                  qDebug() << "GLSL version: " << (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
                  qDebug() << "Vendor: " << (const char*) glGetString(GL_VENDOR);
                  

                  or

                  std::cout << "OpenGL version: " << glGetString(GL_VERSION) << std::endl;
                  std::cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl;
                  std::cout << "Vendor: " << glGetString(GL_VENDOR) << std::endl;
                  

                  Qt by default runs programs with integrated video card on laptop:

                  OpenGL version: 3.1.0 - Build 9.17.10.4459
                  GLSL version:  1.40 - Intel Build 9.17.10.4459
                  Vendor:  Intel
                  
                  1 Reply Last reply
                  0
                  • 8Observer88 Offline
                    8Observer88 Offline
                    8Observer8
                    wrote on last edited by 8Observer8
                    #17

                    Loading 3D models from DAE COLLADA

                    This example shows how to parse XML (.dae) using QDomDocument. It was tested on Android 7.1.1, Windows 10, and WebAssembly.

                    • Click this link to run the demo in your browser
                    • QOpenGLWindow: Source code on GitHub
                    • QOpenGLWidget: Source code on GitHub

                    Note. antialiasing works for WebAssembly with QOpenGLWindow for Qt 6.6.3 but it doesn't work for QOpenGLWidget. It was fixed in Qt 6.7.0. See the bug report: https://bugreports.qt.io/browse/QTBUG-123816

                    fd06b132-c804-445f-ac4f-bb91687ff5aa-image.png

                    1 Reply Last reply
                    0
                    • 8Observer88 Offline
                      8Observer88 Offline
                      8Observer8
                      wrote on last edited by 8Observer8
                      #18

                      Pick color of a pixel with glReadPixels by mouse click or by touching on Mobile

                      glReadPixels requires the following parameters:

                      GLubyte pixel[4];
                      glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
                      

                      Where m_mouseX and m_mouseY are the mouse click coordinates. You should recalculate them before of calling glReadPixels because glReadPixels uses bottom left corner as (0, 0) but Qt uses top left corner as (0, 0). You should add QWindow::devicePixelRatio() because Windows has devicePixelRatio = 1 but Android and macOS (maybe) has devicePixelRatio = 2:

                      void mousePressEvent(QMouseEvent *event) override
                      {
                          m_mouseX = event->pos().x() * devicePixelRatio();
                          m_mouseY = (height() - event->pos().y() - 1) * devicePixelRatio();
                          m_mouseClicked = true;
                          update();
                      }
                      

                      pick-color-with-mouse-opengles2-qt6-cpp.gif

                      pick-color-of-simple-triangle-qopenglwindow-qt6-cpp.pro

                      QT += core gui openglwidgets
                      
                      CONFIG += c++17
                      
                      SOURCES += \
                          main.cpp
                      

                      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
                      {
                      public:
                          OpenGLWindow()
                          {
                              setTitle("OpenGL ES 2.0, Qt6, C++");
                              resize(380, 380);
                          }
                      
                      private:
                          void initializeGL() override
                          {
                              initializeOpenGLFunctions();
                              glClearColor(0.2f, 0.2f, 0.2f, 1.f);
                              qDebug() << "Device pixel ratio:" << devicePixelRatio();
                      
                              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);
                                  // Print a color
                                  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() * devicePixelRatio();
                              m_mouseY = (height() - event->pos().y() - 1) * devicePixelRatio();
                              m_mouseClicked = true;
                              update();
                          }
                      
                      private:
                          int m_mouseX;
                          int m_mouseY;
                          bool m_mouseClicked = false;
                          QOpenGLBuffer m_vertPosBuffer;
                          QOpenGLShaderProgram m_program;
                      };
                      
                      int main(int argc, char *argv[])
                      {
                          QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                          QApplication app(argc, argv);
                          OpenGLWindow w;
                          w.show();
                          return app.exec();
                      }
                      
                      1 Reply Last reply
                      0
                      • 8Observer88 Offline
                        8Observer88 Offline
                        8Observer8
                        wrote on last edited by 8Observer8
                        #19

                        Perspective camera

                        1273b633-a79a-41c0-bab9-16adca1581ac-image.png

                        perspective-camera-opengles2-qt6-cpp.pro

                        QT += core gui openglwidgets
                        
                        CONFIG += c++17
                        
                        SOURCES += \
                            main.cpp
                        

                        main.cpp

                        #include <QtGui/QMatrix4x4>
                        #include <QtGui/QOpenGLFunctions>
                        #include <QtGui/QSurfaceFormat>
                        #include <QtGui/QVector3D>
                        #include <QtOpenGL/QOpenGLBuffer>
                        #include <QtOpenGL/QOpenGLShader>
                        #include <QtOpenGL/QOpenGLShaderProgram>
                        #include <QtOpenGL/QOpenGLWindow>
                        #include <QtWidgets/QApplication>
                        
                        class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                        {
                        public:
                            OpenGLWindow()
                            {
                                setTitle("OpenGL ES 2.0, Qt6, C++");
                                resize(500, 500);
                        
                                QSurfaceFormat surfaceFormat;
                                surfaceFormat.setDepthBufferSize(24);
                                surfaceFormat.setSamples(4);
                                setFormat(surfaceFormat);
                            }
                        
                            void initializeGL() override
                            {
                                initializeOpenGLFunctions();
                                glClearColor(153.f/255.f, 220.f/255.f, 236.f/255.f, 1.f);
                        
                                QString vertShaderSrc =
                                    "attribute vec2 aPosition;\n"
                                    "uniform mat4 uMvpMatrix;"
                                    "void main()\n"
                                    "{\n"
                                    "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                    "}\n";
                        
                                QString fragShaderSrc =
                                    "#ifdef GL_ES\n"
                                    "precision mediump float;\n"
                                    "#endif\n"
                                    "void main()\n"
                                    "{\n"
                                    "    gl_FragColor = vec4(0.058, 0.615, 0.345, 1.0);\n"
                                    "}\n";
                        
                                m_program.create();
                                m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                m_program.link();
                                m_program.bind();
                        
                                float vertPositions[] = {
                                    -0.5f, -0.5f,
                                    0.5f, -0.5f,
                                    -0.5f, 0.5f,
                                    0.5f, 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");
                        
                                m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
                                m_viewMatrix.lookAt(QVector3D(0, 3, 5), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                            }
                        
                            void resizeGL(int w, int h) override
                            {
                                m_projMatrix.setToIdentity();
                                m_projMatrix.perspective(50.f, w / (float) h, 0.1f, 100.f);
                                m_projViewMatrix = m_projMatrix * m_viewMatrix;
                            }
                        
                            void paintGL() override
                            {
                                glClear(GL_COLOR_BUFFER_BIT);
                                m_modelMatrix.setToIdentity();
                                m_modelMatrix.translate(QVector3D(0, 0, 0));
                                m_modelMatrix.rotate(90, QVector3D(1, 0, 0));
                                m_modelMatrix.scale(QVector3D(3, 3, 1));
                                m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                            }
                        
                        private:
                            QOpenGLBuffer m_vertPosBuffer;
                            QOpenGLShaderProgram m_program;
                            int m_uMvpMatrixLocation;
                            QMatrix4x4 m_mvpMatrix;
                            QMatrix4x4 m_projMatrix;
                            QMatrix4x4 m_viewMatrix;
                            QMatrix4x4 m_projViewMatrix;
                            QMatrix4x4 m_modelMatrix;
                        };
                        
                        int main(int argc, char *argv[])
                        {
                            QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                            QApplication app(argc, argv);
                            OpenGLWindow w;
                            w.show();
                            return app.exec();
                        }
                        
                        1 Reply Last reply
                        0
                        • 8Observer88 Offline
                          8Observer88 Offline
                          8Observer8
                          wrote on last edited by
                          #20

                          Rotate and zoom camera

                          Click here to test WebAssembly demo in the browser

                          rotate-and-zoom-camera-opengles2-qt6-cpp-desktop.gif

                          On Android only rotation works. Some work must be made with touch events for zooming:

                          rotate-and-zoom-camera-opengles2-qt6-cpp.gif

                          rotate-and-zoom-camera-opengles2-qt6-cpp.pro

                          QT += core gui openglwidgets
                          
                          CONFIG += c++17
                          
                          SOURCES += \
                              main.cpp
                          

                          main.cpp

                          #include <QtGui/QMatrix4x4>
                          #include <QtGui/QOpenGLFunctions>
                          #include <QtGui/QSurfaceFormat>
                          #include <QtGui/QVector3D>
                          #include <QtGui/QMouseEvent>
                          #include <QtOpenGL/QOpenGLBuffer>
                          #include <QtOpenGL/QOpenGLShader>
                          #include <QtOpenGL/QOpenGLShaderProgram>
                          #include <QtOpenGL/QOpenGLWindow>
                          #include <QtWidgets/QApplication>
                          
                          class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                          {
                          public:
                              OpenGLWindow()
                              {
                                  setTitle("OpenGL ES 2.0, Qt6, C++");
                                  resize(500, 500);
                                  m_degreesPerPixelX = 90.f / (float) width();
                                  m_degreesPerPixelY = 180.f / (float) height();
                          
                                  QSurfaceFormat surfaceFormat;
                                  surfaceFormat.setDepthBufferSize(24);
                                  surfaceFormat.setSamples(4);
                                  setFormat(surfaceFormat);
                              }
                          
                              void initializeGL() override
                              {
                                  initializeOpenGLFunctions();
                                  glClearColor(153.f/255.f, 220.f/255.f, 236.f/255.f, 1.f);
                          
                                  QString vertShaderSrc =
                                      "attribute vec2 aPosition;\n"
                                      "uniform mat4 uMvpMatrix;"
                                      "void main()\n"
                                      "{\n"
                                      "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                      "}\n";
                          
                                  QString fragShaderSrc =
                                      "#ifdef GL_ES\n"
                                      "precision mediump float;\n"
                                      "#endif\n"
                                      "void main()\n"
                                      "{\n"
                                      "    gl_FragColor = vec4(0.058, 0.615, 0.345, 1.0);\n"
                                      "}\n";
                          
                                  m_program.create();
                                  m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                  m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                  m_program.link();
                                  m_program.bind();
                          
                                  float vertPositions[] = {
                                      -0.5f, -0.5f,
                                      0.5f, -0.5f,
                                      -0.5f, 0.5f,
                                      0.5f, 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");
                          
                                  m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
                                  m_viewMatrix = getViewMatrix();
                              }
                          
                              void resizeGL(int w, int h) override
                              {
                                  m_projMatrix.setToIdentity();
                                  m_projMatrix.perspective(50.f, w / (float)h, 0.1f, 100.f);
                              }
                          
                              void paintGL() override
                              {
                                  glClear(GL_COLOR_BUFFER_BIT);
                                  m_modelMatrix.setToIdentity();
                                  m_modelMatrix.translate(QVector3D(0, 0, 0));
                                  m_modelMatrix.rotate(90, QVector3D(1, 0, 0));
                                  m_modelMatrix.scale(QVector3D(3, 3, 1));
                                  m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                  m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                  m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                  glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                              }
                          
                              void mousePressEvent(QMouseEvent *event) override
                              {
                                  switch (event->button())
                                  {
                                      case Qt::MouseButton::LeftButton:
                                      {
                                          if (m_mouseHolding)
                                              return;
                          
                                          m_mouseHolding = true;
                                          m_mousePrevX = (float) event->pos().x();
                                          m_mousePrevY = (float) event->pos().y();
                                          break;
                                      }
                                      default:
                                          break;
                                  }
                              }
                          
                              void mouseMoveEvent(QMouseEvent *event) override
                              {
                                  if (!m_mouseHolding)
                                      return;
                          
                                  float x = (float) event->pos().x();
                                  float y = (float) event->pos().y();
                          
                                  float newCameraRotX = m_cameraRotX + m_degreesPerPixelX * (y - m_mousePrevY);
                                  newCameraRotX = qMax(-85.f, qMin(85.f, newCameraRotX));
                                  float newCameraRotY = m_cameraRotY + m_degreesPerPixelY * (x - m_mousePrevX);
                                  m_mousePrevX = x;
                                  m_mousePrevY = y;
                                  m_cameraRotX = newCameraRotX;
                                  m_cameraRotY = newCameraRotY;
                          
                                  m_viewMatrix = getViewMatrix();
                                  update();
                              }
                          
                              void mouseReleaseEvent(QMouseEvent *event) override
                              {
                                  Q_UNUSED(event);
                                  m_mouseHolding = false;
                              }
                          
                              void wheelEvent(QWheelEvent *event) override
                              {
                                  float delta = event->angleDelta().y();
                                  m_viewDistance += -delta / 500.f;
                                  m_viewMatrix = getViewMatrix();
                                  update();
                              }
                          
                              QMatrix4x4 getViewMatrix()
                              {
                                  QMatrix4x4 mat;
                          
                                  const float cosX = qCos(m_cameraRotX / 180.f * M_PI);
                                  const float sinX = qSin(m_cameraRotX / 180.f * M_PI);
                                  const float cosY = qCos(m_cameraRotY / 180.f * M_PI);
                                  const float sinY = qSin(m_cameraRotY / 180.f * M_PI);
                          
                                  mat.setColumn(0, QVector4D(cosY, sinX * sinY, -cosX * sinY, 0.f));
                                  mat.setColumn(1, QVector4D(0.f, cosX, sinX, 0.f));
                                  mat.setColumn(2, QVector4D(sinY, -sinX * cosY, cosX * cosY, 0.f));
                                  mat.setColumn(3, QVector4D(0, 0, -m_viewDistance, 1.f));
                          
                                  return mat;
                              }
                          
                          private:
                              QOpenGLBuffer m_vertPosBuffer;
                              QOpenGLShaderProgram m_program;
                              int m_uMvpMatrixLocation;
                              QMatrix4x4 m_mvpMatrix;
                              QMatrix4x4 m_projMatrix;
                              QMatrix4x4 m_viewMatrix;
                              QMatrix4x4 m_projViewMatrix;
                              QMatrix4x4 m_modelMatrix;
                              bool m_mouseHolding = false;
                              float m_mousePrevX = 0.f;
                              float m_mousePrevY = 0.f;
                              float m_cameraRotX = 30.f;
                              float m_cameraRotY = 0.f;
                              float m_viewDistance = 5.f;
                              float m_degreesPerPixelX;
                              float m_degreesPerPixelY;
                          };
                          
                          int main(int argc, char *argv[])
                          {
                              QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                              QApplication app(argc, argv);
                              OpenGLWindow w;
                              w.show();
                              return app.exec();
                          }
                          
                          1 Reply Last reply
                          0
                          • 8Observer88 Offline
                            8Observer88 Offline
                            8Observer8
                            wrote on last edited by 8Observer8
                            #21

                            A circle (disk) is inscribed in a square

                            WebAssembly demo on free Netlify hosting

                            7839944d-05e1-4f20-881c-5ad2e41d8519-image.png

                            disk-opengles2-qt6-cpp.pro

                            QT += core gui openglwidgets
                            
                            CONFIG += c++17
                            
                            SOURCES += \
                                main.cpp
                            

                            main.cpp

                            #include <QtMath>
                            #include <QtGui/QMatrix4x4>
                            #include <QtGui/QOpenGLFunctions>
                            #include <QtGui/QSurfaceFormat>
                            #include <QtGui/QVector3D>
                            #include <QtOpenGL/QOpenGLBuffer>
                            #include <QtOpenGL/QOpenGLShader>
                            #include <QtOpenGL/QOpenGLShaderProgram>
                            #include <QtOpenGL/QOpenGLWindow>
                            #include <QtWidgets/QApplication>
                            
                            class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                            {
                            public:
                                OpenGLWindow()
                                {
                                    setTitle("OpenGL ES 2.0, Qt6, C++");
                                    resize(380, 380);
                            
                                    QSurfaceFormat surfaceFormat;
                                    surfaceFormat.setDepthBufferSize(24);
                                    surfaceFormat.setSamples(4);
                                    setFormat(surfaceFormat);
                                }
                            
                                void initializeGL() override
                                {
                                    initializeOpenGLFunctions();
                                    glClearColor(0.04f, 0.62f, 0.48f, 1.f);
                            
                                    QString vertShaderSrc =
                                        "attribute vec2 aPosition;\n"
                                        "uniform mat4 uMvpMatrix;"
                                        "void main()\n"
                                        "{\n"
                                        "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                        "}\n";
                            
                                    QString fragShaderSrc =
                                        "#ifdef GL_ES\n"
                                        "precision mediump float;\n"
                                        "#endif\n"
                                        "uniform vec3 uColor;\n"
                                        "void main()\n"
                                        "{\n"
                                        "    gl_FragColor = vec4(uColor, 1.0);\n"
                                        "}\n";
                            
                                    m_program.create();
                                    m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                    m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                    m_program.link();
                                    m_program.bind();
                            
                                    float vertPositions[m_amountOfDiskVertices * 2 + 8]; // Disk + Square
                                    float radius = 0.5f;
                                    float angle = 0.f;
                            
                                    int index = 0;
                                    // Disk center
                                    vertPositions[index++] = 0.f;
                                    vertPositions[index++] = 0.f;
                            
                                    // Disk
                                    for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
                                    {
                                        float radians = qDegreesToRadians(angle);
                                        float x = radius * qCos(radians);
                                        float y = radius * qSin(radians);
                                        vertPositions[index++] = x;
                                        vertPositions[index++] = y;
                                        angle += m_angleStep;
                                    }
                                    // Square
                                    vertPositions[index++] = -0.5f;
                                    vertPositions[index++] = -0.5f;
                                    vertPositions[index++] = 0.5f;
                                    vertPositions[index++] = -0.5f;
                                    vertPositions[index++] = -0.5f;
                                    vertPositions[index++] = 0.5f;
                                    vertPositions[index++] = 0.5f;
                                    vertPositions[index++] = 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");
                            
                                    m_uColorLocation = m_program.uniformLocation("uColor");
                                    m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
                                    m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                }
                            
                                void resizeGL(int w, int h) override
                                {
                                    int deviceW = w * devicePixelRatio();
                                    int deviceH = h * devicePixelRatio();
                                    float deviceAspect = deviceH / (float) deviceW;
                            
                                    if (deviceAspect > m_worldAspect)
                                    {
                                        m_viewportWidth = deviceW;
                                        m_viewportHeight = (int) deviceW * m_worldAspect;
                                        m_viewportX = 0;
                                        m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                    }
                                    else
                                    {
                                        m_viewportWidth = (int) deviceH / m_worldAspect;
                                        m_viewportHeight = deviceH;
                                        m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                        m_viewportY = 0;
                                    }
                                    m_projMatrix.setToIdentity();
                                    m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                    m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                }
                            
                                void paintGL() override
                                {
                                    glClear(GL_COLOR_BUFFER_BIT);
                                    glClearColor(0.2, 0.2, 0.2, 1);
                                    glClear(GL_COLOR_BUFFER_BIT);
                                    glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                    glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                    glClearColor(0.04, 0.62, 0.48, 1);
                                    glEnable(GL_SCISSOR_TEST);
                                    glClear(GL_COLOR_BUFFER_BIT);
                                    glDisable(GL_SCISSOR_TEST);
                            
                                    // Square
                                    drawRectangle(100, 50, 50, 50, 0, QVector3D(0.3, 0.07, 0.5));
                                    // Disk
                                    drawDisk(100, 50, 50, QVector3D(0.8, 0.8, 0.5));
                                    // Left border
                                    drawRectangle(5, 50, 5, 85, 0, QVector3D(0.62, 0.04, 0.18));
                                    // Right border
                                    drawRectangle(195, 50, 5, 85, 0, QVector3D(0.62, 0.04, 0.18));
                                    // Top border
                                    drawRectangle(100, 95, 185, 5, 0, QVector3D(0.62, 0.04, 0.18));
                                    // Bottom border
                                    drawRectangle(100, 5, 185, 5, 0, QVector3D(0.62, 0.04, 0.18));
                                }
                            
                                void drawDisk(float x, float y, float diameter, const QVector3D& color)
                                {
                                    m_modelMatrix.setToIdentity();
                                    m_modelMatrix.translate(QVector3D(x, y, 0));
                                    m_modelMatrix.scale(QVector3D(diameter, diameter, 1));
                                    m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                    m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                    m_program.setUniformValue(m_uColorLocation, color);
                                    glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
                                }
                            
                                void drawRectangle(float x, float y, float w, float h,
                                    float angle, const QVector3D& color)
                                {
                                    m_modelMatrix.setToIdentity();
                                    m_modelMatrix.translate(QVector3D(x, y, 0));
                                    m_modelMatrix.rotate(angle, QVector3D(0, 0, 1));
                                    m_modelMatrix.scale(QVector3D(w, h, 1));
                                    m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                    m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                    m_program.setUniformValue(m_uColorLocation, color);
                                    glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
                                }
                            
                            private:
                                QOpenGLBuffer m_vertPosBuffer;
                                QOpenGLShaderProgram m_program;
                                int m_uColorLocation;
                                int m_uMvpMatrixLocation;
                                QMatrix4x4 m_mvpMatrix;
                                QMatrix4x4 m_projMatrix;
                                QMatrix4x4 m_viewMatrix;
                                QMatrix4x4 m_projViewMatrix;
                                QMatrix4x4 m_modelMatrix;
                                const float m_worldWidth = 200.f;
                                const float m_worldHeight = 100.f;
                                float m_worldAspect = m_worldHeight / m_worldWidth;
                                int m_viewportX;
                                int m_viewportY;
                                int m_viewportWidth;
                                int m_viewportHeight;
                                float m_angleStep = 10.f;
                                int m_amountOfDiskVertices = 360.f / m_angleStep + 2;
                            };
                            
                            int main(int argc, char *argv[])
                            {
                                QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                QApplication app(argc, argv);
                                OpenGLWindow w;
                                w.show();
                                return app.exec();
                            }
                            
                            1 Reply Last reply
                            0
                            • 8Observer88 Offline
                              8Observer88 Offline
                              8Observer8
                              wrote on last edited by 8Observer8
                              #22

                              Moving a disk by mouse and touching

                              WebAssembly demo on free Netlify hosting

                              move-disk-by-mouse-and-touching-opengles2-qt6-cpp-android.gif

                              move-disk-by-mouse-and-touching-opengles2-qt6-cpp-desktop.gif

                              move-disk-by-mouse-and-touching-opengles2-qt6-cpp.pro

                              QT += core gui openglwidgets
                              
                              CONFIG += c++17
                              
                              SOURCES += \
                                  main.cpp
                              

                              main.cpp

                              #include <QtMath>
                              #include <QtGui/QMatrix4x4>
                              #include <QtGui/QMouseEvent>
                              #include <QtGui/QOpenGLFunctions>
                              #include <QtGui/QSurfaceFormat>
                              #include <QtGui/QVector3D>
                              #include <QtOpenGL/QOpenGLBuffer>
                              #include <QtOpenGL/QOpenGLShader>
                              #include <QtOpenGL/QOpenGLShaderProgram>
                              #include <QtOpenGL/QOpenGLWindow>
                              #include <QtWidgets/QApplication>
                              
                              class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                              {
                              public:
                                  OpenGLWindow()
                                  {
                                      setTitle("OpenGL ES 2.0, Qt6, C++");
                                      resize(380, 380);
                              
                                      QSurfaceFormat surfaceFormat;
                                      surfaceFormat.setDepthBufferSize(24);
                                      surfaceFormat.setSamples(4);
                                      setFormat(surfaceFormat);
                                  }
                              
                                  void initializeGL() override
                                  {
                                      initializeOpenGLFunctions();
                                      glClearColor(0.04f, 0.62f, 0.48f, 1.f);
                              
                                      QString vertShaderSrc =
                                          "attribute vec2 aPosition;\n"
                                          "uniform mat4 uMvpMatrix;"
                                          "void main()\n"
                                          "{\n"
                                          "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                          "}\n";
                              
                                      QString fragShaderSrc =
                                          "#ifdef GL_ES\n"
                                          "precision mediump float;\n"
                                          "#endif\n"
                                          "uniform vec3 uColor;\n"
                                          "void main()\n"
                                          "{\n"
                                          "    gl_FragColor = vec4(uColor, 1.0);\n"
                                          "}\n";
                              
                                      m_program.create();
                                      m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                      m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                      m_program.link();
                                      m_program.bind();
                              
                                      float vertPositions[m_amountOfDiskVertices * 2 + 8]; // Disk + Square
                                      float radius = 0.5f;
                                      float angle = 0.f;
                              
                                      int index = 0;
                                      // Disk center
                                      vertPositions[index++] = 0.f;
                                      vertPositions[index++] = 0.f;
                              
                                      // Disk
                                      for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
                                      {
                                          float radians = qDegreesToRadians(angle);
                                          float x = radius * qCos(radians);
                                          float y = radius * qSin(radians);
                                          vertPositions[index++] = x;
                                          vertPositions[index++] = y;
                                          angle += m_angleStep;
                                      }
                                      // Square
                                      vertPositions[index++] = -0.5f;
                                      vertPositions[index++] = -0.5f;
                                      vertPositions[index++] = 0.5f;
                                      vertPositions[index++] = -0.5f;
                                      vertPositions[index++] = -0.5f;
                                      vertPositions[index++] = 0.5f;
                                      vertPositions[index++] = 0.5f;
                                      vertPositions[index++] = 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");
                              
                                      m_uColorLocation = m_program.uniformLocation("uColor");
                                      m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
                                      m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                  }
                              
                                  void resizeGL(int w, int h) override
                                  {
                                      int deviceW = w * devicePixelRatio();
                                      int deviceH = h * devicePixelRatio();
                                      float deviceAspect = deviceH / (float) deviceW;
                              
                                      if (deviceAspect > m_worldAspect)
                                      {
                                          m_viewportWidth = deviceW;
                                          m_viewportHeight = (int) deviceW * m_worldAspect;
                                          m_viewportX = 0;
                                          m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                      }
                                      else
                                      {
                                          m_viewportWidth = (int) deviceH / m_worldAspect;
                                          m_viewportHeight = deviceH;
                                          m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                          m_viewportY = 0;
                                      }
                                      m_projMatrix.setToIdentity();
                                      m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                      m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                  }
                              
                                  void paintGL() override
                                  {
                                      glClear(GL_COLOR_BUFFER_BIT);
                                      glClearColor(0.2, 0.2, 0.2, 1);
                                      glClear(GL_COLOR_BUFFER_BIT);
                                      glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                      glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                      glClearColor(0.04, 0.62, 0.48, 1);
                                      glEnable(GL_SCISSOR_TEST);
                                      glClear(GL_COLOR_BUFFER_BIT);
                                      glDisable(GL_SCISSOR_TEST);
                              
                                      // Square
                                      drawRectangle(100, 50, 50, 50, 0, QVector3D(0.3, 0.07, 0.5));
                                      // Disk
                                      drawDisk(m_diskPosX, m_diskPosY, 50, QVector3D(0.8, 0.8, 0.5));
                                      // Left border
                                      drawRectangle(5, 50, 5, 85, 0, QVector3D(0.62, 0.04, 0.18));
                                      // Right border
                                      drawRectangle(195, 50, 5, 85, 0, QVector3D(0.62, 0.04, 0.18));
                                      // Top border
                                      drawRectangle(100, 95, 185, 5, 0, QVector3D(0.62, 0.04, 0.18));
                                      // Bottom border
                                      drawRectangle(100, 5, 185, 5, 0, QVector3D(0.62, 0.04, 0.18));
                                  }
                              
                                  void drawDisk(float x, float y, float diameter, const QVector3D& color)
                                  {
                                      m_modelMatrix.setToIdentity();
                                      m_modelMatrix.translate(QVector3D(x, y, 0));
                                      m_modelMatrix.scale(QVector3D(diameter, diameter, 1));
                                      m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                      m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                      m_program.setUniformValue(m_uColorLocation, color);
                                      glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
                                  }
                              
                                  void drawRectangle(float x, float y, float w, float h,
                                      float angle, const QVector3D& color)
                                  {
                                      m_modelMatrix.setToIdentity();
                                      m_modelMatrix.translate(QVector3D(x, y, 0));
                                      m_modelMatrix.rotate(angle, QVector3D(0, 0, 1));
                                      m_modelMatrix.scale(QVector3D(w, h, 1));
                                      m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                      m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                      m_program.setUniformValue(m_uColorLocation, color);
                                      glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
                                  }
                              
                                  void mousePressEvent(QMouseEvent *event) override
                                  {
                                      switch (event->button()) {
                                          case Qt::MouseButton::LeftButton:
                                          {
                                              m_mouseHolding = true;
                                              int x = event->pos().x() * devicePixelRatio();
                                              int y = (height() - event->pos().y() - 1) * devicePixelRatio();
                                              if ((m_viewportX <= x && x < (m_viewportX + m_viewportWidth)) &&
                                                  (m_viewportY <= y && y < (m_viewportY + m_viewportHeight)))
                                              {
                                                  float normalizedX = (x - m_viewportX) / (float) m_viewportWidth;
                                                  float normalizedY = (y - m_viewportY) / (float) m_viewportHeight;
                                                  m_diskPosX = m_worldWidth * normalizedX;
                                                  m_diskPosY = m_worldHeight * normalizedY;
                                              }
                                              update();
                                              break;
                                          }
                                          default:
                                              break;
                                      }
                                  }
                              
                                  void mouseMoveEvent(QMouseEvent *event) override
                                  {
                                      if (!m_mouseHolding)
                                          return;
                              
                                      int x = event->pos().x() * devicePixelRatio();
                                      int y = (height() - event->pos().y() - 1) * devicePixelRatio();
                                      if ((m_viewportX <= x && x < (m_viewportX + m_viewportWidth)) &&
                                          (m_viewportY <= y && y < (m_viewportY + m_viewportHeight)))
                                      {
                                          float normalizedX = (x - m_viewportX) / (float) m_viewportWidth;
                                          float normalizedY = (y - m_viewportY) / (float) m_viewportHeight;
                                          m_diskPosX = m_worldWidth * normalizedX;
                                          m_diskPosY = m_worldHeight * normalizedY;
                                      }
                                      update();
                                  }
                              
                                  void mouseReleaseEvent(QMouseEvent *event) override
                                  {
                                      switch (event->button()) {
                                          case Qt::MouseButton::LeftButton:
                                          {
                                              m_mouseHolding = false;
                                              break;
                                          }
                                          default:
                                              break;
                                      }
                                  }
                              
                              private:
                                  QOpenGLBuffer m_vertPosBuffer;
                                  QOpenGLShaderProgram m_program;
                                  int m_uColorLocation;
                                  int m_uMvpMatrixLocation;
                                  QMatrix4x4 m_mvpMatrix;
                                  QMatrix4x4 m_projMatrix;
                                  QMatrix4x4 m_viewMatrix;
                                  QMatrix4x4 m_projViewMatrix;
                                  QMatrix4x4 m_modelMatrix;
                                  const float m_worldWidth = 200.f;
                                  const float m_worldHeight = 100.f;
                                  float m_worldAspect = m_worldHeight / m_worldWidth;
                                  int m_viewportX;
                                  int m_viewportY;
                                  int m_viewportWidth;
                                  int m_viewportHeight;
                                  float m_angleStep = 10.f;
                                  int m_amountOfDiskVertices = 360.f / m_angleStep + 2;
                                  bool m_mouseHolding = false;
                                  float m_diskPosX = 100.f;
                                  float m_diskPosY = 50.f;
                              };
                              
                              int main(int argc, char *argv[])
                              {
                                  QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                  QApplication app(argc, argv);
                                  OpenGLWindow w;
                                  w.show();
                                  return app.exec();
                              }
                              
                              1 Reply Last reply
                              0
                              • 8Observer88 Offline
                                8Observer88 Offline
                                8Observer8
                                wrote on last edited by
                                #23

                                Custom collision detection between two disks

                                WebAssembly demo on free Netlify hosting

                                custom-collision-detection-disks-opengles2-qt6-cpp-android.gif

                                custom-collision-detection-disks-opengles2-qt6-cpp-desktop.gif

                                custom-collision-detection-disks-opengles2-qt6-cpp.pro

                                QT += core gui openglwidgets
                                
                                CONFIG += c++17
                                
                                SOURCES += \
                                    main.cpp
                                

                                main.cpp

                                
                                #include <QtMath>
                                #include <QtGui/QMatrix4x4>
                                #include <QtGui/QMouseEvent>
                                #include <QtGui/QOpenGLFunctions>
                                #include <QtGui/QSurfaceFormat>
                                #include <QtGui/QVector3D>
                                #include <QtGui/QVector4D>
                                #include <QtOpenGL/QOpenGLBuffer>
                                #include <QtOpenGL/QOpenGLShader>
                                #include <QtOpenGL/QOpenGLShaderProgram>
                                #include <QtOpenGL/QOpenGLWindow>
                                #include <QtWidgets/QApplication>
                                
                                class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                {
                                public:
                                    OpenGLWindow()
                                    {
                                        setTitle("OpenGL ES 2.0, Qt6, C++");
                                        resize(500, 500);
                                
                                        QSurfaceFormat surfaceFormat;
                                        surfaceFormat.setDepthBufferSize(24);
                                        surfaceFormat.setSamples(4);
                                        setFormat(surfaceFormat);
                                    }
                                
                                    void initializeGL() override
                                    {
                                        initializeOpenGLFunctions();
                                        glClearColor(0.04f, 0.62f, 0.48f, 1.f);
                                        glEnable(GL_BLEND);
                                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                                
                                        QString vertShaderSrc =
                                            "attribute vec2 aPosition;\n"
                                            "uniform mat4 uMvpMatrix;"
                                            "void main()\n"
                                            "{\n"
                                            "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                            "}\n";
                                
                                        QString fragShaderSrc =
                                            "#ifdef GL_ES\n"
                                            "precision mediump float;\n"
                                            "#endif\n"
                                            "uniform vec4 uColor;\n"
                                            "void main()\n"
                                            "{\n"
                                            "    gl_FragColor = uColor;\n"
                                            "}\n";
                                
                                        m_program.create();
                                        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                        m_program.link();
                                        m_program.bind();
                                
                                        float vertPositions[m_amountOfDiskVertices * 2 + 8]; // Disk + Square
                                        float radius = 0.5f;
                                        float angle = 0.f;
                                
                                        int index = 0;
                                        // Disk center
                                        vertPositions[index++] = 0.f;
                                        vertPositions[index++] = 0.f;
                                
                                               // Disk
                                        for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
                                        {
                                            float radians = qDegreesToRadians(angle);
                                            float x = radius * qCos(radians);
                                            float y = radius * qSin(radians);
                                            vertPositions[index++] = x;
                                            vertPositions[index++] = y;
                                            angle += m_angleStep;
                                        }
                                        // Square
                                        vertPositions[index++] = -0.5f;
                                        vertPositions[index++] = -0.5f;
                                        vertPositions[index++] = 0.5f;
                                        vertPositions[index++] = -0.5f;
                                        vertPositions[index++] = -0.5f;
                                        vertPositions[index++] = 0.5f;
                                        vertPositions[index++] = 0.5f;
                                        vertPositions[index++] = 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");
                                
                                        m_uColorLocation = m_program.uniformLocation("uColor");
                                        m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
                                        m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                    }
                                
                                    void resizeGL(int w, int h) override
                                    {
                                        int deviceW = w * devicePixelRatio();
                                        int deviceH = h * devicePixelRatio();
                                        float deviceAspect = deviceH / (float) deviceW;
                                
                                        if (deviceAspect > m_worldAspect)
                                        {
                                            m_viewportWidth = deviceW;
                                            m_viewportHeight = (int) deviceW * m_worldAspect;
                                            m_viewportX = 0;
                                            m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                        }
                                        else
                                        {
                                            m_viewportWidth = (int) deviceH / m_worldAspect;
                                            m_viewportHeight = deviceH;
                                            m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                            m_viewportY = 0;
                                        }
                                        m_projMatrix.setToIdentity();
                                        m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                        m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                    }
                                
                                    void paintGL() override
                                    {
                                        glClear(GL_COLOR_BUFFER_BIT);
                                        glClearColor(0.2, 0.2, 0.2, 1);
                                        glClear(GL_COLOR_BUFFER_BIT);
                                        glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                        glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                        glClearColor(0.04, 0.62, 0.48, 1);
                                        glEnable(GL_SCISSOR_TEST);
                                        glClear(GL_COLOR_BUFFER_BIT);
                                        glDisable(GL_SCISSOR_TEST);
                                
                                        m_disk2Color.setW(0.2f);
                                        if (dist(m_disk1PosX, m_disk1PosY, m_disk2PosX, m_disk2PosY) < 30.f)
                                            m_disk2Color.setW(1.f);
                                
                                        // Disk
                                        drawDisk(m_disk2PosX, m_disk2PosY, 30.f, m_disk2Color);
                                        // Disk
                                        drawDisk(m_disk1PosX, m_disk1PosY, 30.f, QVector4D(0.f, 0.f, 0.5f, 1.f));
                                        // Left border
                                        drawRectangle(5.f, 50.f, 5.f, 85.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
                                        // Right border
                                        drawRectangle(195.f, 50.f, 5.f, 85.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
                                        // Top border
                                        drawRectangle(100.f, 95.f, 185.f, 5.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
                                        // Bottom border
                                        drawRectangle(100.f, 5.f, 185.f, 5.f, 0.f, QVector4D(0.62f, 0.04f, 0.18f, 1.f));
                                    }
                                
                                    float dist(float x1, float y1, float x2, float y2)
                                    {
                                        float deltaX = qFabs(x1 - x2);
                                        float deltaY = qFabs(y1 - y2);
                                        return qSqrt(qPow(deltaX, 2) + qPow(deltaY, 2));
                                    }
                                
                                    void drawDisk(float x, float y, float diameter, const QVector4D& color)
                                    {
                                        m_modelMatrix.setToIdentity();
                                        m_modelMatrix.translate(QVector3D(x, y, 0));
                                        m_modelMatrix.scale(QVector3D(diameter, diameter, 1));
                                        m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                        m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                        m_program.setUniformValue(m_uColorLocation, color);
                                        glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
                                    }
                                
                                    void drawRectangle(float x, float y, float w, float h,
                                        float angle, const QVector4D& color)
                                    {
                                        m_modelMatrix.setToIdentity();
                                        m_modelMatrix.translate(QVector3D(x, y, 0));
                                        m_modelMatrix.rotate(angle, QVector3D(0, 0, 1));
                                        m_modelMatrix.scale(QVector3D(w, h, 1));
                                        m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                        m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                        m_program.setUniformValue(m_uColorLocation, color);
                                        glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
                                    }
                                
                                    void mousePressEvent(QMouseEvent *event) override
                                    {
                                        switch (event->button()) {
                                            case Qt::MouseButton::LeftButton:
                                            {
                                                m_mouseHolding = true;
                                                int x = event->pos().x() * devicePixelRatio();
                                                int y = (height() - event->pos().y() - 1) * devicePixelRatio();
                                                if ((m_viewportX <= x && x < (m_viewportX + m_viewportWidth)) &&
                                                    (m_viewportY <= y && y < (m_viewportY + m_viewportHeight)))
                                                {
                                                    float normalizedX = (x - m_viewportX) / (float) m_viewportWidth;
                                                    float normalizedY = (y - m_viewportY) / (float) m_viewportHeight;
                                                    m_disk1PosX = m_worldWidth * normalizedX;
                                                    m_disk1PosY = m_worldHeight * normalizedY;
                                                }
                                                update();
                                                break;
                                            }
                                            default:
                                                break;
                                        }
                                    }
                                
                                    void mouseMoveEvent(QMouseEvent *event) override
                                    {
                                        if (!m_mouseHolding)
                                            return;
                                
                                        int x = event->pos().x() * devicePixelRatio();
                                        int y = (height() - event->pos().y() - 1) * devicePixelRatio();
                                        if ((m_viewportX <= x && x < (m_viewportX + m_viewportWidth)) &&
                                            (m_viewportY <= y && y < (m_viewportY + m_viewportHeight)))
                                        {
                                            float normalizedX = (x - m_viewportX) / (float) m_viewportWidth;
                                            float normalizedY = (y - m_viewportY) / (float) m_viewportHeight;
                                            m_disk1PosX = m_worldWidth * normalizedX;
                                            m_disk1PosY = m_worldHeight * normalizedY;
                                        }
                                        update();
                                    }
                                
                                    void mouseReleaseEvent(QMouseEvent *event) override
                                    {
                                        switch (event->button()) {
                                            case Qt::MouseButton::LeftButton:
                                            {
                                                m_mouseHolding = false;
                                                break;
                                            }
                                            default:
                                                break;
                                        }
                                    }
                                
                                private:
                                    QOpenGLBuffer m_vertPosBuffer;
                                    QOpenGLShaderProgram m_program;
                                    int m_uColorLocation;
                                    int m_uMvpMatrixLocation;
                                    QMatrix4x4 m_mvpMatrix;
                                    QMatrix4x4 m_projMatrix;
                                    QMatrix4x4 m_viewMatrix;
                                    QMatrix4x4 m_projViewMatrix;
                                    QMatrix4x4 m_modelMatrix;
                                    const float m_worldWidth = 200.f;
                                    const float m_worldHeight = 100.f;
                                    float m_worldAspect = m_worldHeight / m_worldWidth;
                                    int m_viewportX;
                                    int m_viewportY;
                                    int m_viewportWidth;
                                    int m_viewportHeight;
                                    float m_angleStep = 10.f;
                                    int m_amountOfDiskVertices = 360.f / m_angleStep + 2;
                                    bool m_mouseHolding = false;
                                    float m_disk1PosX = 150.f;
                                    float m_disk1PosY = 50.f;
                                    QVector4D m_disk2Color = QVector4D(0.8f, 0.f, 0.f, 0.2f);
                                    float m_disk2PosX = 70.f;
                                    float m_disk2PosY = 50.f;
                                };
                                
                                int main(int argc, char *argv[])
                                {
                                    QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                    QApplication app(argc, argv);
                                    OpenGLWindow w;
                                    w.show();
                                    return app.exec();
                                }
                                1 Reply Last reply
                                0
                                • 8Observer88 Offline
                                  8Observer88 Offline
                                  8Observer8
                                  wrote on last edited by 8Observer8
                                  #24

                                  Lines with thickness with disks between them

                                  This example draws two lines from "start" to "finish" with thickness:

                                  void drawLine(const QVector2D &from, const QVector2D &to, float thickness,
                                      const QVector3D& color)
                                  

                                  It draws a rectangle. I place three disks: in the start point, between lines (where lines are connected), and in the finish point:

                                          // Strip line
                                          // Disk
                                          QVector3D lineColor(0.25f, 0.31f, 0.85f);
                                          drawDisk(20.f, 50.f, 10.f, lineColor);
                                          // Line
                                          drawLine(QVector2D(20.f, 50.f), QVector2D(50.f, 70.f), 10.f, lineColor);
                                          // Disk
                                          drawDisk(50.f, 70.f, 10.f, lineColor);
                                          // Line
                                          drawLine(QVector2D(50.f, 70.f), QVector2D(60.f, 20.f), 10.f, lineColor);
                                          // Disk
                                          drawDisk(60.f, 20.f, 10.f, lineColor);
                                  

                                  WebAssembly demo on free Netlify hosting

                                  4432526f-86df-4ca1-be07-343e8c595415-image.png

                                  7c21b577-d491-4e38-9c6d-26c4d12a73e3-image.png

                                  lines-with-thickness-opengles2-qt6-cpp.pro

                                  QT += core gui openglwidgets
                                  
                                  CONFIG += c++17
                                  
                                  SOURCES += \
                                      main.cpp
                                  

                                  main.cpp

                                  #include <QtMath>
                                  #include <QtGui/QMatrix4x4>
                                  #include <QtGui/QOpenGLFunctions>
                                  #include <QtGui/QQuaternion>
                                  #include <QtGui/QSurfaceFormat>
                                  #include <QtGui/QVector2D>
                                  #include <QtGui/QVector3D>
                                  #include <QtOpenGL/QOpenGLBuffer>
                                  #include <QtOpenGL/QOpenGLShader>
                                  #include <QtOpenGL/QOpenGLShaderProgram>
                                  #include <QtOpenGL/QOpenGLWindow>
                                  #include <QtWidgets/QApplication>
                                  
                                  class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                  {
                                  public:
                                      OpenGLWindow()
                                      {
                                          setTitle("OpenGL ES 2.0, Qt6, C++");
                                          resize(450, 450);
                                  
                                          QSurfaceFormat surfaceFormat;
                                          surfaceFormat.setDepthBufferSize(24);
                                          surfaceFormat.setSamples(4);
                                          setFormat(surfaceFormat);
                                      }
                                  
                                      void initializeGL() override
                                      {
                                          initializeOpenGLFunctions();
                                          glClearColor(0.04f, 0.62f, 0.48f, 1.f);
                                  
                                          QString vertShaderSrc =
                                              "attribute vec2 aPosition;\n"
                                              "uniform mat4 uMvpMatrix;"
                                              "void main()\n"
                                              "{\n"
                                              "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                              "}\n";
                                  
                                          QString fragShaderSrc =
                                              "#ifdef GL_ES\n"
                                              "precision mediump float;\n"
                                              "#endif\n"
                                              "uniform vec3 uColor;\n"
                                              "void main()\n"
                                              "{\n"
                                              "    gl_FragColor = vec4(uColor, 1.0);\n"
                                              "}\n";
                                  
                                          m_program.create();
                                          m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                          m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                          m_program.link();
                                          m_program.bind();
                                  
                                          float vertPositions[m_amountOfDiskVertices * 2 + 8]; // Disk + Square
                                          float radius = 0.5f;
                                          float angle = 0.f;
                                  
                                          int index = 0;
                                          // Disk center
                                          vertPositions[index++] = 0.f;
                                          vertPositions[index++] = 0.f;
                                  
                                          // Disk
                                          for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
                                          {
                                              float radians = qDegreesToRadians(angle);
                                              float x = radius * qCos(radians);
                                              float y = radius * qSin(radians);
                                              vertPositions[index++] = x;
                                              vertPositions[index++] = y;
                                              angle += m_angleStep;
                                          }
                                          // Square
                                          vertPositions[index++] = -0.5f;
                                          vertPositions[index++] = -0.5f;
                                          vertPositions[index++] = 0.5f;
                                          vertPositions[index++] = -0.5f;
                                          vertPositions[index++] = -0.5f;
                                          vertPositions[index++] = 0.5f;
                                          vertPositions[index++] = 0.5f;
                                          vertPositions[index++] = 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");
                                  
                                          m_uColorLocation = m_program.uniformLocation("uColor");
                                          m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");
                                          m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                      }
                                  
                                      void resizeGL(int w, int h) override
                                      {
                                          int deviceW = w * devicePixelRatio();
                                          int deviceH = h * devicePixelRatio();
                                          float deviceAspect = deviceH / (float) deviceW;
                                  
                                          if (deviceAspect > m_worldAspect)
                                          {
                                              m_viewportWidth = deviceW;
                                              m_viewportHeight = (int) deviceW * m_worldAspect;
                                              m_viewportX = 0;
                                              m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                          }
                                          else
                                          {
                                              m_viewportWidth = (int) deviceH / m_worldAspect;
                                              m_viewportHeight = deviceH;
                                              m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                              m_viewportY = 0;
                                          }
                                          m_projMatrix.setToIdentity();
                                          m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                          m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                      }
                                  
                                      void paintGL() override
                                      {
                                          glClear(GL_COLOR_BUFFER_BIT);
                                          glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                          glClear(GL_COLOR_BUFFER_BIT);
                                          glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                          glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                          glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                          glEnable(GL_SCISSOR_TEST);
                                          glClear(GL_COLOR_BUFFER_BIT);
                                          glDisable(GL_SCISSOR_TEST);
                                  
                                          // Strip line
                                          // Disk
                                          QVector3D lineColor(0.25f, 0.31f, 0.85f);
                                          drawDisk(20.f, 50.f, 10.f, lineColor);
                                          // Line
                                          drawLine(QVector2D(20.f, 50.f), QVector2D(50.f, 70.f), 10.f, lineColor);
                                          // Disk
                                          drawDisk(50.f, 70.f, 10.f, lineColor);
                                          // Line
                                          drawLine(QVector2D(50.f, 70.f), QVector2D(60.f, 20.f), 10.f, lineColor);
                                          // Disk
                                          drawDisk(60.f, 20.f, 10.f, lineColor);
                                  
                                          // Square
                                          drawRectangle(100.f, 50.f, 50.f, 50.f, 0.f, QVector3D(0.3f, 0.07f, 0.5f));
                                          // Disk
                                          drawDisk(100.f, 50.f, 50.f, QVector3D(0.8f, 0.8f, 0.5f));
                                  
                                          // Borders
                                          QVector3D borderColor(0.62f, 0.04f, 0.18f);
                                          // Left border
                                          drawRectangle(5.f, 50.f, 5.f, 85.f, 0.f, borderColor);
                                          // Right border
                                          drawRectangle(195.f, 50.f, 5.f, 85.f, 0.f, borderColor);
                                          // Top border
                                          drawRectangle(100.f, 95.f, 185.f, 5.f, 0.f, borderColor);
                                          // Bottom border
                                          drawRectangle(100.f, 5.f, 185.f, 5.f, 0.f, borderColor);
                                      }
                                  
                                      void drawDisk(float x, float y, float diameter, const QVector3D& color)
                                      {
                                          m_modelMatrix.setToIdentity();
                                          m_modelMatrix.translate(QVector3D(x, y, 0.f));
                                          m_modelMatrix.scale(QVector3D(diameter, diameter, 1.f));
                                          m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                          m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                          m_program.setUniformValue(m_uColorLocation, color);
                                          glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
                                      }
                                  
                                      void drawRectangle(float x, float y, float w, float h,
                                          float angle, const QVector3D& color)
                                      {
                                          m_modelMatrix.setToIdentity();
                                          m_modelMatrix.translate(QVector3D(x, y, 0.f));
                                          m_modelMatrix.rotate(angle, QVector3D(0.f, 0.f, 1.f));
                                          m_modelMatrix.scale(QVector3D(w, h, 1.f));
                                          m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                          m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                          m_program.setUniformValue(m_uColorLocation, color);
                                          glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
                                      }
                                  
                                      void drawLine(const QVector2D &from, const QVector2D &to, float thickness,
                                          const QVector3D& color)
                                      {
                                          QVector2D center;
                                  
                                          if (from.x() > to.x())
                                          {
                                              center.setX(to.x() + qFabs(from.x() - to.x()) / 2.f);
                                          }
                                          else
                                          {
                                              center.setX(from.x() + qFabs(to.x() - from.x()) / 2.f);
                                          }
                                  
                                          if (from.y() > to.y())
                                          {
                                              center.setY(to.y() + qFabs(from.y() - to.y()) / 2.f);
                                          }
                                          else
                                          {
                                              center.setY(from.y() + qFabs(to.y() - from.y()) / 2.f);
                                          }
                                  
                                          QVector3D tempVec;
                                          tempVec.setX(to.x() - from.x());
                                          tempVec.setY(to.y() - from.y());
                                          float length = tempVec.length();
                                          tempVec.normalize();
                                          QQuaternion quat = QQuaternion::rotationTo(QVector3D(1.f, 0.f, 0.f), tempVec);
                                  
                                          m_modelMatrix.setToIdentity();
                                          m_modelMatrix.translate(QVector3D(center.x(), center.y(), 0.f));
                                          m_modelMatrix.rotate(quat);
                                          m_modelMatrix.scale(QVector3D(length, thickness, 1.f));
                                          m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                          m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                          m_program.setUniformValue(m_uColorLocation, color);
                                          glDrawArrays(GL_TRIANGLE_STRIP, m_amountOfDiskVertices, 4);
                                      }
                                  
                                  private:
                                      QOpenGLBuffer m_vertPosBuffer;
                                      QOpenGLShaderProgram m_program;
                                      int m_uColorLocation;
                                      int m_uMvpMatrixLocation;
                                      QMatrix4x4 m_mvpMatrix;
                                      QMatrix4x4 m_projMatrix;
                                      QMatrix4x4 m_viewMatrix;
                                      QMatrix4x4 m_projViewMatrix;
                                      QMatrix4x4 m_modelMatrix;
                                      const float m_worldWidth = 200.f;
                                      const float m_worldHeight = 100.f;
                                      float m_worldAspect = m_worldHeight / m_worldWidth;
                                      int m_viewportX;
                                      int m_viewportY;
                                      int m_viewportWidth;
                                      int m_viewportHeight;
                                      int m_angleStep = 10;
                                      int m_amountOfDiskVertices = 360 / m_angleStep + 2;
                                  };
                                  
                                  int main(int argc, char *argv[])
                                  {
                                      QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                      QApplication app(argc, argv);
                                      OpenGLWindow w;
                                      w.show();
                                      return app.exec();
                                  }
                                  
                                  1 Reply Last reply
                                  0
                                  • 8Observer88 Offline
                                    8Observer88 Offline
                                    8Observer8
                                    wrote on last edited by 8Observer8
                                    #25

                                    Line drawer

                                    Created a separate class for drawing a line.

                                    WebAssembly demo on free Netlify hosting

                                    4a1428fe-c102-448b-acbc-e4a4c9bdaa47-image.png

                                    662df3bd-205a-4e3e-885b-50ca5700be10-image.png

                                    line-drawer-opengles2-qt6-cpp.pro

                                    QT += core gui openglwidgets
                                    
                                    win32: LIBS += -lopengl32
                                    
                                    CONFIG += c++17
                                    
                                    SOURCES += \
                                        line_drawer.cpp \
                                        main.cpp \
                                        opengl_window.cpp
                                    
                                    HEADERS += \
                                        line_drawer.h \
                                        opengl_window.h
                                    

                                    main.cpp

                                    #include <QtWidgets/QApplication>
                                    #include "opengl_window.h"
                                    
                                    int main(int argc, char *argv[])
                                    {
                                        QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                        QApplication app(argc, argv);
                                        OpenGLWindow w;
                                        w.show();
                                        return app.exec();
                                    }
                                    

                                    line_drawer.h

                                    #ifndef LINE_DRAWER
                                    #define LINE_DRAWER
                                    
                                    #include <QtGui/QMatrix4x4>
                                    #include <QtGui/QVector2D>
                                    #include <QtGui/QVector3D>
                                    #include <QtOpenGL/QOpenGLBuffer>
                                    #include <QtOpenGL/QOpenGLShaderProgram>
                                    
                                    class LineDrawer
                                    {
                                    public:
                                        LineDrawer(QOpenGLShaderProgram *program);
                                    
                                        void draw(const QVector2D &from, const QVector2D &to,
                                            const QVector3D &color, float thickness = 1.f);
                                        void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
                                    
                                    private:
                                        void bind();
                                    
                                    private:
                                        QOpenGLShaderProgram *m_program;
                                        QOpenGLBuffer m_vertPosBuffer;
                                        int m_aPositionLocation;
                                        int m_uMvpMatrixLocation;
                                        int m_uColorLocation;
                                        QMatrix4x4 m_projViewMatrix;
                                        QMatrix4x4 m_modelMatrix;
                                        QMatrix4x4 m_mvpMatrix;
                                    };
                                    
                                    #endif // LINE_DRAWER
                                    

                                    line_drawer.cpp

                                    #include "line_drawer.h"
                                    
                                    LineDrawer::LineDrawer(QOpenGLShaderProgram *program)
                                    {
                                        m_program = program;
                                        m_program->bind();
                                    
                                        m_aPositionLocation = m_program->attributeLocation("aPosition");
                                        m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
                                        m_uColorLocation = m_program->uniformLocation("uColor");
                                    
                                        float vertPositions[] = {
                                            -0.5, -0.5,
                                            0.5, -0.5,
                                            -0.5, 0.5,
                                            0.5, 0.5
                                        };
                                        m_vertPosBuffer.create();
                                        m_vertPosBuffer.bind();
                                        m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
                                    }
                                    
                                    void LineDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
                                    {
                                        m_projViewMatrix = projViewMatrix;
                                    }
                                    
                                    void LineDrawer::bind()
                                    {
                                        m_program->bind();
                                        m_vertPosBuffer.bind();
                                        m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
                                        m_program->enableAttributeArray(m_aPositionLocation);
                                    }
                                    
                                    void LineDrawer::draw(const QVector2D &from, const QVector2D &to,
                                        const QVector3D &color, float thickness)
                                    {
                                        bind();
                                        float centerX, centerY;
                                        QVector3D tempVec;
                                    
                                        if (from.x() > to.x())
                                        {
                                            centerX = to.x() + std::abs(from.x() - to.x()) / 2.f;
                                        }
                                        else
                                        {
                                            centerX = from.x() + std::abs(to.x() - from.x()) / 2.f;
                                        }
                                    
                                        if (from.y() > to.y())
                                        {
                                            centerY = to.y() + std::abs(from.y() - to.y()) / 2.f;
                                        }
                                        else
                                        {
                                            centerY = from.y() + std::abs(to.y() - from.y()) / 2.f;
                                        }
                                    
                                        tempVec.setX(to.x() - from.x());
                                        tempVec.setY(to.y() - from.y());
                                        float length = tempVec.length();
                                        tempVec.normalize();
                                        QQuaternion quat = QQuaternion::rotationTo(QVector3D(1, 0, 0), tempVec);
                                    
                                        m_modelMatrix.setToIdentity();
                                        m_modelMatrix.translate(QVector3D(centerX, centerY, 0));
                                        m_modelMatrix.rotate(quat);
                                        m_modelMatrix.scale(QVector3D(length, thickness, 1));
                                        m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                        m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                        m_program->setUniformValue(m_uColorLocation, color);
                                        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                                    }
                                    

                                    opengl_window.h

                                    #ifndef OPENGL_WINDOW_H
                                    #define OPENGL_WINDOW_H
                                    
                                    #include <QtMath>
                                    #include <QtGui/QMatrix4x4>
                                    #include <QtGui/QOpenGLFunctions>
                                    #include <QtGui/QQuaternion>
                                    #include <QtGui/QSurfaceFormat>
                                    #include <QtGui/QVector2D>
                                    #include <QtGui/QVector3D>
                                    #include <QtOpenGL/QOpenGLShader>
                                    #include <QtOpenGL/QOpenGLShaderProgram>
                                    #include <QtOpenGL/QOpenGLWindow>
                                    
                                    #include "line_drawer.h"
                                    
                                    class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                    {
                                    public:
                                        OpenGLWindow();
                                    
                                        ~OpenGLWindow();
                                    
                                    private:
                                        void initializeGL() override;
                                        void resizeGL(int w, int h) override;
                                        void paintGL() override;
                                    
                                    private:
                                        QOpenGLShaderProgram m_program;
                                        QMatrix4x4 m_projMatrix;
                                        QMatrix4x4 m_viewMatrix;
                                        QMatrix4x4 m_projViewMatrix;
                                        const float m_worldWidth = 200.f;
                                        const float m_worldHeight = 100.f;
                                        float m_worldAspect = m_worldHeight / m_worldWidth;
                                        int m_viewportX;
                                        int m_viewportY;
                                        int m_viewportWidth;
                                        int m_viewportHeight;
                                        LineDrawer *m_lineDrawer;
                                    };
                                    
                                    #endif // OPENGL_WINDOW_H
                                    

                                    opengl_window.cpp

                                    #include "opengl_window.h"
                                    
                                    OpenGLWindow::OpenGLWindow()
                                    {
                                        setTitle("OpenGL ES 2.0, Qt6, C++");
                                        resize(450, 450);
                                    
                                        QSurfaceFormat surfaceFormat;
                                        surfaceFormat.setDepthBufferSize(24);
                                        surfaceFormat.setSamples(4);
                                        setFormat(surfaceFormat);
                                    }
                                    
                                    OpenGLWindow::~OpenGLWindow()
                                    {
                                        delete m_lineDrawer;
                                    }
                                    
                                    void OpenGLWindow::initializeGL()
                                    {
                                        initializeOpenGLFunctions();
                                    
                                        QString vertShaderSrc =
                                            "attribute vec2 aPosition;\n"
                                            "uniform mat4 uMvpMatrix;"
                                            "void main()\n"
                                            "{\n"
                                            "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                            "}\n";
                                    
                                        QString fragShaderSrc =
                                            "#ifdef GL_ES\n"
                                            "precision mediump float;\n"
                                            "#endif\n"
                                            "uniform vec3 uColor;\n"
                                            "void main()\n"
                                            "{\n"
                                            "    gl_FragColor = vec4(uColor, 1.0);\n"
                                            "}\n";
                                    
                                        m_program.create();
                                        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                        m_program.link();
                                        m_program.bind();
                                    
                                        m_lineDrawer = new LineDrawer(&m_program);
                                    
                                        m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                    }
                                    
                                    void OpenGLWindow::resizeGL(int w, int h)
                                    {
                                        int deviceW = w * devicePixelRatio();
                                        int deviceH = h * devicePixelRatio();
                                        float deviceAspect = deviceH / (float) deviceW;
                                    
                                        if (deviceAspect > m_worldAspect)
                                        {
                                            m_viewportWidth = deviceW;
                                            m_viewportHeight = (int) deviceW * m_worldAspect;
                                            m_viewportX = 0;
                                            m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                        }
                                        else
                                        {
                                            m_viewportWidth = (int) deviceH / m_worldAspect;
                                            m_viewportHeight = deviceH;
                                            m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                            m_viewportY = 0;
                                        }
                                        m_projMatrix.setToIdentity();
                                        m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                        m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                    
                                        m_lineDrawer->setProjViewMatrix(m_projViewMatrix);
                                    }
                                    
                                    void OpenGLWindow::paintGL()
                                    {
                                        glClear(GL_COLOR_BUFFER_BIT);
                                        glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                        glClear(GL_COLOR_BUFFER_BIT);
                                        glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                        glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                        glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                        glEnable(GL_SCISSOR_TEST);
                                        glClear(GL_COLOR_BUFFER_BIT);
                                        glDisable(GL_SCISSOR_TEST);
                                    
                                        // X axis
                                        QVector3D xAxisColor(0.80f, 0.15f, 0.18f);
                                        m_lineDrawer->draw(QVector2D(30.f, 20.f), QVector2D(170.f, 20.f), xAxisColor);
                                        // Arrow
                                        m_lineDrawer->draw(QVector2D(165.f, 23.f), QVector2D(170.f, 20.f), xAxisColor);
                                        m_lineDrawer->draw(QVector2D(165.f, 17.f), QVector2D(170.f, 20.f),xAxisColor);
                                        // Divisions
                                        m_lineDrawer->draw(QVector2D(50.f, 17.f), QVector2D(50.f, 23.f), xAxisColor);
                                        m_lineDrawer->draw(QVector2D(70.f, 17.f), QVector2D(70.f, 23.f), xAxisColor);
                                        m_lineDrawer->draw(QVector2D(90.f, 17.f), QVector2D(90.f, 23.f), xAxisColor);
                                        m_lineDrawer->draw(QVector2D(110.f, 17.f), QVector2D(110.f, 23.f), xAxisColor);
                                        m_lineDrawer->draw(QVector2D(130.f, 17.f), QVector2D(130.f, 23.f), xAxisColor);
                                        m_lineDrawer->draw(QVector2D(150.f, 17.f), QVector2D(150.f, 23.f), xAxisColor);
                                    
                                        // Y axis
                                        QVector3D yAxisColor(0.20f, 0.60f, 0.30f);
                                        m_lineDrawer->draw(QVector2D(30.f, 20.f), QVector2D(30.f, 95.f), yAxisColor);
                                        // Arrow
                                        m_lineDrawer->draw(QVector2D(27.f, 90.f), QVector2D(30.f, 95.f), yAxisColor);
                                        m_lineDrawer->draw(QVector2D(33.f, 90.f), QVector2D(30.f, 95.f), yAxisColor);
                                        // Divisions
                                        m_lineDrawer->draw(QVector2D(27.f, 40.f), QVector2D(33.f, 40.f), yAxisColor);
                                        m_lineDrawer->draw(QVector2D(27.f, 60.f), QVector2D(33.f, 60.f), yAxisColor);
                                        m_lineDrawer->draw(QVector2D(27.f, 80.f), QVector2D(33.f, 80.f), yAxisColor);
                                    
                                        // Graph
                                        QVector3D graphColor(0.25f, 0.31f, 0.85f);
                                        m_lineDrawer->draw(QVector2D(50.f, 40.f), QVector2D(70.f, 60.f), graphColor);
                                        m_lineDrawer->draw(QVector2D(70.f, 60.f), QVector2D(130.f, 60.f), graphColor);
                                        m_lineDrawer->draw(QVector2D(130.f, 60.f), QVector2D(150.f, 80.f), graphColor);
                                    }
                                    
                                    1 Reply Last reply
                                    0
                                    • 8Observer88 Offline
                                      8Observer88 Offline
                                      8Observer8
                                      wrote on last edited by
                                      #26

                                      Rectangle drawer

                                      WebAssembly demo on free Netlify hosting

                                      a826ef3c-65a8-4057-8dc6-a9952f09ae7b-image.png

                                      44977ea3-f4da-492f-a58d-7549b7e21278-image.png

                                      rectangle-drawer-opengles2-qt6-cpp.pro

                                      QT += core gui openglwidgets
                                      
                                      win32: LIBS += -lopengl32
                                      
                                      CONFIG += c++17
                                      
                                      SOURCES += \
                                          main.cpp \
                                          opengl_window.cpp \
                                          rectangle_drawer.cpp
                                      
                                      HEADERS += \
                                          opengl_window.h \
                                          rectangle_drawer.h
                                      

                                      main.cpp

                                      #include <QtWidgets/QApplication>
                                      #include "opengl_window.h"
                                      
                                      int main(int argc, char *argv[])
                                      {
                                          QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                          QApplication app(argc, argv);
                                          OpenGLWindow w;
                                          w.show();
                                          return app.exec();
                                      }
                                      

                                      rectangle_drawer.h

                                      #ifndef RECTANGLE_DRAWER
                                      #define RECTANGLE_DRAWER
                                      
                                      #include <QtGui/QMatrix4x4>
                                      #include <QtGui/QVector2D>
                                      #include <QtGui/QVector3D>
                                      #include <QtOpenGL/QOpenGLBuffer>
                                      #include <QtOpenGL/QOpenGLShaderProgram>
                                      
                                      class RectangleDrawer
                                      {
                                      public:
                                          RectangleDrawer(QOpenGLShaderProgram *program);
                                      
                                          void draw(const QVector2D &position, const QVector2D &size,
                                              const QVector3D &color, float angle = 0.f);
                                          void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
                                      
                                      private:
                                          void bind();
                                      
                                      private:
                                          QOpenGLShaderProgram *m_program;
                                          QOpenGLBuffer m_vertPosBuffer;
                                          int m_aPositionLocation;
                                          int m_uMvpMatrixLocation;
                                          int m_uColorLocation;
                                          QMatrix4x4 m_projViewMatrix;
                                          QMatrix4x4 m_modelMatrix;
                                          QMatrix4x4 m_mvpMatrix;
                                      };
                                      
                                      #endif // RECTANGLE_DRAWER
                                      

                                      rectangle_drawer.cpp

                                      #include "rectangle_drawer.h"
                                      
                                      RectangleDrawer::RectangleDrawer(QOpenGLShaderProgram *program)
                                      {
                                          m_program = program;
                                          m_program->bind();
                                      
                                          m_aPositionLocation = m_program->attributeLocation("aPosition");
                                          m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
                                          m_uColorLocation = m_program->uniformLocation("uColor");
                                      
                                          float vertPositions[] = {
                                              -0.5, -0.5,
                                              0.5, -0.5,
                                              -0.5, 0.5,
                                              0.5, 0.5
                                          };
                                          m_vertPosBuffer.create();
                                          m_vertPosBuffer.bind();
                                          m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
                                      }
                                      
                                      void RectangleDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
                                      {
                                          m_projViewMatrix = projViewMatrix;
                                      }
                                      
                                      void RectangleDrawer::bind()
                                      {
                                          m_program->bind();
                                          m_vertPosBuffer.bind();
                                          m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
                                          m_program->enableAttributeArray(m_aPositionLocation);
                                      }
                                      
                                      void RectangleDrawer::draw(const QVector2D &position, const QVector2D &size,
                                          const QVector3D &color, float angle)
                                      {
                                          bind();
                                          m_modelMatrix.setToIdentity();
                                          m_modelMatrix.translate(QVector3D(position.x(), position.y(), 0.f));
                                          m_modelMatrix.rotate(angle, QVector3D(0.f, 0.f, 1.f));
                                          m_modelMatrix.scale(QVector3D(size.x(), size.y(), 1.f));
                                          m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                          m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                          m_program->setUniformValue(m_uColorLocation, color);
                                          glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                                      }
                                      

                                      opengl_window.h

                                      #ifndef OPENGL_WINDOW
                                      #define OPENGL_WINDOW
                                      
                                      #include <QtMath>
                                      #include <QtGui/QMatrix4x4>
                                      #include <QtGui/QOpenGLFunctions>
                                      #include <QtGui/QQuaternion>
                                      #include <QtGui/QSurfaceFormat>
                                      #include <QtGui/QVector2D>
                                      #include <QtGui/QVector3D>
                                      #include <QtOpenGL/QOpenGLShader>
                                      #include <QtOpenGL/QOpenGLShaderProgram>
                                      #include <QtOpenGL/QOpenGLWindow>
                                      
                                      #include "rectangle_drawer.h"
                                      
                                      class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                      {
                                      public:
                                          OpenGLWindow();
                                      
                                          ~OpenGLWindow();
                                      
                                      private:
                                          void initializeGL() override;
                                          void resizeGL(int w, int h) override;
                                          void paintGL() override;
                                      
                                      private:
                                          QOpenGLShaderProgram m_program;
                                          QMatrix4x4 m_projMatrix;
                                          QMatrix4x4 m_viewMatrix;
                                          QMatrix4x4 m_projViewMatrix;
                                          const float m_worldWidth = 200.f;
                                          const float m_worldHeight = 100.f;
                                          float m_worldAspect = m_worldHeight / m_worldWidth;
                                          int m_viewportX;
                                          int m_viewportY;
                                          int m_viewportWidth;
                                          int m_viewportHeight;
                                          RectangleDrawer *m_rectangleDrawer;
                                      };
                                      
                                      #endif // OPENGL_WINDOW
                                      

                                      opengl_window.cpp

                                      #include "opengl_window.h"
                                      
                                      OpenGLWindow::OpenGLWindow()
                                      {
                                          setTitle("OpenGL ES 2.0, Qt6, C++");
                                          resize(600, 300);
                                      
                                          QSurfaceFormat surfaceFormat;
                                          surfaceFormat.setDepthBufferSize(24);
                                          surfaceFormat.setSamples(4);
                                          setFormat(surfaceFormat);
                                      }
                                      
                                      OpenGLWindow::~OpenGLWindow()
                                      {
                                          delete m_rectangleDrawer;
                                      }
                                      
                                      void OpenGLWindow::initializeGL()
                                      {
                                          initializeOpenGLFunctions();
                                      
                                          QString vertShaderSrc =
                                              "attribute vec2 aPosition;\n"
                                              "uniform mat4 uMvpMatrix;"
                                              "void main()\n"
                                              "{\n"
                                              "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                              "}\n";
                                      
                                          QString fragShaderSrc =
                                              "#ifdef GL_ES\n"
                                              "precision mediump float;\n"
                                              "#endif\n"
                                              "uniform vec3 uColor;\n"
                                              "void main()\n"
                                              "{\n"
                                              "    gl_FragColor = vec4(uColor, 1.0);\n"
                                              "}\n";
                                      
                                          m_program.create();
                                          m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                          m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                          m_program.link();
                                          m_program.bind();
                                      
                                          m_rectangleDrawer = new RectangleDrawer(&m_program);
                                      
                                          m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                      }
                                      
                                      void OpenGLWindow::resizeGL(int w, int h)
                                      {
                                          int deviceW = w * devicePixelRatio();
                                          int deviceH = h * devicePixelRatio();
                                          float deviceAspect = deviceH / (float) deviceW;
                                      
                                          if (deviceAspect > m_worldAspect)
                                          {
                                              m_viewportWidth = deviceW;
                                              m_viewportHeight = (int) deviceW * m_worldAspect;
                                              m_viewportX = 0;
                                              m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                          }
                                          else
                                          {
                                              m_viewportWidth = (int) deviceH / m_worldAspect;
                                              m_viewportHeight = deviceH;
                                              m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                              m_viewportY = 0;
                                          }
                                          m_projMatrix.setToIdentity();
                                          m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                          m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                      
                                          m_rectangleDrawer->setProjViewMatrix(m_projViewMatrix);
                                      }
                                      
                                      void OpenGLWindow::paintGL()
                                      {
                                          glClear(GL_COLOR_BUFFER_BIT);
                                          glClearColor(0.2f, 0.2f, 0.2f, 1.f);
                                          // glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                          glClear(GL_COLOR_BUFFER_BIT);
                                          glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                          glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                          glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                          glEnable(GL_SCISSOR_TEST);
                                          glClear(GL_COLOR_BUFFER_BIT);
                                          glDisable(GL_SCISSOR_TEST);
                                      
                                          m_rectangleDrawer->draw(QVector2D(50.f, 70.f), QVector2D(72.f, 7.f),
                                              QVector3D(0.80f, 0.15f, 0.18f), -27.f);
                                          m_rectangleDrawer->draw(QVector2D(160.f, 50.f), QVector2D(70.f, 5.f),
                                              QVector3D(0.20f, 0.60f, 0.30f), 10.f);
                                          m_rectangleDrawer->draw(QVector2D(100.f, 15.f), QVector2D(150.f, 7.f),
                                              QVector3D(0.25f, 0.31f, 0.85f));
                                      }
                                      
                                      1 Reply Last reply
                                      0
                                      • 8Observer88 Offline
                                        8Observer88 Offline
                                        8Observer8
                                        wrote on last edited by 8Observer8
                                        #27

                                        Disk drawer

                                        WebAssembly demo on free Netlify hosting

                                        7f948267-de69-476e-93b8-fb71355b3423-image.png

                                        29f3e494-89c4-4642-9232-5063de0acc78-image.png

                                        disk-drawer-opengles2-qt6-cpp.pro

                                        QT += core gui openglwidgets
                                        
                                        win32: LIBS += -lopengl32
                                        
                                        CONFIG += c++17
                                        
                                        SOURCES += \
                                            disk_drawer.cpp \
                                            main.cpp \
                                            opengl_window.cpp
                                        
                                        HEADERS += \
                                            disk_drawer.h \
                                            opengl_window.h
                                        

                                        main.cpp

                                        #include <QtWidgets/QApplication>
                                        #include "opengl_window.h"
                                        
                                        int main(int argc, char *argv[])
                                        {
                                            QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                            QApplication app(argc, argv);
                                            OpenGLWindow w;
                                            w.show();
                                            return app.exec();
                                        }
                                        

                                        disk_drawer.h

                                        #ifndef DISK_DRAWER
                                        #define DISK_DRAWER
                                        
                                        #include <QtGui/QMatrix4x4>
                                        #include <QtGui/QVector2D>
                                        #include <QtGui/QVector3D>
                                        #include <QtOpenGL/QOpenGLBuffer>
                                        #include <QtOpenGL/QOpenGLShaderProgram>
                                        
                                        class DiskDrawer
                                        {
                                        public:
                                            DiskDrawer(QOpenGLShaderProgram *program);
                                        
                                            void draw(const QVector2D &position, float diameter,
                                                const QVector3D &color);
                                            void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
                                        
                                        private:
                                            void bind();
                                        
                                        private:
                                            QOpenGLShaderProgram *m_program;
                                            QOpenGLBuffer m_vertPosBuffer;
                                            int m_aPositionLocation;
                                            int m_uMvpMatrixLocation;
                                            int m_uColorLocation;
                                            QMatrix4x4 m_projViewMatrix;
                                            QMatrix4x4 m_modelMatrix;
                                            QMatrix4x4 m_mvpMatrix;
                                            int m_angleStep = 5;
                                            int m_amountOfDiskVertices = 360 / m_angleStep + 2;
                                        };
                                        
                                        #endif // DISK_DRAWER
                                        

                                        disk_drawer.cpp

                                        #include "disk_drawer.h"
                                        
                                        DiskDrawer::DiskDrawer(QOpenGLShaderProgram *program)
                                        {
                                            m_program = program;
                                            m_program->bind();
                                        
                                            m_aPositionLocation = m_program->attributeLocation("aPosition");
                                            m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
                                            m_uColorLocation = m_program->uniformLocation("uColor");
                                        
                                            float vertPositions[m_amountOfDiskVertices * 2];
                                            float radius = 0.5f;
                                            float angle = 0.f;
                                            int index = 0;
                                        
                                            // Disk center
                                            vertPositions[index++] = 0.f;
                                            vertPositions[index++] = 0.f;
                                        
                                            for (int i = 0; i < m_amountOfDiskVertices - 1; i++)
                                            {
                                                float radians = qDegreesToRadians(angle);
                                                float x = radius * qCos(radians);
                                                float y = radius * qSin(radians);
                                                vertPositions[index++] = x;
                                                vertPositions[index++] = y;
                                                angle += m_angleStep;
                                            }
                                        
                                            m_vertPosBuffer.create();
                                            m_vertPosBuffer.bind();
                                            m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
                                        }
                                        
                                        void DiskDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
                                        {
                                            m_projViewMatrix = projViewMatrix;
                                        }
                                        
                                        void DiskDrawer::bind()
                                        {
                                            m_program->bind();
                                            m_vertPosBuffer.bind();
                                            m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
                                            m_program->enableAttributeArray(m_aPositionLocation);
                                        }
                                        
                                        void DiskDrawer::draw(const QVector2D &position, float diameter,
                                            const QVector3D &color)
                                        {
                                            bind();
                                            m_modelMatrix.setToIdentity();
                                            m_modelMatrix.translate(QVector3D(position.x(), position.y(), 0.f));
                                            m_modelMatrix.scale(QVector3D(diameter, diameter, 1.f));
                                            m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                            m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                            m_program->setUniformValue(m_uColorLocation, color);
                                            glDrawArrays(GL_TRIANGLE_FAN, 0, m_amountOfDiskVertices);
                                        }
                                        

                                        opengl_window.h

                                        #ifndef OPENGL_WINDOW
                                        #define OPENGL_WINDOW
                                        
                                        #include <QtMath>
                                        #include <QtGui/QMatrix4x4>
                                        #include <QtGui/QOpenGLFunctions>
                                        #include <QtGui/QQuaternion>
                                        #include <QtGui/QSurfaceFormat>
                                        #include <QtGui/QVector2D>
                                        #include <QtGui/QVector3D>
                                        #include <QtOpenGL/QOpenGLShader>
                                        #include <QtOpenGL/QOpenGLShaderProgram>
                                        #include <QtOpenGL/QOpenGLWindow>
                                        
                                        #include "disk_drawer.h"
                                        
                                        class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                        {
                                        public:
                                            OpenGLWindow();
                                        
                                            ~OpenGLWindow();
                                        
                                        private:
                                            void initializeGL() override;
                                            void resizeGL(int w, int h) override;
                                            void paintGL() override;
                                        
                                        private:
                                            QOpenGLShaderProgram m_program;
                                            QMatrix4x4 m_projMatrix;
                                            QMatrix4x4 m_viewMatrix;
                                            QMatrix4x4 m_projViewMatrix;
                                            const float m_worldWidth = 200.f;
                                            const float m_worldHeight = 100.f;
                                            float m_worldAspect = m_worldHeight / m_worldWidth;
                                            int m_viewportX;
                                            int m_viewportY;
                                            int m_viewportWidth;
                                            int m_viewportHeight;
                                            DiskDrawer *m_diskDrawer;
                                        };
                                        
                                        #endif // OPENGL_WINDOW
                                        

                                        opengl_window.cpp

                                        #include "opengl_window.h"
                                        
                                        OpenGLWindow::OpenGLWindow()
                                        {
                                            setTitle("OpenGL ES 2.0, Qt6, C++");
                                            resize(600, 300);
                                        
                                            QSurfaceFormat surfaceFormat;
                                            surfaceFormat.setDepthBufferSize(24);
                                            surfaceFormat.setSamples(4);
                                            setFormat(surfaceFormat);
                                        }
                                        
                                        OpenGLWindow::~OpenGLWindow()
                                        {
                                            delete m_diskDrawer;
                                        }
                                        
                                        void OpenGLWindow::initializeGL()
                                        {
                                            initializeOpenGLFunctions();
                                        
                                            QString vertShaderSrc =
                                                "attribute vec2 aPosition;\n"
                                                "uniform mat4 uMvpMatrix;"
                                                "void main()\n"
                                                "{\n"
                                                "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                                "}\n";
                                        
                                            QString fragShaderSrc =
                                                "#ifdef GL_ES\n"
                                                "precision mediump float;\n"
                                                "#endif\n"
                                                "uniform vec3 uColor;\n"
                                                "void main()\n"
                                                "{\n"
                                                "    gl_FragColor = vec4(uColor, 1.0);\n"
                                                "}\n";
                                        
                                            m_program.create();
                                            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                            m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                            m_program.link();
                                            m_program.bind();
                                        
                                            m_diskDrawer = new DiskDrawer(&m_program);
                                        
                                            m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                        }
                                        
                                        void OpenGLWindow::resizeGL(int w, int h)
                                        {
                                            int deviceW = w * devicePixelRatio();
                                            int deviceH = h * devicePixelRatio();
                                            float deviceAspect = deviceH / (float) deviceW;
                                        
                                            if (deviceAspect > m_worldAspect)
                                            {
                                                m_viewportWidth = deviceW;
                                                m_viewportHeight = (int) deviceW * m_worldAspect;
                                                m_viewportX = 0;
                                                m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                            }
                                            else
                                            {
                                                m_viewportWidth = (int) deviceH / m_worldAspect;
                                                m_viewportHeight = deviceH;
                                                m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                                m_viewportY = 0;
                                            }
                                            m_projMatrix.setToIdentity();
                                            m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                            m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                        
                                            m_diskDrawer->setProjViewMatrix(m_projViewMatrix);
                                        }
                                        
                                        void OpenGLWindow::paintGL()
                                        {
                                            glClear(GL_COLOR_BUFFER_BIT);
                                            // glClearColor(0.2f, 0.2f, 0.2f, 1.f);
                                            glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                            glClear(GL_COLOR_BUFFER_BIT);
                                            glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                            glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                            glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                            glEnable(GL_SCISSOR_TEST);
                                            glClear(GL_COLOR_BUFFER_BIT);
                                            glDisable(GL_SCISSOR_TEST);
                                        
                                            m_diskDrawer->draw(QVector2D(50.f, 70.f), 40.f,
                                                QVector3D(0.80f, 0.15f, 0.18f));
                                            m_diskDrawer->draw(QVector2D(160.f, 50.f), 50.f,
                                                QVector3D(0.20f, 0.60f, 0.30f));
                                            m_diskDrawer->draw(QVector2D(100.f, 15.f), 20.f,
                                                QVector3D(0.25f, 0.31f, 0.85f));
                                        }
                                        
                                        1 Reply Last reply
                                        0
                                        • 8Observer88 Offline
                                          8Observer88 Offline
                                          8Observer8
                                          wrote on last edited by 8Observer8
                                          #28

                                          Ring drawer using line drawer

                                          The RingDrawer class uses the LineDrawer class to draw the segments of a ring. For example, for number of segments equals to 10:

                                          void RingDrawer::draw(const QVector2D &center, float radius,
                                              const QVector3D &color, int numberOfSegments, float thickness)
                                          {
                                              float angle = 0.f;
                                              const float angleStep = 360.f / numberOfSegments;
                                          
                                              float x = radius * qCos(qDegreesToRadians(angle));
                                              float y = radius * qSin(qDegreesToRadians(angle));
                                              QVector2D from(center.x() + x, center.y() + y);
                                              angle += angleStep;
                                          
                                              for (int i = 0; i < numberOfSegments; i++)
                                              {
                                                  x = radius * qCos(qDegreesToRadians(angle));
                                                  y = radius * qSin(qDegreesToRadians(angle));
                                                  QVector2D to(center.x() + x, center.y() + y);
                                                  m_lineDrawer->draw(from, to, color, thickness);
                                                  angle += angleStep;
                                                  from = to;
                                              }
                                          }
                                          

                                          72b84185-de20-4c48-a487-c69398bae1d2-image.png

                                          For number of segments equals to 50: WebAssembly demo on free Netlify hosting

                                          26c86b27-e3fc-4501-987e-e92f21ae14b1-image.png

                                          61fc9cf8-eebc-48bb-9000-f3c3bc2d16d2-image.png

                                          ring-drawer-opengles2-qt6-cpp.pro

                                          QT += core gui openglwidgets
                                          
                                          win32: LIBS += -lopengl32
                                          
                                          CONFIG += c++17
                                          
                                          SOURCES += \
                                              line_drawer.cpp \
                                              main.cpp \
                                              opengl_window.cpp \
                                              ring_drawer.cpp
                                          
                                          HEADERS += \
                                              line_drawer.h \
                                              opengl_window.h \
                                              ring_drawer.h
                                          

                                          main.cpp

                                          #include <QtWidgets/QApplication>
                                          #include "opengl_window.h"
                                          
                                          int main(int argc, char *argv[])
                                          {
                                              QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
                                              QApplication app(argc, argv);
                                              OpenGLWindow w;
                                              w.show();
                                              return app.exec();
                                          }
                                          

                                          ring_drawer.h

                                          #ifndef RING_DRAWER
                                          #define RING_DRAWER
                                          
                                          #include "line_drawer.h"
                                          
                                          class RingDrawer
                                          {
                                          public:
                                              RingDrawer(QOpenGLShaderProgram *program);
                                              ~RingDrawer();
                                          
                                              void draw(const QVector2D &center, float radius,
                                                  const QVector3D &color, int numberOfSegments = 50,
                                                  float thickness = 1.f);
                                              void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
                                          
                                          private:
                                              LineDrawer *m_lineDrawer;
                                          };
                                          
                                          #endif // RING_DRAWER
                                          

                                          ring_drawer.cpp

                                          #include <QtMath>
                                          
                                          #include "ring_drawer.h"
                                          
                                          RingDrawer::RingDrawer(QOpenGLShaderProgram *program)
                                          {
                                              m_lineDrawer = new LineDrawer(program);
                                          }
                                          
                                          RingDrawer::~RingDrawer()
                                          {
                                              delete m_lineDrawer;
                                          }
                                          
                                          void RingDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
                                          {
                                              m_lineDrawer->setProjViewMatrix(projViewMatrix);
                                          }
                                          
                                          void RingDrawer::draw(const QVector2D &center, float radius,
                                              const QVector3D &color, int numberOfSegments, float thickness)
                                          {
                                              float angle = 0.f;
                                              const float angleStep = 360.f / numberOfSegments;
                                          
                                              float x = radius * qCos(qDegreesToRadians(angle));
                                              float y = radius * qSin(qDegreesToRadians(angle));
                                              QVector2D from(center.x() + x, center.y() + y);
                                              angle += angleStep;
                                          
                                              for (int i = 0; i < numberOfSegments; i++)
                                              {
                                                  x = radius * qCos(qDegreesToRadians(angle));
                                                  y = radius * qSin(qDegreesToRadians(angle));
                                                  QVector2D to(center.x() + x, center.y() + y);
                                                  m_lineDrawer->draw(from, to, color, thickness);
                                                  angle += angleStep;
                                                  from = to;
                                              }
                                          }
                                          

                                          opengl_window.h

                                          #ifndef OPENGL_WINDOW
                                          #define OPENGL_WINDOW
                                          
                                          #include <QtMath>
                                          #include <QtGui/QMatrix4x4>
                                          #include <QtGui/QOpenGLFunctions>
                                          #include <QtGui/QQuaternion>
                                          #include <QtGui/QSurfaceFormat>
                                          #include <QtGui/QVector2D>
                                          #include <QtGui/QVector3D>
                                          #include <QtOpenGL/QOpenGLShader>
                                          #include <QtOpenGL/QOpenGLShaderProgram>
                                          #include <QtOpenGL/QOpenGLWindow>
                                          
                                          #include "ring_drawer.h"
                                          
                                          class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
                                          {
                                          public:
                                              OpenGLWindow();
                                          
                                              ~OpenGLWindow();
                                          
                                          private:
                                              void initializeGL() override;
                                              void resizeGL(int w, int h) override;
                                              void paintGL() override;
                                          
                                          private:
                                              QOpenGLShaderProgram m_program;
                                              QMatrix4x4 m_projMatrix;
                                              QMatrix4x4 m_viewMatrix;
                                              QMatrix4x4 m_projViewMatrix;
                                              const float m_worldWidth = 200.f;
                                              const float m_worldHeight = 100.f;
                                              float m_worldAspect = m_worldHeight / m_worldWidth;
                                              int m_viewportX;
                                              int m_viewportY;
                                              int m_viewportWidth;
                                              int m_viewportHeight;
                                              RingDrawer *m_ringDrawer;
                                          };
                                          
                                          #endif // OPENGL_WINDOW
                                          

                                          opengl_window.cpp

                                          #include "opengl_window.h"
                                          
                                          OpenGLWindow::OpenGLWindow()
                                          {
                                              setTitle("OpenGL ES 2.0, Qt6, C++");
                                              resize(600, 300);
                                          
                                              QSurfaceFormat surfaceFormat;
                                              surfaceFormat.setDepthBufferSize(24);
                                              surfaceFormat.setSamples(4);
                                              setFormat(surfaceFormat);
                                          }
                                          
                                          OpenGLWindow::~OpenGLWindow()
                                          {
                                              delete m_ringDrawer;
                                          }
                                          
                                          void OpenGLWindow::initializeGL()
                                          {
                                              initializeOpenGLFunctions();
                                          
                                          
                                              QString vertShaderSrc =
                                                  "attribute vec2 aPosition;\n"
                                                  "uniform mat4 uMvpMatrix;"
                                                  "void main()\n"
                                                  "{\n"
                                                  "    gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0);\n"
                                                  "}\n";
                                          
                                              QString fragShaderSrc =
                                                  "#ifdef GL_ES\n"
                                                  "precision mediump float;\n"
                                                  "#endif\n"
                                                  "uniform vec3 uColor;\n"
                                                  "void main()\n"
                                                  "{\n"
                                                  "    gl_FragColor = vec4(uColor, 1.0);\n"
                                                  "}\n";
                                          
                                              m_program.create();
                                              m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex, vertShaderSrc);
                                              m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment, fragShaderSrc);
                                              m_program.link();
                                              m_program.bind();
                                          
                                              m_ringDrawer = new RingDrawer(&m_program);
                                          
                                              m_viewMatrix.lookAt(QVector3D(0, 0, 1), QVector3D(0, 0, 0), QVector3D(0, 1, 0));
                                          }
                                          
                                          void OpenGLWindow::resizeGL(int w, int h)
                                          {
                                              int deviceW = w * devicePixelRatio();
                                              int deviceH = h * devicePixelRatio();
                                              float deviceAspect = deviceH / (float) deviceW;
                                          
                                              if (deviceAspect > m_worldAspect)
                                              {
                                                  m_viewportWidth = deviceW;
                                                  m_viewportHeight = (int) deviceW * m_worldAspect;
                                                  m_viewportX = 0;
                                                  m_viewportY = (int) (deviceH - m_viewportHeight) / 2.f;
                                              }
                                              else
                                              {
                                                  m_viewportWidth = (int) deviceH / m_worldAspect;
                                                  m_viewportHeight = deviceH;
                                                  m_viewportX = (int) (deviceW - m_viewportWidth) / 2.f;
                                                  m_viewportY = 0;
                                              }
                                              m_projMatrix.setToIdentity();
                                              m_projMatrix.ortho(0.f, m_worldWidth, 0.f, m_worldHeight, 1.f, -1.f);
                                              m_projViewMatrix = m_projMatrix * m_viewMatrix;
                                          
                                              m_ringDrawer->setProjViewMatrix(m_projViewMatrix);
                                          }
                                          
                                          void OpenGLWindow::paintGL()
                                          {
                                              glClear(GL_COLOR_BUFFER_BIT);
                                              // glClearColor(0.2f, 0.2f, 0.2f, 1.f);
                                              glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                              glClear(GL_COLOR_BUFFER_BIT);
                                              glViewport(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                              glScissor(m_viewportX, m_viewportY, m_viewportWidth, m_viewportHeight);
                                              glClearColor(0.82f, 0.87f, 0.97f, 1.f);
                                              glEnable(GL_SCISSOR_TEST);
                                              glClear(GL_COLOR_BUFFER_BIT);
                                              glDisable(GL_SCISSOR_TEST);
                                          
                                              m_ringDrawer->draw(QVector2D(50.f, 70.f), 20.f,
                                                  QVector3D(0.80f, 0.15f, 0.18f));
                                              m_ringDrawer->draw(QVector2D(160.f, 50.f), 25.f,
                                                  QVector3D(0.20f, 0.60f, 0.30f));
                                              m_ringDrawer->draw(QVector2D(100.f, 15.f), 10.f,
                                                  QVector3D(0.25f, 0.31f, 0.85f));
                                          }
                                          

                                          line_drawer.h

                                          #ifndef LINE_DRAWER
                                          #define LINE_DRAWER
                                          
                                          #include <QtGui/QMatrix4x4>
                                          #include <QtGui/QVector2D>
                                          #include <QtGui/QVector3D>
                                          #include <QtOpenGL/QOpenGLBuffer>
                                          #include <QtOpenGL/QOpenGLShaderProgram>
                                          
                                          class LineDrawer
                                          {
                                          public:
                                              LineDrawer(QOpenGLShaderProgram *program);
                                          
                                              void draw(const QVector2D &from, const QVector2D &to,
                                                  const QVector3D &color, float thickness = 1.f);
                                              void setProjViewMatrix(const QMatrix4x4 &projViewMatrix);
                                          
                                          private:
                                              void bind();
                                          
                                          private:
                                              QOpenGLShaderProgram *m_program;
                                              QOpenGLBuffer m_vertPosBuffer;
                                              int m_aPositionLocation;
                                              int m_uMvpMatrixLocation;
                                              int m_uColorLocation;
                                              QMatrix4x4 m_projViewMatrix;
                                              QMatrix4x4 m_modelMatrix;
                                              QMatrix4x4 m_mvpMatrix;
                                          };
                                          
                                          #endif // LINE_DRAWER
                                          

                                          line_drawer.cpp

                                          #include "line_drawer.h"
                                          
                                          LineDrawer::LineDrawer(QOpenGLShaderProgram *program)
                                          {
                                              m_program = program;
                                              m_program->bind();
                                          
                                              m_aPositionLocation = m_program->attributeLocation("aPosition");
                                              m_uMvpMatrixLocation = m_program->uniformLocation("uMvpMatrix");
                                              m_uColorLocation = m_program->uniformLocation("uColor");
                                          
                                              float vertPositions[] = {
                                                  -0.5, -0.5,
                                                  0.5, -0.5,
                                                  -0.5, 0.5,
                                                  0.5, 0.5
                                              };
                                              m_vertPosBuffer.create();
                                              m_vertPosBuffer.bind();
                                              m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
                                          }
                                          
                                          void LineDrawer::setProjViewMatrix(const QMatrix4x4 &projViewMatrix)
                                          {
                                              m_projViewMatrix = projViewMatrix;
                                          }
                                          
                                          void LineDrawer::bind()
                                          {
                                              m_program->bind();
                                              m_vertPosBuffer.bind();
                                              m_program->setAttributeBuffer(m_aPositionLocation, GL_FLOAT, 0, 2);
                                              m_program->enableAttributeArray(m_aPositionLocation);
                                          }
                                          
                                          void LineDrawer::draw(const QVector2D &from, const QVector2D &to,
                                              const QVector3D &color, float thickness)
                                          {
                                              bind();
                                              float centerX, centerY;
                                              QVector3D tempVec;
                                          
                                              if (from.x() > to.x())
                                              {
                                                  centerX = to.x() + std::abs(from.x() - to.x()) / 2.f;
                                              }
                                              else
                                              {
                                                  centerX = from.x() + std::abs(to.x() - from.x()) / 2.f;
                                              }
                                          
                                              if (from.y() > to.y())
                                              {
                                                  centerY = to.y() + std::abs(from.y() - to.y()) / 2.f;
                                              }
                                              else
                                              {
                                                  centerY = from.y() + std::abs(to.y() - from.y()) / 2.f;
                                              }
                                          
                                              tempVec.setX(to.x() - from.x());
                                              tempVec.setY(to.y() - from.y());
                                              float length = tempVec.length();
                                              tempVec.normalize();
                                              QQuaternion quat = QQuaternion::rotationTo(QVector3D(1, 0, 0), tempVec);
                                          
                                              m_modelMatrix.setToIdentity();
                                              m_modelMatrix.translate(QVector3D(centerX, centerY, 0));
                                              m_modelMatrix.rotate(quat);
                                              m_modelMatrix.scale(QVector3D(length, thickness, 1));
                                              m_mvpMatrix = m_projViewMatrix * m_modelMatrix;
                                              m_program->setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);
                                              m_program->setUniformValue(m_uColorLocation, color);
                                              glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
                                          }
                                          
                                          1 Reply Last reply
                                          0

                                          • Login

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