Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to update a scene on a QQuickItem which renders OpenGL?



  • In order to use OpenGL with QML, I created OpenGlVideoQtQuick which is a QQuickItem and OpenGlVideoQtQuickRenderer which is QObject and QOpenGLFunctions exactly as described here. The only difference is that I added the updateData() function to update the buffers, while in the example a static image is drawn in the screen.

    Here's the crucial part of OpenGlVideoQtQuickRenderer, which is the paint function

    void OpenGlVideoQtQuickRenderer::paint()
    {
        if (this->firstRun) {
            this->firstRun = false;
            //qDebug() << "initializeGL";
            std::cout << "initializing gl" << std::endl;
            //初始化opengl (QOpenGLFunctions继承)函数
            initializeOpenGLFunctions();
    
            //this->m_F  = QOpenGLContext::currentContext()->functions();
    
            //program加载shader(顶点和片元)脚本
            //片元(像素)
            std::cout << program.addShaderFromSourceCode(QOpenGLShader::Fragment, tString2) << std::endl;
            //顶点shader
            std::cout << program.addShaderFromSourceCode(QOpenGLShader::Vertex, vString2) << std::endl;
    
            //设置顶点坐标的变量
            program.bindAttributeLocation("vertexIn",A_VER);
    
            //设置材质坐标
            program.bindAttributeLocation("textureIn",T_VER);
    
            //编译shader
            std::cout << "program.link() = " << program.link() << std::endl;
    
        }
        program.bind();
    
        //传递顶点和材质坐标
        //顶点
        static const GLfloat ver[] = {
            -1.0f,-1.0f,
            1.0f,-1.0f,
            -1.0f, 1.0f,
            1.0f,1.0f
        };
    
        //材质
        static const GLfloat tex[] = {
            0.0f, 1.0f,
            1.0f, 1.0f,
            0.0f, 0.0f,
            1.0f, 0.0f
        };
    
        //顶点
        glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);
        glEnableVertexAttribArray(A_VER);
    
        //材质
        glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);
        glEnableVertexAttribArray(T_VER);
    
        //glUseProgram(&program);
        //从shader获取材质
        unis[0] = program.uniformLocation("tex_y");
        unis[1] = program.uniformLocation("tex_u");
        unis[2] = program.uniformLocation("tex_v");
    
        //创建材质
        glGenTextures(3, texs);
    
        //Y
        glBindTexture(GL_TEXTURE_2D, texs[0]);
        //放大过滤,线性插值   GL_NEAREST(效率高,但马赛克严重)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        //创建材质显卡空间
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
    
        //U
        glBindTexture(GL_TEXTURE_2D, texs[1]);
        //放大过滤,线性插值
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        //创建材质显卡空间
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
    
        //V
        glBindTexture(GL_TEXTURE_2D, texs[2]);
        //放大过滤,线性插值
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        //创建材质显卡空间
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
    
        ///分配材质内存空间
        datas[0] = new unsigned char[width*height];		//Y
        datas[1] = new unsigned char[width*height/4];	//U
        datas[2] = new unsigned char[width*height/4];	//V
    
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texs[0]); //0层绑定到Y材质
        //修改材质内容(复制内存内容)
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, datas[0]);
        //与shader uni遍历关联
        glUniform1i(unis[0], 0);
    
    
        glActiveTexture(GL_TEXTURE0+1);
        glBindTexture(GL_TEXTURE_2D, texs[1]); //1层绑定到U材质
                                               //修改材质内容(复制内存内容)
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width/2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);
        //与shader uni遍历关联
        glUniform1i(unis[1],1);
    
    
        glActiveTexture(GL_TEXTURE0+2);
        glBindTexture(GL_TEXTURE_2D, texs[2]); //2层绑定到V材质
                                               //修改材质内容(复制内存内容)
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);
        //与shader uni遍历关联
        glUniform1i(unis[2], 2);
    
        glDrawArrays(GL_TRIANGLE_STRIP,0,4);
        //this->update();
    
        // Not strictly needed for this example, but generally useful for when
        // mixing with raw OpenGL.
        m_window->resetOpenGLState();//COMMENT OR NOT?
    }
    

    This is the function I'm using to update the buffers that are meant to be painted:

    void OpenGlVideoQtQuickRenderer::updateData(unsigned char**data)
    {
        std::cout << "updating data..." << std::endl;
        memcpy(datas[0], data[0], width*height);
        memcpy(datas[1], data[1], width*height/4);
        memcpy(datas[2], data[2], width*height/4);
        //I should update something here
        
    }
    

    My only problem is that I see the function updateData being called with new data, so the buffers are being updated. However, the screen continues in its initial position (green). I'm sure there must be a function I must call to update everything.

    Is there anything more I need to call in updateData?

    Here's the entire code if someone wants to take a look: https://github.com/lucaszanella/orwell/blob/2aff3b97abd88e6ec2980856718e1c8302d41616/OpenGlVideoQtQuick.cpp#L117

    I've tried every way of updating, but it wont work


Log in to reply