代码之家  ›  专栏  ›  技术社区  ›  PPP

qt qml中的opengl,无法更新屏幕上的图像

  •  0
  • PPP  · 技术社区  · 6 年前

    为了在qml中使用opengl,我创建了 OpenGlVideoQtQuick OpenGlVideoQtQuickRenderer 类完全如所述 here . 唯一的区别是我把 updateData() 函数来更新缓冲区,而在示例中,屏幕中会绘制静态图像。

    以下是 openglvideoqtquickrenderer ,这是 paint 功能

    void OpenGlVideoQtQuickRenderer::paint()
    {
        if (this->firstRun) {
            this->firstRun = false;
            //qDebug() << "initializeGL";
            std::cout << "initializing gl" << std::endl;
            //初始化opengl (QOpenGLFunctions继承)函数
            initializeOpenGLFunctions();
    
            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   
    
            //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);
    
        ///分配材质内存空间
    
    
        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?
    }
    

    这是我用来更新要绘制的缓冲区的函数:

    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
    
    }
    

    我唯一的问题是看到updatedata函数被新数据调用,所以缓冲区被更新。但是,屏幕将继续处于初始位置(绿色)。我相信一定有一个函数我必须调用更新一切。

    还有什么我需要打电话进来的吗 updateData ?

    我试过各种方法来更新数据,但图像仍然不会更新

                this->openGlVideoQtQuickRenderer->paint();
                if (this->openGlVideoQtQuick->window()) {
                    std::cout << "window update" << std::endl;
                    this->openGlVideoQtQuick->update();
                    this->openGlVideoQtQuick->window()->update();
                }
    

    但是,如果我调整屏幕大小,我可以看到图像不到一秒钟,它就会消失。

    如果有人想看一看,整个代码是: https://github.com/lucaszanella/orwell/blob/2aff3b97abd88e6ec2980856718e1c8302d41616/OpenGlVideoQtQuick.cpp#L117

    0 回复  |  直到 6 年前
        1
  •  0
  •   PPP    6 年前

    好吧,我试着像你上面看到的那样更新窗口,但是唯一有效的是

    connect(window(), &QQuickWindow::afterRendering, this, &OpenGlVideoQtQuick::update, Qt::DirectConnection);
    

    (为了让这个更新窗口正常工作,我不得不关闭上面的更新窗口)