Learn OpenGL with Qt——模板測試

由於被這節的標題和內容吸引,先完成了這節的代碼,具體教程等之前的教程更新之後再做

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include "camera.h"

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QTimer>
#include <QTime>
#include <QtMath>
#include <QKeyEvent>
class Widget : public QOpenGLWidget,public QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();
protected:
    virtual void initializeGL() override;
    virtual void resizeGL(int w,int h) override;
    virtual void paintGL() override;

    virtual bool event(QEvent *e) override;

private:
    QVector<float> vertices;
    QVector<QVector3D> cubePositions;
    QOpenGLShaderProgram shaderProgram;
    QOpenGLShaderProgram shaderSingle;
    QOpenGLBuffer VBO;
    QOpenGLVertexArrayObject VAO;
    QTimer timer;

    Camera camera;
};

#endif // WIDGET_H

 widget.cpp

#include "widget.h"
#include <QtMath>

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
    , VBO(QOpenGLBuffer::VertexBuffer)
    , camera(this)
{
    vertices = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 1.0f,
         0.5f, -0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
         0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
         0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };

    timer.setInterval(18);
    connect(&timer,&QTimer::timeout,this,static_cast<void (Widget::*)()>(&Widget::update));
    timer.start();

}

Widget::~Widget()
{
    makeCurrent();

    doneCurrent();
}

void Widget::initializeGL()
{
    this->initializeOpenGLFunctions();        //初始化opengl函數
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/triangle.vert")){     //添加並編譯頂點着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果編譯出錯,打印報錯信息
    }
    if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/triangle.frag")){   //添加並編譯片段着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果編譯出錯,打印報錯信息
    }
    if(!shaderProgram.link()){                      //鏈接着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果鏈接出錯,打印報錯信息
    }

    if(!shaderSingle.addShaderFromSourceFile(QOpenGLShader::Vertex,":/triangle.vert")){     //添加並編譯頂點着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果編譯出錯,打印報錯信息
    }
    if(!shaderSingle.addShaderFromSourceFile(QOpenGLShader::Fragment,":/lamp.frag")){   //添加並編譯片段着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果編譯出錯,打印報錯信息
    }
    if(!shaderSingle.link()){                      //鏈接着色器
        qDebug()<<"ERROR:"<<shaderProgram.log();    //如果鏈接出錯,打印報錯信息
    }

    QOpenGLVertexArrayObject::Binder{&VAO};

    VBO.create();       //生成VBO對象
    VBO.bind();         //將VBO綁定到當前的頂點緩衝對象(QOpenGLBuffer::VertexBuffer)中

    //將頂點數據分配到VBO中,第一個參數爲數據指針,第二個參數爲數據的字節長度
    VBO.allocate(vertices.data(),sizeof(float)*vertices.size());


    //設置頂點解析格式,並啓用頂點
    shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 5);
    shaderProgram.enableAttributeArray("aPos");
    shaderProgram.setAttributeBuffer("aTexCoord", GL_FLOAT,sizeof(GLfloat) * 3, 2, sizeof(GLfloat) * 5);
    shaderProgram.enableAttributeArray("aTexCoord");

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_NOTEQUAL, 1, 0xFF);

    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

    camera.init();

}

void Widget::resizeGL(int w, int h)
{
    this->glViewport(0,0,w,h);                  //定義視口區域
}

void Widget::paintGL()
{
    this->glClearColor(0.1f,0.5f,0.7f,1.0f);                       //設置清屏顏色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);       //清除顏色緩存和深度緩存
    float time=QTime::currentTime().msecsSinceStartOfDay()/1000.0;
    QMatrix4x4 model;
    QMatrix4x4 projection;
    projection.perspective(45.0f,width()/(float)height(),0.1f,100.0f);

    shaderSingle.bind();
    shaderSingle.setUniformValue("view",camera.getView());
    shaderSingle.setUniformValue("projection",projection);

    shaderProgram.bind();
    shaderProgram.setUniformValue("view",camera.getView());
    shaderProgram.setUniformValue("projection",projection);

    glStencilFunc(GL_ALWAYS, 1, 0xFF);
    glStencilMask(0xFF);

    QOpenGLVertexArrayObject::Binder{&VAO};

    shaderProgram.setUniformValue("model",model);
    this->glDrawArrays(GL_TRIANGLES, 0, 36);


    glStencilMask(0x00);

    glDisable(GL_DEPTH_TEST);
    glStencilFunc(GL_NOTEQUAL, 1, 0xFF);

    shaderSingle.bind();
    GLfloat scale = 1.1;
    model.scale(scale,scale,scale);
    shaderSingle.setUniformValue("model",model);

    glDrawArrays(GL_TRIANGLES, 0, 36);
    glStencilMask(0xFF);
    glEnable(GL_DEPTH_TEST);
}

bool Widget::event(QEvent *e)
{
    camera.handle(e);
    return QWidget::event(e);   //調用父類的事件分發函數
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章