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

How to implement QOpenGLBuffer ::PixelPackBuffer



  • Hello,
    I'm just started learning Qt/C++ and now I'm trying to learn how to use PBO using Qt's OpenGL wrapper.

    A quick overview of my idea: I'm using GLSL shaders to process images OffScreen, and showing the results with a QOpenGLBlitter Quad. My current objective is to 'stack' multiple shaders passes to the same image.
    Right now I'm using fbo.toImage to save the offscreen render, and then using it as the texture for the following passes. Now I wanted to use PBO's to retain the fbo render and pass it as the texture for subsequent shader calls.

    Here most of my code.

    QImage imageShader::proImg(const QImage& image,
                             const QImage& tip,
                             const QString& vertexPosVar,
                             const QString& textureCoordVar){
    
        QOpenGLContext context;
    
        QOffscreenSurface offSurface;
        offSurface.setFormat(context.format());
        offSurface.create();
    
        // I'm sharing the context to show the offscreen Render into a
        // QOpenGLTextureBlitter under PaintGL()
        context.setShareContext(imageShader::context()); 
        context.create();
        context.makeCurrent(&offSurface);
    
        m_fbo = new QOpenGLFramebufferObject(image.size());
        m_fbo->bind();
    
        context.functions()->glViewport(0, 0, image.width(), image.height());
    
        QOpenGLShaderProgram program(&context);
        program.addShaderFromSourceFile(QOpenGLShader::Vertex, "path to vertex shader");
        program.addShaderFromSourceFile(QOpenGLShader::Fragment, "path to fragment shader");
        program.link();
        program.bind();
    
        // The next block is basically what I understood how to setup a PBO using
        // Qt's OpenGL wrapper.
        QOpenGLBuffer *pubo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
        pubo->setUsagePattern(QOpenGLBuffer::DynamicCopy);
        pubo->create();
        pubo->bind();
        pubo->map(QOpenGLBuffer::ReadWrite);
        pubo->allocate(image.bits(),image.sizeInBytes());
        pubo->write(0,image.bits(),image.sizeInBytes());
        pubo->unmap();
        pubo->release();
    
        // Testing how to use texture::setData() using straight bytes instead of the
        // baked method of setData(QImage).
        // I believe this is how to use the PBO's content to set the texture using QOpenGL?
        QOpenGLTexture textu(QOpenGLTexture::Target2D);
        textu.setSize(image.width(),image.height());
        textu.setFormat(QOpenGLTexture::RGBA8_UNorm);
        textu.allocateStorage();
        textu.setData(QOpenGLTexture::BGRA,QOpenGLTexture::UInt8,image.bits(),nullptr);
    
        // The texture bellow is a test to see if I was able to set up two textures and
        // change which one the shader should use.
        QOpenGLTexture brush(QOpenGLTexture::Target2D);
        brush.setData(tip);
    
    
        // Using native OpenGL snippets never work. The texture remain black.
    //    GLuint tex;
    //    glGenTextures(1, &tex);
    //    glBindTexture(GL_TEXTURE_2D, tex);
    
    //        glTexImage2D(GL_TEXTURE_2D, 0, 3, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
    //        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    //    glBindTexture( GL_TEXTURE_2D, 0);
    
        GLint brTip = 1;
        brush.bind(brTip);
        GLint oriTxt = 0;
        textu.bind(oriTxt);
    
    //Rest of the code. Following Amin Ahmadi tutorial.
    
    

    I can summarize my questions as follow:

    1. Is this possible to keep a Offscreen render in memory and pass it as texture on a future shader call?
    2. What is the proper setup before writing into a PBO?
    3. QOpenGLBuffer::write will not work using with a simple QImage.bits(). How one write to a Pixel Buffer?
    4. How do you use a written PBO with Texture::setData()?

    I really hope to a least learn how to use QOpenGL::PixelBuffer, because every time I tried implement native OpenGL code in my project it broke it.

    Thanks.



  • I don't have an exact answer, but do you need any of that PBO stuff? You have a QImage and you want a QOpenGLTexture, so you can just do that directly: https://doc.qt.io/qt-5/qopengltexture.html#QOpenGLTexture-1 The texture object can be made directly from a QImage, with no extra steps.

    @Carlos-Roberto said in How to implement QOpenGLBuffer ::PixelPackBuffer:

    Is this possible to keep a Offscreen render in memory and pass it as texture on a future shader call?

    Sure. Render to your QOpenGLFramebufferObject, release it, and it has a texture() method so you can use it as a texture in a render somewhere else.