1. 程式人生 > >qt opengl示例

qt opengl示例

#include <QObject>
#include <QOpenGLWidget>
#include <GL/gl.h>
#include <GL/glu.h>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QGLWidget>
#include <QImage>

QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL);

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;

};

#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();
}