我们将学习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)效果(待补充)