• 3805阅读
  • 3回复

基于QOpenGLWidget自适应大小显示图片 [复制链接]

上一主题 下一主题
离线729248122
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2018-12-29

一直想用OpenGL来显示图像或者做视频播放器的窗口,网上找了很久,都没有Qt这方面最新的靠谱的例子,大部分都是3D模型上贴图,要不就是各种报错,或者Qt的OpenGL版本不对,自己摸索了好久,终于搞定了,是在QT5.6.3MinGW下编译的,可自适应窗口大小,部分代码如下:

-----MyGLWidget.h------

#ifndef MYGLWIDGET_H

#define MYGLWIDGET_H

#include <QObject>

#include <QOpenGLWidget>

#include <GL/gl.h>

#include <GL/glu.h>

#include <QOpenGLFunctions>

#include <QOpenGLShaderProgram>

#include <QOpenGLTexture>

#include <QGLWidget>

#include <QImage>

class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions

{

    Q_OBJECT

public:

    explicit MyGLWidget(QWidget *parent = 0);

signals:

public slots:

    void initializeGL() Q_DECL_OVERRIDE;

    void resizeGL(int w, int h) Q_DECL_OVERRIDE;

    void paintGL() Q_DECL_OVERRIDE;

    void setBackground(QImage image);

    void initTextures();

    void initShaders();

private:

    QVector<QVector3D> vertices;

    QVector<QVector2D> texCoords;

    QOpenGLShaderProgram program;

    QOpenGLTexture *texture;

    QImage m_image;

    QMatrix4x4 projection;

};

#endif // MYGLWIDGET_H

/////////////////////////////////////////////////////

-------MyGLWidget.cpp--------

#include "myglwidget.h

"#include <QDebug>

#include <QGraphicsOpacityEffect>

MyGLWidget::MyGLWidget(QWidget *parent) : QOpenGLWidget(parent)

{}

void MyGLWidget::initTextures()

{

    if(m_image.isNull())  

  {

        qDebug("Cannot open the image...");      

        QImage dummy(128, 128, QImage::Format_RGB32);//当没找到所需打开的图片时,创建一副128*128大小,深度为32位的位图

        dummy.fill(Qt::green);      

        m_image = dummy;

    }    

    // 加载 Avengers.jpg 图片

    texture = new QOpenGLTexture(m_image);

    // 设置最近的过滤模式,以缩小纹理  

    texture->setMinificationFilter(QOpenGLTexture::Nearest); //滤波

    // 设置双线性过滤模式,以放大纹理

    texture->setMagnificationFilter(QOpenGLTexture::Linear);

    //重复使用纹理坐标    //纹理坐标(1.1, 1.2)与(0.1, 0.2)相同

    texture->setWrapMode(QOpenGLTexture::Repeat);

}

void MyGLWidget::initShaders()

{

    //纹理坐标    

texCoords.append(QVector2D(0, 1)); //左上

texCoords.append(QVector2D(1, 1)); //右上  

texCoords.append(QVector2D(0, 0)); //左下

texCoords.append(QVector2D(1, 0)); //右下    

//顶点坐标

vertices.append(QVector3D(-1, -1, 1));//左下  

vertices.append(QVector3D(1, -1, 1)); //右下

vertices.append(QVector3D(-1, 1, 1)); //左上  

vertices.append(QVector3D(1, 1, 1));  //右上

QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);  

const char *vsrc =

            "attribute vec4 vertex;\n"            

            "attribute vec2 texCoord;\n"

            "varying vec2 texc;\n"            

            "void main(void)\n"

            "{\n"            

             "    gl_Position = vertex;\n"

            "    texc = texCoord;\n"        

            "}\n";

    vshader->compileSourceCode(vsrc);//编译顶点着色器代码

    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);    

    const char *fsrc =

            "uniform sampler2D texture;\n"

           "varying vec2 texc;\n"

            "void main(void)\n"

           "{\n"

            "    gl_FragColor = texture2D(texture,texc);\n"            

           "}\n";

    fshader->compileSourceCode(fsrc); //编译纹理着色器代码

    program.addShader(vshader);//添加顶点着色器  

    program.addShader(fshader);//添加纹理碎片着色器

    program.bindAttributeLocation("vertex", 0);//绑定顶点属性位置

    program.bindAttributeLocation("texCoord", 1);//绑定纹理属性位置

    // 链接着色器管道    

   if (!program.link())

        close();    // 绑定着色器管道

    if (!program.bind())      

        close();

}

void MyGLWidget::initializeGL()

{    

    initializeOpenGLFunctions(); //初始化OPenGL功能函数

    glClearColor(0, 0, 0, 0);    //设置背景为黑色    

    glEnable(GL_CULL_FACE);

    glEnable(GL_TEXTURE_2D);  

    initTextures();

    initShaders();

}

void MyGLWidget::resizeGL(int w, int h)

{

    // 计算窗口横纵比    

    qreal aspect = qreal(w) / qreal(h ? h : 1);

    // 设置近平面值 3.0, 远平面值 7.0, 视场45度

    const qreal zNear = 3.0, zFar = 7.0, fov = 45.0;

    // 重设投影

    projection.setToIdentity();

    // 设置透视投影

    projection.perspective(fov, static_cast<float>(aspect), zNear, zFar);

}

void MyGLWidget::paintGL()

{

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕缓存和深度缓冲

    texture->bind();                                    //绑定纹理

    QMatrix4x4 matrix;

    matrix.translate(0.0, 0.0, -5.0);                   //矩阵变换

    program.enableAttributeArray(0);

    program.enableAttributeArray(1);

    program.setAttributeArray(0, vertices.constData());

    program.setAttributeArray(1, texCoords.constData());

    program.setUniformValue("texture", 0);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

}

void MyGLWidget::setBackground(QImage image)

{    

    m_image = image;

    update();

}

附件: OPenGL_Test.zip (1239 K) 下载次数:67
离线maxlogo

只看该作者 1楼 发表于: 2018-12-29
这不就是纹理贴图而已吗
个人博客:
简书:https://www.jianshu.com/u/14fa805306bd
CSDN:https://blog.csdn.net/qq10097355
思否:https://segmentfault.com/u/lowbees/articles
离线20091001753

只看该作者 2楼 发表于: 2018-12-30
看这代码量,我还是用QLabel显示图片吧。。。
(づ ̄ 3 ̄)づ
离线玖零儛

只看该作者 3楼 发表于: 2019-01-07
QOpenGLWidget你重写下
  1. resizeGl(int w, int h) {glViewport(0, 0, w, h);}

不就可以自适应了么...
快速回复
限100 字节
 
上一个 下一个