当前位置: 首页 > 工具软件 > Basic Pitch > 使用案例 >

QT学习OpenGL序列:Hello Basic Lighting

慕麒
2023-12-01

我们将学习OpenGL中的几种不同环境光照

(1) 头文件

#ifndef COPENGLWIDGETAMBIENT_H
#define COPENGLWIDGETAMBIENT_H

/*
 * 控件名称:Hello Basic Lighting
 * 环境光照(Ambient)
 *
 * 注意:STD C++ Version >= C++11
 *
 * Author: hsw
 *
*/


#include <QPainter>
#include <QPaintEngine>
#include <QKeyEvent>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLWidget>          // OpenGLWidget
#include <QOpenGLFunctions>       // OpenGL函数
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QMatrix4x4>


class COpenGLWidgetAmbient : public QOpenGLWidget, public QOpenGLFunctions
{
    Q_OBJECT

    enum class RS_MOUSE_PRESS_TYPE : int
    {
        RS_MOUSE_PRESS_NON = 0,
        RS_MOUSE_PRESS_LEFT   ,
        RS_MOUSE_PRESS_RIGHT  ,
        RS_MOUSE_PRESS_MID
    };

public:
    COpenGLWidgetAmbient(QWidget* parent);
    ~COpenGLWidgetAmbient();
protected:
    void initializeGL() override;
    void resizeGL(int width, int height) override;
    void paintGL() override;
protected:
    bool eventFilter(QObject *obj, QEvent *event);
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void wheelEvent(QWheelEvent* event);
signals:
    void m_openglCloseSgn();
private:
    void m_paintCubeObject();
    void m_paintCubeLight();
private:
    QWidget*    m_pParent;
private:
    QOpenGLShader*        m_pVShaderObject;       // 物体的顶点着色器
    QOpenGLShader*        m_pVShaderLight;        // 光源的顶点着色器

    QOpenGLShader*        m_pFShaderObject;       // 物体的分片着色器
    QOpenGLShader*        m_pFShaderLight;        // 光源的顶点着色器

    QOpenGLShaderProgram* m_pShaderObjectProgram; // 管理物体着色器
    QOpenGLShaderProgram* m_pShaderLightProgram;  // 管理光源着色器

    QOpenGLBuffer         m_vBufferObject;        // 物体的顶点数据缓冲对象
    QOpenGLBuffer         m_vBufferLight;         // 光源的顶点数据缓冲对象

    int                   m_vertexObjectAttr;
    int                   m_vertexLightAttr;
private:
    // 相机的参数
    QVector3D             m_cameraPos;
    QVector3D             m_cameraFront;
    QVector3D             m_cameraUp;
    QVector3D             m_cameraRight;
    float                 m_pitch;
    float                 m_yaw;
    float                 m_fov;

    // 模型变换矩阵 + 视图变换矩阵 + 投影变换矩阵
    QMatrix4x4            m_modelObjectMatrix;
    QMatrix4x4            m_modelLightMatrix;
    QMatrix4x4            m_viewMatrix;
    QMatrix4x4            m_projectionMatrix;

    // 鼠标相关的数据
    QPointF               m_leftMousePressPos;
    QPointF               m_rightMousePressPos;
    QPointF               m_midMousePressPos;

    QPointF               m_leftMouseMovePos;
    QPointF               m_rightMouseMovePos;
    QPointF               m_midMouseMovePos;

    RS_MOUSE_PRESS_TYPE   m_mousePressType;
};

#endif // COPENGLWIDGETAMBIENT_H
#ifndef COPENGLWIDGETDIFFUSE_H
#define COPENGLWIDGETDIFFUSE_H

/*
 * 控件名称:Hello Basic Lighting
 * 环境光照(Ambient) + 漫反射(Diffuse)
 *
 * 注意:STD C++ Version >= C++11
 *
 * Author: hsw
 *
*/


#include <QPainter>
#include <QPaintEngine>
#include <QKeyEvent>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLWidget>          // OpenGLWidget
#include <QOpenGLFunctions>       // OpenGL函数
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QMatrix4x4>


class COpenGLWidgetDiffuse : public QOpenGLWidget, public QOpenGLFunctions
{
    Q_OBJECT

    enum class RS_MOUSE_PRESS_TYPE : int
    {
        RS_MOUSE_PRESS_NON = 0,
        RS_MOUSE_PRESS_LEFT   ,
        RS_MOUSE_PRESS_RIGHT  ,
        RS_MOUSE_PRESS_MID
    };

public:
    COpenGLWidgetDiffuse(QWidget* parent);
    ~COpenGLWidgetDiffuse();
protected:
    void initializeGL() override;
    void resizeGL(int width, int height) override;
    void paintGL() override;
protected:
    bool eventFilter(QObject *obj, QEvent *event);
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void wheelEvent(QWheelEvent* event);
signals:
    void m_openglCloseSgn();
private:
    void m_paintCubeObject();
    void m_paintCubeLight();
private:
    QWidget*    m_pParent;
private:
    QOpenGLShader*        m_pVShaderObject;       // 物体的顶点着色器
    QOpenGLShader*        m_pVShaderLight;        // 光源的顶点着色器

    QOpenGLShader*        m_pFShaderObject;       // 物体的分片着色器
    QOpenGLShader*        m_pFShaderLight;        // 光源的顶点着色器

    QOpenGLShaderProgram* m_pShaderObjectProgram; // 管理物体着色器
    QOpenGLShaderProgram* m_pShaderLightProgram;  // 管理光源着色器

    QOpenGLBuffer         m_vBufferObject;        // 物体的顶点数据缓冲对象
    QOpenGLBuffer         m_vBufferLight;         // 光源的顶点数据缓冲对象

    int                   m_vertexObjectAttr;
    int                   m_vertexObjectNormalAttr;
    int                   m_vertexLightAttr;
private:
    // 相机的参数
    QVector3D             m_cameraPos;
    QVector3D             m_cameraFront;
    QVector3D             m_cameraUp;
    QVector3D             m_cameraRight;
    float                 m_pitch;
    float                 m_yaw;
    float                 m_fov;

    // 模型变换矩阵 + 视图变换矩阵 + 投影变换矩阵
    QMatrix4x4            m_modelObjectMatrix;
    QMatrix4x4            m_modelLightMatrix;
    QMatrix4x4            m_viewMatrix;
    QMatrix4x4            m_projectionMatrix;

    // 鼠标相关的数据
    QPointF               m_leftMousePressPos;
    QPointF               m_rightMousePressPos;
    QPointF               m_midMousePressPos;

    QPointF               m_leftMouseMovePos;
    QPointF               m_rightMouseMovePos;
    QPointF               m_midMouseMovePos;

    RS_MOUSE_PRESS_TYPE   m_mousePressType;
};

#endif // COPENGLWIDGETDIFFUSE_H
#ifndef COpenGLWidgetDiffuseNormal_H
#define COpenGLWidgetDiffuseNormal_H

/*
 * 控件名称:Hello Basic Lighting
 * 环境光照(Ambient) + 漫反射(Diffuse)
 *
 * 由于法线方向会在物体进行非等比例缩放时不垂直物体表面
 *
 * 注意:STD C++ Version >= C++11
 *
 * Author: hsw
 *
*/

#include <QPainter>
#include <QPaintEngine>
#include <QKeyEvent>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLWidget>          // OpenGLWidget
#include <QOpenGLFunctions>       // OpenGL函数
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QMatrix4x4>


class COpenGLWidgetDiffuseNormal : public QOpenGLWidget, public QOpenGLFunctions
{
    Q_OBJECT

    enum class RS_MOUSE_PRESS_TYPE : int
    {
        RS_MOUSE_PRESS_NON = 0,
        RS_MOUSE_PRESS_LEFT   ,
        RS_MOUSE_PRESS_RIGHT  ,
        RS_MOUSE_PRESS_MID
    };

public:
    COpenGLWidgetDiffuseNormal(QWidget* parent);
    ~COpenGLWidgetDiffuseNormal();
protected:
    void initializeGL() override;
    void resizeGL(int width, int height) override;
    void paintGL() override;
protected:
    bool eventFilter(QObject *obj, QEvent *event);
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void wheelEvent(QWheelEvent* event);
signals:
    void m_openglCloseSgn();
private:
    void m_paintCubeObject();
    void m_paintCubeLight();
private:
    QWidget*    m_pParent;
private:
    QOpenGLShader*        m_pVShaderObject;       // 物体的顶点着色器
    QOpenGLShader*        m_pVShaderLight;        // 光源的顶点着色器

    QOpenGLShader*        m_pFShaderObject;       // 物体的分片着色器
    QOpenGLShader*        m_pFShaderLight;        // 光源的顶点着色器

    QOpenGLShaderProgram* m_pShaderObjectProgram; // 管理物体着色器
    QOpenGLShaderProgram* m_pShaderLightProgram;  // 管理光源着色器

    QOpenGLBuffer         m_vBufferObject;        // 物体的顶点数据缓冲对象
    QOpenGLBuffer         m_vBufferLight;         // 光源的顶点数据缓冲对象

    int                   m_vertexObjectAttr;
    int                   m_vertexObjectNormalAttr;
    int                   m_vertexLightAttr;
private:
    // 相机的参数
    QVector3D             m_cameraPos;
    QVector3D             m_cameraFront;
    QVector3D             m_cameraUp;
    QVector3D             m_cameraRight;
    float                 m_pitch;
    float                 m_yaw;
    float                 m_fov;

    // 模型变换矩阵 + 视图变换矩阵 + 投影变换矩阵
    QMatrix4x4            m_modelObjectMatrix;
    QMatrix4x4            m_modelLightMatrix;
    QMatrix3x3            m_modelObjectNormalMatrix;
    QMatrix4x4            m_viewMatrix;
    QMatrix4x4            m_projectionMatrix;

    // 鼠标相关的数据
    QPointF               m_leftMousePressPos;
    QPointF               m_rightMousePressPos;
    QPointF               m_midMousePressPos;

    QPointF               m_leftMouseMovePos;
    QPointF               m_rightMouseMovePos;
    QPointF               m_midMouseMovePos;

    RS_MOUSE_PRESS_TYPE   m_mousePressType;
};

#endif // COpenGLWidgetDiffuseNormal_H
#ifndef COpenGLWidgetSpecular_H
#define COpenGLWidgetSpecular_H

/*
 * 控件名称:Hello Basic Lighting
 * 环境光照(Ambient) + 漫反射(Diffuse) + 镜面反射(Specular)
 *
 * 由于法线方向会在物体进行非等比例缩放时不垂直物体表面
 *
 * 注意:STD C++ Version >= C++11
 *
 * Author: hsw
 *
*/

#include <QPainter>
#include <QPaintEngine>
#include <QKeyEvent>
#include <QDebug>
#include <QCoreApplication>
#include <QOpenGLWidget>          // OpenGLWidget
#include <QOpenGLFunctions>       // OpenGL函数
#include <QOpenGLShaderProgram>
#include <QOpenGLShader>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QMatrix4x4>


class COpenGLWidgetSpecular : public QOpenGLWidget, public QOpenGLFunctions
{
    Q_OBJECT

    enum class RS_MOUSE_PRESS_TYPE : int
    {
        RS_MOUSE_PRESS_NON = 0,
        RS_MOUSE_PRESS_LEFT   ,
        RS_MOUSE_PRESS_RIGHT  ,
        RS_MOUSE_PRESS_MID
    };

public:
    COpenGLWidgetSpecular(QWidget* parent);
    ~COpenGLWidgetSpecular();
protected:
    void initializeGL() override;
    void resizeGL(int width, int height) override;
    void paintGL() override;
protected:
    bool eventFilter(QObject *obj, QEvent *event);
    void mousePressEvent(QMouseEvent* event);
    void mouseMoveEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void wheelEvent(QWheelEvent* event);
signals:
    void m_openglCloseSgn();
private:
    void m_paintCubeObject();
    void m_paintCubeLight();
private:
    QWidget*    m_pParent;
private:
    QOpenGLShader*        m_pVShaderObject;       // 物体的顶点着色器
    QOpenGLShader*        m_pVShaderLight;        // 光源的顶点着色器

    QOpenGLShader*        m_pFShaderObject;       // 物体的分片着色器
    QOpenGLShader*        m_pFShaderLight;        // 光源的顶点着色器

    QOpenGLShaderProgram* m_pShaderObjectProgram; // 管理物体着色器
    QOpenGLShaderProgram* m_pShaderLightProgram;  // 管理光源着色器

    QOpenGLBuffer         m_vBufferObject;        // 物体的顶点数据缓冲对象
    QOpenGLBuffer         m_vBufferLight;         // 光源的顶点数据缓冲对象

    int                   m_vertexObjectAttr;
    int                   m_vertexObjectNormalAttr;
    int                   m_vertexLightAttr;
private:
    // 相机的参数
    QVector3D             m_cameraPos;
    QVector3D             m_cameraFront;
    QVector3D             m_cameraUp;
    QVector3D             m_cameraRight;
    float                 m_pitch;
    float                 m_yaw;
    float                 m_fov;

    // 模型变换矩阵 + 视图变换矩阵 + 投影变换矩阵
    QMatrix4x4            m_modelObjectMatrix;
    QMatrix4x4            m_modelLightMatrix;
    QMatrix3x3            m_modelObjectNormalMatrix;
    QMatrix4x4            m_viewMatrix;
    QMatrix4x4            m_projectionMatrix;

    // 鼠标相关的数据
    QPointF               m_leftMousePressPos;
    QPointF               m_rightMousePressPos;
    QPointF               m_midMousePressPos;

    QPointF               m_leftMouseMovePos;
    QPointF               m_rightMouseMovePos;
    QPointF               m_midMouseMovePos;

    RS_MOUSE_PRESS_TYPE   m_mousePressType;
};

#endif // COpenGLWidgetSpecular_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "crsopenglwidgetambient.h"
#include "crsopenglwidgetdiffuse.h"
#include "crsopenglwidgetdiffusenormal.h"
#include "crsopenglwidgetspecular.h"

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
private:
    COpenGLWidgetAmbient*       m_pRSOpenGLWidgetAmbient;
    COpenGLWidgetDiffuse*       m_pRSOpenGLWidgetDiffuse;
    COpenGLWidgetDiffuseNormal* m_pRSOpenGLWidgetDiffuseNormal;
    COpenGLWidgetSpecular*      m_pRSOpenGLWidgetSpecular;
};

#endif // MAINWINDOW_H

(2) CPP文件

#include "crsopenglwidgetambient.h"

COpenGLWidgetAmbient::COpenGLWidgetAmbient(QWidget *parent) : QOpenGLWidget(parent)
{
    m_pParent = parent;

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    QSurfaceFormat::setDefaultFormat(format);
}


COpenGLWidgetAmbient::~COpenGLWidgetAmbient()
{
    delete m_pVShaderObject;
    delete m_pVShaderLight;

    delete m_pFShaderObject;
    delete m_pFShaderLight;

    delete m_pShaderObjectProgram;
    delete m_pShaderLightProgram;
}



void COpenGLWidgetAmbient::initializeGL()
{
     bool ret;
    // 初始化OpenGL函数
    initializeOpenGLFunctions();

    // 初始化相机
    m_cameraPos   = QVector3D(0.0F, 0.0f, 10.0f);
    m_cameraFront = QVector3D(0.0f, 0.0f, -1.0f);
    m_cameraUp    = QVector3D(0.0f, 1.0f,  0.0f);
    m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

    m_fov         = 45;
    m_pitch       =  0.0f;
    m_yaw         = -90.0f;


    QSize size = this->size();

    m_projectionMatrix = QMatrix4x4();

    m_projectionMatrix.perspective(45.0f, (float)size.width() / (float)size.height(), 0.1f, 100.f);

    m_modelObjectMatrix = QMatrix4x4();

    m_modelLightMatrix  = QMatrix4x4();
    m_modelLightMatrix.translate(QVector3D(1.2f, 1.0f, 2.0f));
    m_modelLightMatrix.scale(0.2f);

    // 初始化物体的顶点着色器
    m_pVShaderObject = new QOpenGLShader(QOpenGLShader::Vertex);
    QString vShaderObjectSrc;

    vShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("}\n");


    m_pVShaderObject->compileSourceCode(vShaderObjectSrc);


    // 初始化物体的片段着色器
    m_pFShaderObject = new QOpenGLShader(QOpenGLShader::Fragment);
    QString fShaderObjectSrc;

    fShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("uniform vec3 objectColor; \n")
            + QString("uniform vec3 lightColor; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    float ambientStrength = 0.3f; \n")
            + QString("    vec3 ambient = ambientStrength * lightColor; \n")
            + QString("    vec3 result  = ambient * objectColor; \n")
            + QString("    FragColor    = vec4(result, 1.0); \n")
            + QString("}\n");

    m_pFShaderObject->compileSourceCode(fShaderObjectSrc);

    m_pShaderObjectProgram = new QOpenGLShaderProgram;
    m_pShaderObjectProgram->addShader(m_pVShaderObject);
    m_pShaderObjectProgram->addShader(m_pFShaderObject);

    ret = m_pShaderObjectProgram->link();

    if(ret == false)
    {
        qDebug() << "Object Shader Link Failed !";
        qDebug() << m_pShaderObjectProgram->log();
    }

    m_vertexObjectAttr = m_pShaderObjectProgram->attributeLocation("aPos");

    // 初始化光源的顶点着色器
    m_pVShaderLight = new QOpenGLShader(QOpenGLShader::Vertex);

    QString vShaderLightSrc;

    vShaderLightSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("}\n");

    m_pVShaderLight->compileSourceCode(vShaderLightSrc);

    // 初始化光源的片段着色器
    m_pFShaderLight = new QOpenGLShader(QOpenGLShader::Fragment);

    QString fShaderLightSrc;

    fShaderLightSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n")
            + QString("}\n");

    m_pFShaderLight->compileSourceCode(fShaderLightSrc);

    m_pShaderLightProgram = new QOpenGLShaderProgram;
    m_pShaderLightProgram->addShader(m_pVShaderLight);
    m_pShaderLightProgram->addShader(m_pFShaderLight);

    ret = m_pShaderLightProgram->link();

    if(ret == false)
    {
        qDebug() << "Light Shader Link Failed !";
        qDebug() << m_pShaderLightProgram->log();
    }


     m_vertexLightAttr  = m_pShaderLightProgram->attributeLocation("aPos");


}

void COpenGLWidgetAmbient::resizeGL(int width, int height)
{
    // TODO...
    m_projectionMatrix = QMatrix4x4();
    m_projectionMatrix.perspective(45.0f, (float)width / (float)height, 0.1f, 100.f);
}

void COpenGLWidgetAmbient::paintGL()
{
    QPainter painter;

    painter.begin(this);

    painter.beginNativePainting();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    // Updata ViewMatrix
    m_viewMatrix.lookAt(m_cameraPos, m_cameraPos + m_cameraFront, m_cameraUp);


    if(m_pShaderObjectProgram->isLinked())
    {
        m_pShaderObjectProgram->bind();
        m_paintCubeObject();
        m_pShaderObjectProgram->release();
    }

    if(m_pShaderLightProgram->isLinked())
    {
        m_pShaderLightProgram->bind();
        m_paintCubeLight();
        m_pShaderLightProgram->release();
    }

    glDisable(GL_DEPTH_TEST);

    painter.endNativePainting();

    // QT 绘制文字信息
    painter.setPen(Qt::green);
    QString textInfo = QString("按\"ESC\"退出");
    painter.drawText(25, 25, textInfo);

    painter.end();

    update();
}


void COpenGLWidgetAmbient::m_paintCubeObject()
{
    if(!m_vBufferObject.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,

            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,

            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,

            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
        };

        m_vBufferObject.create();
        m_vBufferObject.bind();
        m_vBufferObject.allocate(36 * 3 * sizeof(float));
        m_vBufferObject.write(0, afVertices, sizeof(afVertices));
        m_vBufferObject.release();
    }

    // Uniform
    m_pShaderObjectProgram->setUniformValue("objectColor", QVector3D(1.0f, 0.5f, 0.31f));
    m_pShaderObjectProgram->setUniformValue("lightColor" , QVector3D(1.0f, 1.0f, 1.0f));

    m_pShaderObjectProgram->setUniformValue("model"      , m_modelObjectMatrix);
    m_pShaderObjectProgram->setUniformValue("view"       , m_viewMatrix);
    m_pShaderObjectProgram->setUniformValue("projection" , m_projectionMatrix);


    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectAttr);
    m_vBufferObject.bind();
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectAttr, GL_FLOAT, 0, 3, 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferObject.release();
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectAttr);
}

void COpenGLWidgetAmbient::m_paintCubeLight()
{
    if(!m_vBufferLight.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,

            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,

            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,

            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
        };

        m_vBufferLight.create();
        m_vBufferLight.bind();
        m_vBufferLight.allocate(36 * 3 * sizeof(float));
        m_vBufferLight.write(0, afVertices, sizeof(afVertices));
        m_vBufferLight.release();
    }

    // Uniform    
    m_pShaderLightProgram->setUniformValue("model"     , m_modelLightMatrix);
    m_pShaderLightProgram->setUniformValue("view"      , m_viewMatrix);
    m_pShaderLightProgram->setUniformValue("projection", m_projectionMatrix);


    m_pShaderLightProgram->enableAttributeArray(m_vertexLightAttr);
    m_vBufferLight.bind();
    m_pShaderLightProgram->setAttributeBuffer(m_vertexLightAttr, GL_FLOAT, 0, 3, 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferLight.release();
    m_pShaderLightProgram->disableAttributeArray(m_vertexLightAttr);
}


bool COpenGLWidgetAmbient::eventFilter(QObject *obj, QEvent * event)
{
    if(obj == m_pParent)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent != NULL)
        {
            if(keyEvent->type() == QKeyEvent::KeyPress)
            {
                if(keyEvent->key() == Qt::Key_Escape)
                {
                    qDebug() << "Close QOpenGLWidget";
                    QCoreApplication::quit();
                }
            }
        }
    }

    return false;
}

void COpenGLWidgetAmbient::mousePressEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT;
        m_leftMousePressPos = event->pos();
    }
    else if(event->button() == Qt::RightButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT;
        m_rightMousePressPos = event->pos();
    }
    else if(event->button() == Qt::MidButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID;
        m_midMousePressPos = event->pos();
    }
}

void COpenGLWidgetAmbient::mouseMoveEvent(QMouseEvent* event)
{
    if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT)
    {
        m_leftMouseMovePos = event->pos();

        float diffX = m_leftMouseMovePos.x() - m_leftMousePressPos.x();
        float diffY = m_leftMouseMovePos.y() - m_leftMousePressPos.y();

        float sensitivity = 0.05f;
        m_yaw   -= diffX * sensitivity;
        m_pitch += diffY * sensitivity;

        if(m_pitch > 89.0f)
        {
            m_pitch = 89.0f;
        }
        else if(m_pitch < -89.0f)
        {
            m_pitch = -89.0f;
        }

        QVector3D front;

        front.setX(cos(m_pitch / 180.0f * M_PI) * cos(m_yaw / 180.0f * M_PI));
        front.setY(sin(m_pitch / 180.0f * M_PI));
        front.setZ(cos(m_pitch / 180.0f * M_PI) * sin(m_yaw / 180.0f * M_PI));
        front.normalized();

        // qDebug() << "front = " << front;

        m_cameraFront = front;

        m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

        m_cameraUp    = QVector3D::crossProduct(m_cameraRight, m_cameraFront).normalized();


        m_leftMousePressPos = m_leftMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT)
    {
        m_rightMouseMovePos = event->pos();


        m_rightMousePressPos = m_rightMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID)
    {
        m_midMouseMovePos = event->pos();

        m_midMousePressPos = m_midMouseMovePos;
    }
}

void COpenGLWidgetAmbient::mouseReleaseEvent(QMouseEvent *event)
{
    m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_NON;
}

void COpenGLWidgetAmbient::wheelEvent(QWheelEvent* event)
{
    if(event->delta() > 0)
    {
        m_fov -= 2.5f;
    }
    else if(event->delta() < 0)
    {
        m_fov += 2.5f;
    }

    if(m_fov < 1.0f)
    {
        m_fov = 1.0f;
    }
    else if(m_fov > 45.0f)
    {
        m_fov = 45.0f;
    }
}
#include "crsopenglwidgetdiffuse.h"

COpenGLWidgetDiffuse::COpenGLWidgetDiffuse(QWidget *parent) : QOpenGLWidget(parent)
{
    m_pParent = parent;

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    QSurfaceFormat::setDefaultFormat(format);
}


COpenGLWidgetDiffuse::~COpenGLWidgetDiffuse()
{
    delete m_pVShaderObject;
    delete m_pVShaderLight;

    delete m_pFShaderObject;
    delete m_pFShaderLight;

    delete m_pShaderObjectProgram;
    delete m_pShaderLightProgram;

}



void COpenGLWidgetDiffuse::initializeGL()
{
     bool ret;
    // 初始化OpenGL函数
    initializeOpenGLFunctions();

    // 初始化相机
    m_cameraPos   = QVector3D(0.0F, 0.0f, 10.0f);
    m_cameraFront = QVector3D(0.0f, 0.0f, -1.0f);
    m_cameraUp    = QVector3D(0.0f, 1.0f,  0.0f);
    m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

    m_fov         = 45;
    m_pitch       =  0.0f;
    m_yaw         = -90.0f;

    QSize size = this->size();

    m_projectionMatrix = QMatrix4x4();

    m_projectionMatrix.perspective(45.0f, (float)size.width() / (float)size.height(), 0.1f, 100.f);

    m_modelObjectMatrix = QMatrix4x4();

    m_modelLightMatrix  = QMatrix4x4();
    m_modelLightMatrix.translate(QVector3D(1.2f, 1.0f, 2.0f)); // 注意: QVector3D(1.2f, 1.0f, 2.0f)为光源的位置
    m_modelLightMatrix.scale(0.2f);



    // 初始化物体的顶点着色器
    m_pVShaderObject = new QOpenGLShader(QOpenGLShader::Vertex);
    QString vShaderObjectSrc;

    vShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("layout (location = 1) in vec3 aNormal; \n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("out vec3 Normal; \n")
            + QString("out vec3 FragPos; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("    FragPos     = vec3(model * vec4(aPos, 1.0f)); \n")
            + QString("    Normal      = aNormal; \n")
            + QString("}\n");


    m_pVShaderObject->compileSourceCode(vShaderObjectSrc);


    // 初始化物体的片段着色器
    m_pFShaderObject = new QOpenGLShader(QOpenGLShader::Fragment);
    QString fShaderObjectSrc;

    fShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("in vec3 FragPos; \n")
            + QString("in vec3 Normal; \n")
            + QString("uniform vec3 objectColor; \n")
            + QString("uniform vec3 lightColor; \n")
            + QString("uniform vec3 lightPos; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    float ambientStrength = 0.3f; \n")
            + QString("    vec3 ambient = ambientStrength * lightColor; \n")
            + QString("    vec3 norm = normalize(Normal); \n")
            + QString("    vec3 lightDir = normalize(lightPos - FragPos); \n")
            + QString("    float diff = max(dot(norm, lightDir), 0.0); \n")
            + QString("    vec3 diffuse = diff * lightColor; \n")
            + QString("    vec3 result  = (ambient + diffuse) * objectColor; \n")
            + QString("    FragColor    = vec4(result, 1.0); \n")
            + QString("}\n");

    m_pFShaderObject->compileSourceCode(fShaderObjectSrc);

    m_pShaderObjectProgram = new QOpenGLShaderProgram;
    m_pShaderObjectProgram->addShader(m_pVShaderObject);
    m_pShaderObjectProgram->addShader(m_pFShaderObject);

    ret = m_pShaderObjectProgram->link();

    if(ret == false)
    {
        qDebug() << "Object Shader Link Failed !";
        qDebug() << m_pShaderObjectProgram->log();
    }

    m_vertexObjectAttr       = m_pShaderObjectProgram->attributeLocation("aPos");
    m_vertexObjectNormalAttr = m_pShaderObjectProgram->attributeLocation("aNormal");

    // 初始化光源的顶点着色器
    m_pVShaderLight = new QOpenGLShader(QOpenGLShader::Vertex);

    QString vShaderLightSrc;

    vShaderLightSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("}\n");

    m_pVShaderLight->compileSourceCode(vShaderLightSrc);

    // 初始化光源的片段着色器
    m_pFShaderLight = new QOpenGLShader(QOpenGLShader::Fragment);

    QString fShaderLightSrc;

    fShaderLightSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n")
            + QString("}\n");

    m_pFShaderLight->compileSourceCode(fShaderLightSrc);

    m_pShaderLightProgram = new QOpenGLShaderProgram;
    m_pShaderLightProgram->addShader(m_pVShaderLight);
    m_pShaderLightProgram->addShader(m_pFShaderLight);

    ret = m_pShaderLightProgram->link();

    if(ret == false)
    {
        qDebug() << "Light Shader Link Failed !";
        qDebug() << m_pShaderLightProgram->log();
    }


     m_vertexLightAttr  = m_pShaderLightProgram->attributeLocation("aPos");


}

void COpenGLWidgetDiffuse::resizeGL(int width, int height)
{
    // TODO...
    m_projectionMatrix = QMatrix4x4();
    m_projectionMatrix.perspective(45.0f, (float)width / (float)height, 0.1f, 100.f);
}

void COpenGLWidgetDiffuse::paintGL()
{
    QPainter painter;

    painter.begin(this);

    painter.beginNativePainting();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    // Updata ViewMatrix
    m_viewMatrix.lookAt(m_cameraPos, m_cameraPos + m_cameraFront, m_cameraUp);


    if(m_pShaderObjectProgram->isLinked())
    {
        m_pShaderObjectProgram->bind();
        m_paintCubeObject();
        m_pShaderObjectProgram->release();
    }

    if(m_pShaderLightProgram->isLinked())
    {
        m_pShaderLightProgram->bind();
        m_paintCubeLight();
        m_pShaderLightProgram->release();
    }

    glDisable(GL_DEPTH_TEST);

    painter.endNativePainting();

    // QT 绘制文字信息
    painter.setPen(Qt::green);
    QString textInfo = QString("按\"ESC\"退出");
    painter.drawText(25, 25, textInfo);

    painter.end();

    update();
}


void COpenGLWidgetDiffuse::m_paintCubeObject()
{
    if(!m_vBufferObject.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

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

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

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

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

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

        m_vBufferObject.create();
        m_vBufferObject.bind();
        m_vBufferObject.allocate(36 * 6 * sizeof(float));
        m_vBufferObject.write(0, afVertices, sizeof(afVertices));
        m_vBufferObject.release();
    }

    // Uniform
    m_pShaderObjectProgram->setUniformValue("objectColor", QVector3D(1.0f, 0.5f, 0.31f));
    m_pShaderObjectProgram->setUniformValue("lightColor" , QVector3D(1.0f, 1.0f, 1.0f));
    m_pShaderObjectProgram->setUniformValue("lightPos", QVector3D(1.2f, 1.0f, 2.0f));

    m_pShaderObjectProgram->setUniformValue("model"      , m_modelObjectMatrix);
    m_pShaderObjectProgram->setUniformValue("view"       , m_viewMatrix);
    m_pShaderObjectProgram->setUniformValue("projection" , m_projectionMatrix);


    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectAttr);
    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectNormalAttr);
    m_vBufferObject.bind();
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectAttr      , GL_FLOAT, 0                , 3, 6 * sizeof(float));
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectNormalAttr, GL_FLOAT, 3 * sizeof(float), 3, 6 * sizeof(float));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferObject.release();
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectAttr);
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectNormalAttr);
}

void COpenGLWidgetDiffuse::m_paintCubeLight()
{
    if(!m_vBufferLight.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,

            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,

            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,

            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
        };

        m_vBufferLight.create();
        m_vBufferLight.bind();
        m_vBufferLight.allocate(36 * 3 * sizeof(float));
        m_vBufferLight.write(0, afVertices, sizeof(afVertices));
        m_vBufferLight.release();
    }

    // Uniform    
    m_pShaderLightProgram->setUniformValue("model"     , m_modelLightMatrix);
    m_pShaderLightProgram->setUniformValue("view"      , m_viewMatrix);
    m_pShaderLightProgram->setUniformValue("projection", m_projectionMatrix);


    m_pShaderLightProgram->enableAttributeArray(m_vertexLightAttr);
    m_vBufferLight.bind();
    m_pShaderLightProgram->setAttributeBuffer(m_vertexLightAttr, GL_FLOAT, 0, 3, 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferLight.release();
    m_pShaderLightProgram->disableAttributeArray(m_vertexLightAttr);
}


bool COpenGLWidgetDiffuse::eventFilter(QObject *obj, QEvent * event)
{
    if(obj == m_pParent)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent != NULL)
        {
            if(keyEvent->type() == QKeyEvent::KeyPress)
            {
                if(keyEvent->key() == Qt::Key_Escape)
                {
                    qDebug() << "Close QOpenGLWidget";
                    QCoreApplication::quit();
                }
            }
        }
    }

    return false;
}

void COpenGLWidgetDiffuse::mousePressEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT;
        m_leftMousePressPos = event->pos();
    }
    else if(event->button() == Qt::RightButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT;
        m_rightMousePressPos = event->pos();
    }
    else if(event->button() == Qt::MidButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID;
        m_midMousePressPos = event->pos();
    }
}

void COpenGLWidgetDiffuse::mouseMoveEvent(QMouseEvent* event)
{
    if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT)
    {
        m_leftMouseMovePos = event->pos();

        float diffX = m_leftMouseMovePos.x() - m_leftMousePressPos.x();
        float diffY = m_leftMouseMovePos.y() - m_leftMousePressPos.y();

        float sensitivity = 0.05f;
        m_yaw   -= diffX * sensitivity;
        m_pitch += diffY * sensitivity;

        if(m_pitch > 89.0f)
        {
            m_pitch = 89.0f;
        }
        else if(m_pitch < -89.0f)
        {
            m_pitch = -89.0f;
        }

        QVector3D front;

        front.setX(cos(m_pitch / 180.0f * M_PI) * cos(m_yaw / 180.0f * M_PI));
        front.setY(sin(m_pitch / 180.0f * M_PI));
        front.setZ(cos(m_pitch / 180.0f * M_PI) * sin(m_yaw / 180.0f * M_PI));
        front.normalized();

        // qDebug() << "front = " << front;

        m_cameraFront = front;

        m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

        m_cameraUp    = QVector3D::crossProduct(m_cameraRight, m_cameraFront).normalized();


        m_leftMousePressPos = m_leftMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT)
    {
        m_rightMouseMovePos = event->pos();


        m_rightMousePressPos = m_rightMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID)
    {
        m_midMouseMovePos = event->pos();

        m_midMousePressPos = m_midMouseMovePos;
    }
}

void COpenGLWidgetDiffuse::mouseReleaseEvent(QMouseEvent *event)
{
    m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_NON;
}

void COpenGLWidgetDiffuse::wheelEvent(QWheelEvent* event)
{
    if(event->delta() > 0)
    {
        m_fov -= 2.5f;
    }
    else if(event->delta() < 0)
    {
        m_fov += 2.5f;
    }

    if(m_fov < 1.0f)
    {
        m_fov = 1.0f;
    }
    else if(m_fov > 45.0f)
    {
        m_fov = 45.0f;
    }
}
#include "crsopenglwidgetdiffusenormal.h"

COpenGLWidgetDiffuseNormal::COpenGLWidgetDiffuseNormal(QWidget *parent) : QOpenGLWidget(parent)
{
    m_pParent = parent;

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    QSurfaceFormat::setDefaultFormat(format);
}


COpenGLWidgetDiffuseNormal::~COpenGLWidgetDiffuseNormal()
{
    delete m_pVShaderObject;
    delete m_pVShaderLight;

    delete m_pFShaderObject;
    delete m_pFShaderLight;

    delete m_pShaderObjectProgram;
    delete m_pShaderLightProgram;
}



void COpenGLWidgetDiffuseNormal::initializeGL()
{
     bool ret;
    // 初始化OpenGL函数
    initializeOpenGLFunctions();

    // 初始化相机
    m_cameraPos   = QVector3D(0.0F, 0.0f, 10.0f);
    m_cameraFront = QVector3D(0.0f, 0.0f, -1.0f);
    m_cameraUp    = QVector3D(0.0f, 1.0f,  0.0f);
    m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

    m_fov         = 45;
    m_pitch       =  0.0f;
    m_yaw         = -90.0f;


    QSize size = this->size();

    m_projectionMatrix = QMatrix4x4();

    m_projectionMatrix.perspective(45.0f, (float)size.width() / (float)size.height(), 0.1f, 100.f);

    m_modelObjectMatrix = QMatrix4x4();

    m_modelLightMatrix  = QMatrix4x4();
    m_modelLightMatrix.translate(QVector3D(1.2f, 1.0f, 2.0f)); // 注意: QVector3D(1.2f, 1.0f, 2.0f)为光源的位置
    m_modelLightMatrix.scale(0.2f);

    // 初始化物体的顶点着色器
    m_pVShaderObject = new QOpenGLShader(QOpenGLShader::Vertex);
    QString vShaderObjectSrc;

    vShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("layout (location = 1) in vec3 aNormal; \n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("uniform mat3 normalmodel; \n")
            + QString("out vec3 Normal; \n")
            + QString("out vec3 FragPos; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("    FragPos     = vec3(model * vec4(aPos, 1.0f)); \n")
            + QString("    Normal      = normalmodel * aNormal; \n")
            + QString("}\n");


    m_pVShaderObject->compileSourceCode(vShaderObjectSrc);


    // 初始化物体的片段着色器
    m_pFShaderObject = new QOpenGLShader(QOpenGLShader::Fragment);
    QString fShaderObjectSrc;

    fShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("in vec3 FragPos; \n")
            + QString("in vec3 Normal; \n")
            + QString("uniform vec3 objectColor; \n")
            + QString("uniform vec3 lightColor; \n")
            + QString("uniform vec3 lightPos; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    float ambientStrength = 0.3f; \n")
            + QString("    vec3 ambient = ambientStrength * lightColor; \n")
            + QString("    vec3 norm = normalize(Normal); \n")
            + QString("    vec3 lightDir = normalize(lightPos - FragPos); \n")
            + QString("    float diff = max(dot(norm, lightDir), 0.0); \n")
            + QString("    vec3 diffuse = diff * lightColor; \n")
            + QString("    vec3 result  = (ambient + diffuse) * objectColor; \n")
            + QString("    FragColor    = vec4(result, 1.0); \n")
            + QString("}\n");

    m_pFShaderObject->compileSourceCode(fShaderObjectSrc);

    m_pShaderObjectProgram = new QOpenGLShaderProgram;
    m_pShaderObjectProgram->addShader(m_pVShaderObject);
    m_pShaderObjectProgram->addShader(m_pFShaderObject);

    ret = m_pShaderObjectProgram->link();

    if(ret == false)
    {
        qDebug() << "Object Shader Link Failed !";
        qDebug() << m_pShaderObjectProgram->log();
    }

    m_vertexObjectAttr       = m_pShaderObjectProgram->attributeLocation("aPos");
    m_vertexObjectNormalAttr = m_pShaderObjectProgram->attributeLocation("aNormal");

    // 初始化光源的顶点着色器
    m_pVShaderLight = new QOpenGLShader(QOpenGLShader::Vertex);

    QString vShaderLightSrc;

    vShaderLightSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("}\n");

    m_pVShaderLight->compileSourceCode(vShaderLightSrc);

    // 初始化光源的片段着色器
    m_pFShaderLight = new QOpenGLShader(QOpenGLShader::Fragment);

    QString fShaderLightSrc;

    fShaderLightSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n")
            + QString("}\n");

    m_pFShaderLight->compileSourceCode(fShaderLightSrc);

    m_pShaderLightProgram = new QOpenGLShaderProgram;
    m_pShaderLightProgram->addShader(m_pVShaderLight);
    m_pShaderLightProgram->addShader(m_pFShaderLight);

    ret = m_pShaderLightProgram->link();

    if(ret == false)
    {
        qDebug() << "Light Shader Link Failed !";
        qDebug() << m_pShaderLightProgram->log();
    }


     m_vertexLightAttr  = m_pShaderLightProgram->attributeLocation("aPos");


}

void COpenGLWidgetDiffuseNormal::resizeGL(int width, int height)
{
    // TODO...
    m_projectionMatrix = QMatrix4x4();
    m_projectionMatrix.perspective(45.0f, (float)width / (float)height, 0.1f, 100.f);
}

void COpenGLWidgetDiffuseNormal::paintGL()
{
    QPainter painter;

    painter.begin(this);

    painter.beginNativePainting();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    // Updata ViewMatrix
    m_viewMatrix.lookAt(m_cameraPos, m_cameraPos + m_cameraFront, m_cameraUp);

    if(m_pShaderObjectProgram->isLinked())
    {
        m_pShaderObjectProgram->bind();
        m_paintCubeObject();
        m_pShaderObjectProgram->release();
    }

    if(m_pShaderLightProgram->isLinked())
    {
        m_pShaderLightProgram->bind();
        m_paintCubeLight();
        m_pShaderLightProgram->release();
    }

    glDisable(GL_DEPTH_TEST);

    painter.endNativePainting();

    // QT 绘制文字信息
    painter.setPen(Qt::green);
    QString textInfo = QString("按\"ESC\"退出");
    painter.drawText(25, 25, textInfo);

    painter.end();

    update();
}


void COpenGLWidgetDiffuseNormal::m_paintCubeObject()
{
    if(!m_vBufferObject.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

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

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

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

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

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

        m_vBufferObject.create();
        m_vBufferObject.bind();
        m_vBufferObject.allocate(36 * 6 * sizeof(float));
        m_vBufferObject.write(0, afVertices, sizeof(afVertices));
        m_vBufferObject.release();
    }

    // Uniform
    m_pShaderObjectProgram->setUniformValue("objectColor", QVector3D(1.0f, 0.5f, 0.31f));
    m_pShaderObjectProgram->setUniformValue("lightColor" , QVector3D(1.0f, 1.0f, 1.0f));
    m_pShaderObjectProgram->setUniformValue("lightPos", QVector3D(1.2f, 1.0f, 2.0f));

    // 计算正规矩阵
    m_modelObjectNormalMatrix = m_modelObjectMatrix.normalMatrix();

    m_pShaderObjectProgram->setUniformValue("model"      , m_modelObjectMatrix);
    m_pShaderObjectProgram->setUniformValue("normalmodel", m_modelObjectNormalMatrix);
    m_pShaderObjectProgram->setUniformValue("view"       , m_viewMatrix);
    m_pShaderObjectProgram->setUniformValue("projection" , m_projectionMatrix);


    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectAttr);
    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectNormalAttr);
    m_vBufferObject.bind();
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectAttr      , GL_FLOAT, 0                , 3, 6 * sizeof(float));
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectNormalAttr, GL_FLOAT, 3 * sizeof(float), 3, 6 * sizeof(float));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferObject.release();
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectAttr);
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectNormalAttr);
}

void COpenGLWidgetDiffuseNormal::m_paintCubeLight()
{
    if(!m_vBufferLight.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,

            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,

            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,

            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
        };

        m_vBufferLight.create();
        m_vBufferLight.bind();
        m_vBufferLight.allocate(36 * 3 * sizeof(float));
        m_vBufferLight.write(0, afVertices, sizeof(afVertices));
        m_vBufferLight.release();
    }

    // Uniform    
    m_pShaderLightProgram->setUniformValue("model"     , m_modelLightMatrix);
    m_pShaderLightProgram->setUniformValue("view"      , m_viewMatrix);
    m_pShaderLightProgram->setUniformValue("projection", m_projectionMatrix);


    m_pShaderLightProgram->enableAttributeArray(m_vertexLightAttr);
    m_vBufferLight.bind();
    m_pShaderLightProgram->setAttributeBuffer(m_vertexLightAttr, GL_FLOAT, 0, 3, 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferLight.release();
    m_pShaderLightProgram->disableAttributeArray(m_vertexLightAttr);
}


bool COpenGLWidgetDiffuseNormal::eventFilter(QObject *obj, QEvent * event)
{
    if(obj == m_pParent)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent != NULL)
        {
            if(keyEvent->type() == QKeyEvent::KeyPress)
            {
                if(keyEvent->key() == Qt::Key_Escape)
                {
                    qDebug() << "Close QOpenGLWidget";
                    QCoreApplication::quit();
                }
            }
        }
    }

    return false;
}

void COpenGLWidgetDiffuseNormal::mousePressEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT;
        m_leftMousePressPos = event->pos();
    }
    else if(event->button() == Qt::RightButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT;
        m_rightMousePressPos = event->pos();
    }
    else if(event->button() == Qt::MidButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID;
        m_midMousePressPos = event->pos();
    }
}

void COpenGLWidgetDiffuseNormal::mouseMoveEvent(QMouseEvent* event)
{
    if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT)
    {
        m_leftMouseMovePos = event->pos();

        float diffX = m_leftMouseMovePos.x() - m_leftMousePressPos.x();
        float diffY = m_leftMouseMovePos.y() - m_leftMousePressPos.y();

        float sensitivity = 0.05f;
        m_yaw   -= diffX * sensitivity;
        m_pitch += diffY * sensitivity;

        if(m_pitch > 89.0f)
        {
            m_pitch = 89.0f;
        }
        else if(m_pitch < -89.0f)
        {
            m_pitch = -89.0f;
        }

        QVector3D front;

        front.setX(cos(m_pitch / 180.0f * M_PI) * cos(m_yaw / 180.0f * M_PI));
        front.setY(sin(m_pitch / 180.0f * M_PI));
        front.setZ(cos(m_pitch / 180.0f * M_PI) * sin(m_yaw / 180.0f * M_PI));
        front.normalized();

        // qDebug() << "front = " << front;

        m_cameraFront = front;

        m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

        m_cameraUp    = QVector3D::crossProduct(m_cameraRight, m_cameraFront).normalized();


        m_leftMousePressPos = m_leftMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT)
    {
        m_rightMouseMovePos = event->pos();


        m_rightMousePressPos = m_rightMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID)
    {
        m_midMouseMovePos = event->pos();

        m_midMousePressPos = m_midMouseMovePos;
    }
}

void COpenGLWidgetDiffuseNormal::mouseReleaseEvent(QMouseEvent *event)
{
    m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_NON;
}

void COpenGLWidgetDiffuseNormal::wheelEvent(QWheelEvent* event)
{
    if(event->delta() > 0)
    {
        m_fov -= 2.5f;
    }
    else if(event->delta() < 0)
    {
        m_fov += 2.5f;
    }

    if(m_fov < 1.0f)
    {
        m_fov = 1.0f;
    }
    else if(m_fov > 45.0f)
    {
        m_fov = 45.0f;
    }
}
#include "crsopenglwidgetspecular.h"

COpenGLWidgetSpecular::COpenGLWidgetSpecular(QWidget *parent) : QOpenGLWidget(parent)
{
    m_pParent = parent;

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    QSurfaceFormat::setDefaultFormat(format);
}


COpenGLWidgetSpecular::~COpenGLWidgetSpecular()
{
    delete m_pVShaderObject;
    delete m_pVShaderLight;

    delete m_pFShaderObject;
    delete m_pFShaderLight;

    delete m_pShaderObjectProgram;
    delete m_pShaderLightProgram;
}



void COpenGLWidgetSpecular::initializeGL()
{
     bool ret;
    // 初始化OpenGL函数
    initializeOpenGLFunctions();

    // 初始化相机
    m_cameraPos   = QVector3D(0.0F, 0.0f, 10.0f);
    m_cameraFront = QVector3D(0.0f, 0.0f, -1.0f);
    m_cameraUp    = QVector3D(0.0f, 1.0f,  0.0f);
    m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

    m_fov         = 45;
    m_pitch       =  0.0f;
    m_yaw         = -90.0f;


    QSize size = this->size();

    m_projectionMatrix = QMatrix4x4();

    m_projectionMatrix.perspective(45.0f, (float)size.width() / (float)size.height(), 0.1f, 100.f);

    m_modelObjectMatrix = QMatrix4x4();

    m_modelLightMatrix  = QMatrix4x4();
    m_modelLightMatrix.translate(QVector3D(1.2f, 1.0f, 2.0f)); // 注意: QVector3D(1.2f, 1.0f, 2.0f)为光源的位置
    m_modelLightMatrix.scale(0.2f);

    // 初始化物体的顶点着色器
    m_pVShaderObject = new QOpenGLShader(QOpenGLShader::Vertex);
    QString vShaderObjectSrc;

    vShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("layout (location = 1) in vec3 aNormal; \n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("uniform mat3 normalmodel; \n")
            + QString("out vec3 Normal; \n")
            + QString("out vec3 FragPos; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("    FragPos     = vec3(model * vec4(aPos, 1.0f)); \n")
            + QString("    Normal      = normalmodel * aNormal; \n")
            + QString("}\n");


    m_pVShaderObject->compileSourceCode(vShaderObjectSrc);


    // 初始化物体的片段着色器
    m_pFShaderObject = new QOpenGLShader(QOpenGLShader::Fragment);
    QString fShaderObjectSrc;

    fShaderObjectSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("in vec3 FragPos; \n")
            + QString("in vec3 Normal; \n")
            + QString("uniform vec3 objectColor; \n")
            + QString("uniform vec3 lightColor; \n")
            + QString("uniform vec3 lightPos; \n")
            + QString("uniform vec3 viewPos; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    float ambientStrength = 0.3f; \n")
            + QString("    vec3 ambient = ambientStrength * lightColor; \n")
            + QString("    vec3 norm = normalize(Normal); \n")
            + QString("    vec3 lightDir = normalize(lightPos - FragPos); \n")
            + QString("    float diff = max(dot(norm, lightDir), 0.0); \n")
            + QString("    vec3 diffuse = diff * lightColor; \n")
            + QString("    float specularStrength = 0.5f; \n")
            + QString("    vec3 viewDir = normalize(viewPos - FragPos); \n")
            + QString("    vec3 reflectDir = reflect(-lightDir, norm); \n")
            + QString("    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); \n")
            + QString("    vec3 specular = specularStrength * spec * lightColor; \n")
            + QString("    vec3 result  = (ambient + diffuse + specular) * objectColor; \n")
            + QString("    FragColor    = vec4(result, 1.0); \n")
            + QString("}\n");

    m_pFShaderObject->compileSourceCode(fShaderObjectSrc);

    m_pShaderObjectProgram = new QOpenGLShaderProgram;
    m_pShaderObjectProgram->addShader(m_pVShaderObject);
    m_pShaderObjectProgram->addShader(m_pFShaderObject);

    ret = m_pShaderObjectProgram->link();

    if(ret == false)
    {
        qDebug() << "Object Shader Link Failed !";
        qDebug() << m_pShaderObjectProgram->log();
    }

    m_vertexObjectAttr       = m_pShaderObjectProgram->attributeLocation("aPos");
    m_vertexObjectNormalAttr = m_pShaderObjectProgram->attributeLocation("aNormal");

    // 初始化光源的顶点着色器
    m_pVShaderLight = new QOpenGLShader(QOpenGLShader::Vertex);

    QString vShaderLightSrc;

    vShaderLightSrc =
            QString("#version 330 core \n")
            + QString("layout (location = 0) in vec3 aPos;\n")
            + QString("uniform mat4 model; \n")
            + QString("uniform mat4 view; \n")
            + QString("uniform mat4 projection; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    gl_Position = projection * view * model * vec4(aPos, 1.0);\n")
            + QString("}\n");

    m_pVShaderLight->compileSourceCode(vShaderLightSrc);

    // 初始化光源的片段着色器
    m_pFShaderLight = new QOpenGLShader(QOpenGLShader::Fragment);

    QString fShaderLightSrc;

    fShaderLightSrc =
            QString("#version 330 core \n")
            + QString("out vec4 FragColor; \n")
            + QString("\n")
            + QString("void main()\n")
            + QString("{\n")
            + QString("    FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n")
            + QString("}\n");

    m_pFShaderLight->compileSourceCode(fShaderLightSrc);

    m_pShaderLightProgram = new QOpenGLShaderProgram;
    m_pShaderLightProgram->addShader(m_pVShaderLight);
    m_pShaderLightProgram->addShader(m_pFShaderLight);

    ret = m_pShaderLightProgram->link();

    if(ret == false)
    {
        qDebug() << "Light Shader Link Failed !";
        qDebug() << m_pShaderLightProgram->log();
    }


     m_vertexLightAttr  = m_pShaderLightProgram->attributeLocation("aPos");


}

void COpenGLWidgetSpecular::resizeGL(int width, int height)
{
    // TODO...
    m_projectionMatrix = QMatrix4x4();
    m_projectionMatrix.perspective(45.0f, (float)width / (float)height, 0.1f, 100.f);
}

void COpenGLWidgetSpecular::paintGL()
{
    QPainter painter;

    painter.begin(this);

    painter.beginNativePainting();

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    // Updata ViewMatrix
    m_viewMatrix.lookAt(m_cameraPos, m_cameraPos + m_cameraFront, m_cameraUp);


    if(m_pShaderObjectProgram->isLinked())
    {
        m_pShaderObjectProgram->bind();
        m_paintCubeObject();
        m_pShaderObjectProgram->release();
    }

    if(m_pShaderLightProgram->isLinked())
    {
        m_pShaderLightProgram->bind();
        m_paintCubeLight();
        m_pShaderLightProgram->release();
    }

    glDisable(GL_DEPTH_TEST);

    painter.endNativePainting();

    // QT 绘制文字信息
    painter.setPen(Qt::green);
    QString textInfo = QString("按\"ESC\"退出");
    painter.drawText(25, 25, textInfo);

    painter.end();

    update();
}


void COpenGLWidgetSpecular::m_paintCubeObject()
{
    if(!m_vBufferObject.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
             0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
            -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

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

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

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

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

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

        m_vBufferObject.create();
        m_vBufferObject.bind();
        m_vBufferObject.allocate(36 * 6 * sizeof(float));
        m_vBufferObject.write(0, afVertices, sizeof(afVertices));
        m_vBufferObject.release();
    }

    // Uniform
    m_pShaderObjectProgram->setUniformValue("objectColor", QVector3D(1.0f, 0.5f, 0.31f));
    m_pShaderObjectProgram->setUniformValue("lightColor" , QVector3D(1.0f, 1.0f, 1.0f));
    m_pShaderObjectProgram->setUniformValue("lightPos", QVector3D(1.2f, 1.0f, 2.0f));

    // 相机位置(视点)
    m_pShaderObjectProgram->setUniformValue("viewPos", m_cameraPos);

    // 计算正规矩阵
    m_modelObjectNormalMatrix = m_modelObjectMatrix.normalMatrix();

    m_pShaderObjectProgram->setUniformValue("model"      , m_modelObjectMatrix);
    m_pShaderObjectProgram->setUniformValue("normalmodel", m_modelObjectNormalMatrix);
    m_pShaderObjectProgram->setUniformValue("view"       , m_viewMatrix);
    m_pShaderObjectProgram->setUniformValue("projection" , m_projectionMatrix);


    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectAttr);
    m_pShaderObjectProgram->enableAttributeArray(m_vertexObjectNormalAttr);
    m_vBufferObject.bind();
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectAttr      , GL_FLOAT, 0                , 3, 6 * sizeof(float));
    m_pShaderObjectProgram->setAttributeBuffer(m_vertexObjectNormalAttr, GL_FLOAT, 3 * sizeof(float), 3, 6 * sizeof(float));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferObject.release();
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectAttr);
    m_pShaderObjectProgram->disableAttributeArray(m_vertexObjectNormalAttr);
}

void COpenGLWidgetSpecular::m_paintCubeLight()
{
    if(!m_vBufferLight.isCreated())
    {
        static GLfloat afVertices[] =
        {
            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,

            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,

            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,

            -0.5f, -0.5f, -0.5f,
            0.5f, -0.5f, -0.5f,
            0.5f, -0.5f,  0.5f,
            0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f,  0.5f,
            -0.5f, -0.5f, -0.5f,

            -0.5f,  0.5f, -0.5f,
            0.5f,  0.5f, -0.5f,
            0.5f,  0.5f,  0.5f,
            0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f,  0.5f,
            -0.5f,  0.5f, -0.5f,
        };

        m_vBufferLight.create();
        m_vBufferLight.bind();
        m_vBufferLight.allocate(36 * 3 * sizeof(float));
        m_vBufferLight.write(0, afVertices, sizeof(afVertices));
        m_vBufferLight.release();
    }

    // Uniform    
    m_pShaderLightProgram->setUniformValue("model"     , m_modelLightMatrix);
    m_pShaderLightProgram->setUniformValue("view"      , m_viewMatrix);
    m_pShaderLightProgram->setUniformValue("projection", m_projectionMatrix);


    m_pShaderLightProgram->enableAttributeArray(m_vertexLightAttr);
    m_vBufferLight.bind();
    m_pShaderLightProgram->setAttributeBuffer(m_vertexLightAttr, GL_FLOAT, 0, 3, 0);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    m_vBufferLight.release();
    m_pShaderLightProgram->disableAttributeArray(m_vertexLightAttr);
}


bool COpenGLWidgetSpecular::eventFilter(QObject *obj, QEvent * event)
{
    if(obj == m_pParent)
    {
        QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
        if(keyEvent != NULL)
        {
            if(keyEvent->type() == QKeyEvent::KeyPress)
            {
                if(keyEvent->key() == Qt::Key_Escape)
                {
                    qDebug() << "Close QOpenGLWidget";
                    QCoreApplication::quit();
                }
            }
        }
    }

    return false;
}

void COpenGLWidgetSpecular::mousePressEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT;
        m_leftMousePressPos = event->pos();
    }
    else if(event->button() == Qt::RightButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT;
        m_rightMousePressPos = event->pos();
    }
    else if(event->button() == Qt::MidButton)
    {
        m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID;
        m_midMousePressPos = event->pos();
    }
}

void COpenGLWidgetSpecular::mouseMoveEvent(QMouseEvent* event)
{
    if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_LEFT)
    {
        m_leftMouseMovePos = event->pos();

        float diffX = m_leftMouseMovePos.x() - m_leftMousePressPos.x();
        float diffY = m_leftMouseMovePos.y() - m_leftMousePressPos.y();

        float sensitivity = 0.05f;
        m_yaw   -= diffX * sensitivity;
        m_pitch += diffY * sensitivity;

        if(m_pitch > 89.0f)
        {
            m_pitch = 89.0f;
        }
        else if(m_pitch < -89.0f)
        {
            m_pitch = -89.0f;
        }

        QVector3D front;

        front.setX(cos(m_pitch / 180.0f * M_PI) * cos(m_yaw / 180.0f * M_PI));
        front.setY(sin(m_pitch / 180.0f * M_PI));
        front.setZ(cos(m_pitch / 180.0f * M_PI) * sin(m_yaw / 180.0f * M_PI));
        front.normalized();

        // qDebug() << "front = " << front;

        m_cameraFront = front;

        m_cameraRight = QVector3D::crossProduct(m_cameraFront, m_cameraUp).normalized();

        m_cameraUp    = QVector3D::crossProduct(m_cameraRight, m_cameraFront).normalized();


        m_leftMousePressPos = m_leftMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_RIGHT)
    {
        m_rightMouseMovePos = event->pos();


        m_rightMousePressPos = m_rightMouseMovePos;
    }
    else if(m_mousePressType == RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_MID)
    {
        m_midMouseMovePos = event->pos();

        m_midMousePressPos = m_midMouseMovePos;
    }
}

void COpenGLWidgetSpecular::mouseReleaseEvent(QMouseEvent *event)
{
    m_mousePressType = RS_MOUSE_PRESS_TYPE::RS_MOUSE_PRESS_NON;
}

void COpenGLWidgetSpecular::wheelEvent(QWheelEvent* event)
{
    if(event->delta() > 0)
    {
        m_fov -= 2.5f;
    }
    else if(event->delta() < 0)
    {
        m_fov += 2.5f;
    }

    if(m_fov < 1.0f)
    {
        m_fov = 1.0f;
    }
    else if(m_fov > 45.0f)
    {
        m_fov = 45.0f;
    }
}
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowTitle(QString("LearnBasicLighting"));

    m_pRSOpenGLWidgetAmbient       = new COpenGLWidgetAmbient(this);
    m_pRSOpenGLWidgetDiffuse       = new COpenGLWidgetDiffuse(this);
    m_pRSOpenGLWidgetDiffuseNormal = new COpenGLWidgetDiffuseNormal(this);
    m_pRSOpenGLWidgetSpecular      = new COpenGLWidgetSpecular(this);

    ui->verticalLayout->addWidget(m_pRSOpenGLWidgetAmbient);
    ui->verticalLayout->addWidget(m_pRSOpenGLWidgetDiffuse);
    ui->verticalLayout->addWidget(m_pRSOpenGLWidgetDiffuseNormal);
    ui->verticalLayout->addWidget(m_pRSOpenGLWidgetSpecular);

    this->installEventFilter(m_pRSOpenGLWidgetAmbient);
}

MainWindow::~MainWindow()
{
    delete ui;
}

(3)效果(待补充)

 

 类似资料: