QOpenGLWidget渲染QImage

简单做个记录吧,调了半天终于能显示出来了。.h
#ifndef OPENGL_IMAGE_H
#define OPENGL_IMAGE_H
#include <QGLWidget>
#include <QImage>
#include <QPainter>
#include <queue>
#include <QMutex>
#include <QTimer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QMatrix4x4>


#include <QOpenGLFunctions>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLWidget>

class opengl_image : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit opengl_image(QWidget* parent = 0);
    void   set_image(const QImage & ppp1image);
    void refresh();
    void hide_view(bool state);
    void clear();
signals:
    void signal_refresh();
    void signal_hide(bool state);
    void signal_clear();

public slots:
    void slot_refresh();
    void slot_hide(bool state);
    void slot_clear();
protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int width, int height) override;
    void initializeShaderProgram();
private:
    QOpenGLVertexArrayObject vao;
    QOpenGLBuffer vbo;
    QOpenGLShaderProgram *program;
    GLuint texture;
    QImage image;
     QMutex image_mutex_;
};

#endif

.cpp

#include "opengl_image.h"
#include <QDebug>
#include <iostream>
#include <QDateTime>
opengl_image::opengl_image(QWidget* parent)
    : QOpenGLWidget(parent)
{
    this->setWindowFlags(Qt::FramelessWindowHint); //delete title

     this->setAttribute(Qt::WA_TranslucentBackground, true);

    connect(this, SIGNAL(signal_refresh()), this, SLOT(slot_refresh()), Qt::QueuedConnection);
    connect(this, SIGNAL(signal_hide(bool)), this, SLOT(slot_hide(bool)), Qt::QueuedConnection);
    connect(this, SIGNAL(signal_clear()), this, SLOT(slot_clear()), Qt::QueuedConnection);
}

void opengl_image::set_image(const QImage & ppp1image){
       if (ppp1image.isNull()) {
           qDebug() << "Image is null!";
           return;
       }
       image_mutex_.lock();
       qDebug() << "Image convertToFormat format ="<<image.format() <<endl;
       if (ppp1image.format() != QImage::Format_RGB888) {
           qDebug() << "Image convertToFormat format ="<<image.format() <<endl;
           image = ppp1image.convertToFormat(QImage::Format_RGB888);
           qDebug() << "Image convertToFormat Format_RGB32!"<<endl;
       }
       else
       {
            image = ppp1image;
       }
       image_mutex_.unlock();
       refresh();
    }

void opengl_image::initializeGL()
{
    initializeOpenGLFunctions();
    // 初始化着色器程序
    initializeShaderProgram();
    // 创建 VAO
    vao.create();
    vao.bind();
    // 创建 VBO
    vbo.create();
    vbo.bind();

    // 顶点数据 (位置和纹理坐标)
    const GLfloat vertexData[] = {
        // 第一个三角形: 左下角、右下角、左上角
        -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 0.0f, 0.0f, 0.0f,

        // 第二个三角形: 左上角、右下角、右上角
        -1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
        1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
    };

    vbo.allocate(vertexData, sizeof(vertexData));

    // 顶点属性 (位置)
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 0);
    glEnableVertexAttribArray(0);

    // 顶点属性 (纹理坐标)
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), reinterpret_cast<void*>(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);

    // 解绑 VBO
    vbo.release();

    // 解绑 VAO
    vao.release();

    // 生成纹理
    glGenTextures(1, &texture);

    // 绑定纹理
    glBindTexture(GL_TEXTURE_2D, texture);

    // 设置纹理参数
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

void opengl_image::initializeShaderProgram()
{
    // 创建顶点着色器
    QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
    vertexShader->compileSourceFile("./res/v.glsl");
    if (!vertexShader->isCompiled()) {
        qDebug() << "Vertex shader compilation failed:" << vertexShader->log();
    }

    // 创建片段着色器
    QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment);
    fragmentShader->compileSourceFile("./res/f.glsl");
    if (!fragmentShader->isCompiled()) {
        qDebug() << "Fragment shader compilation failed:" << fragmentShader->log();
    }

    // 创建着色器程序
    program = new QOpenGLShaderProgram;
    program->addShader(vertexShader);
    program->addShader(fragmentShader);
    program->link();

    if (!program->isLinked()) {
        qDebug() << "Shader program linking failed:" << program->log();
    }

    delete vertexShader;
    delete fragmentShader;
}

void opengl_image::paintGL()
{
    // 清除颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT);

    // 绑定着色器程序
    program->bind();

    // 绑定纹理
    glBindTexture(GL_TEXTURE_2D, texture);

    // 上传纹理数据 (这里需要根据你的 QImage 对象进行修改)
    image_mutex_.lock();

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.bits());
    qDebug()<<"width:"<< image.width()<<endl;
    qDebug()<<"height:"<< image.height()<<endl;
    image_mutex_.unlock();
    // 设置投影矩阵 (这里需要根据你的需求进行修改)
    QMatrix4x4 projection;
    projection.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
    program->setUniformValue("projection", projection);

    // 设置模型视图矩阵 (这里需要根据你的需求进行修改)
    QMatrix4x4 modelView;
    program->setUniformValue("modelView", modelView);

    // 绑定 VAO
    vao.bind();

    // 绘制
    glDrawArrays(GL_TRIANGLES, 0, 6);

    // 解绑 VAO
    vao.release();

    // 解绑着色器程序
    program->release();
}

void opengl_image::resizeGL(int width, int height)
{
    // 设置视口
    glViewport(0, 0, width, height);
    // 设置投影矩阵 (根据需要进行修改)
    QMatrix4x4 projection;
    projection.ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
    program->setUniformValue("projection", projection);
}



void opengl_image::slot_clear()
{
   QImage image("./res/black.png");
   set_image(image);
}






void opengl_image::hide_view(bool state)
{
    emit signal_hide(state);
}
void opengl_image::refresh()
{
     emit signal_refresh();
}

void opengl_image::slot_refresh()
{
    update();
}

void opengl_image::slot_hide(bool state)
{
     qDebug()<<"opengl_img_render::slot_hide()"<<endl;
     if(state)
     {
         this->show();
     }
    else
     {
         this->hide();
     }
}

v.glsl

#version 320 es

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 projection;
uniform mat4 modelView;

void main()
{
    gl_Position = projection * modelView * vec4(aPos, 1.0);
    TexCoord = aTexCoord;
}

f.glsl

#version 320 es

precision mediump float;

in vec2 TexCoord;

uniform sampler2D ourTexture;

out vec4 FragColor;

void main()
{
    FragColor = texture(ourTexture, TexCoord);
}

由于是用在Rk3568上的,版本是openes 3.2所以只能这样了,x86平台需要自己修改一下,后面空了把x86的也放出来