由于被这节的标题和内容吸引,先完成了这节的代码,具体教程等之前的教程更新之后再做
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include "camera.h"
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QTimer>
#include <QTime>
#include <QtMath>
#include <QKeyEvent>
class Widget : public QOpenGLWidget,public QOpenGLExtraFunctions
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
protected:
virtual void initializeGL() override;
virtual void resizeGL(int w,int h) override;
virtual void paintGL() override;
virtual bool event(QEvent *e) override;
private:
QVector<float> vertices;
QVector<QVector3D> cubePositions;
QOpenGLShaderProgram shaderProgram;
QOpenGLShaderProgram shaderSingle;
QOpenGLBuffer VBO;
QOpenGLVertexArrayObject VAO;
QTimer timer;
Camera camera;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QtMath>
Widget::Widget(QWidget *parent)
: QOpenGLWidget(parent)
, VBO(QOpenGLBuffer::VertexBuffer)
, camera(this)
{
vertices = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
timer.setInterval(18);
connect(&timer,&QTimer::timeout,this,static_cast<void (Widget::*)()>(&Widget::update));
timer.start();
}
Widget::~Widget()
{
makeCurrent();
doneCurrent();
}
void Widget::initializeGL()
{
this->initializeOpenGLFunctions(); //初始化opengl函数
if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/triangle.vert")){ //添加并编译顶点着色器
qDebug()<<"ERROR:"<<shaderProgram.log(); //如果编译出错,打印报错信息
}
if(!shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/triangle.frag")){ //添加并编译片段着色器
qDebug()<<"ERROR:"<<shaderProgram.log(); //如果编译出错,打印报错信息
}
if(!shaderProgram.link()){ //链接着色器
qDebug()<<"ERROR:"<<shaderProgram.log(); //如果链接出错,打印报错信息
}
if(!shaderSingle.addShaderFromSourceFile(QOpenGLShader::Vertex,":/triangle.vert")){ //添加并编译顶点着色器
qDebug()<<"ERROR:"<<shaderProgram.log(); //如果编译出错,打印报错信息
}
if(!shaderSingle.addShaderFromSourceFile(QOpenGLShader::Fragment,":/lamp.frag")){ //添加并编译片段着色器
qDebug()<<"ERROR:"<<shaderProgram.log(); //如果编译出错,打印报错信息
}
if(!shaderSingle.link()){ //链接着色器
qDebug()<<"ERROR:"<<shaderProgram.log(); //如果链接出错,打印报错信息
}
QOpenGLVertexArrayObject::Binder{&VAO};
VBO.create(); //生成VBO对象
VBO.bind(); //将VBO绑定到当前的顶点缓冲对象(QOpenGLBuffer::VertexBuffer)中
//将顶点数据分配到VBO中,第一个参数为数据指针,第二个参数为数据的字节长度
VBO.allocate(vertices.data(),sizeof(float)*vertices.size());
//设置顶点解析格式,并启用顶点
shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 5);
shaderProgram.enableAttributeArray("aPos");
shaderProgram.setAttributeBuffer("aTexCoord", GL_FLOAT,sizeof(GLfloat) * 3, 2, sizeof(GLfloat) * 5);
shaderProgram.enableAttributeArray("aTexCoord");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
camera.init();
}
void Widget::resizeGL(int w, int h)
{
this->glViewport(0,0,w,h); //定义视口区域
}
void Widget::paintGL()
{
this->glClearColor(0.1f,0.5f,0.7f,1.0f); //设置清屏颜色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //清除颜色缓存和深度缓存
float time=QTime::currentTime().msecsSinceStartOfDay()/1000.0;
QMatrix4x4 model;
QMatrix4x4 projection;
projection.perspective(45.0f,width()/(float)height(),0.1f,100.0f);
shaderSingle.bind();
shaderSingle.setUniformValue("view",camera.getView());
shaderSingle.setUniformValue("projection",projection);
shaderProgram.bind();
shaderProgram.setUniformValue("view",camera.getView());
shaderProgram.setUniformValue("projection",projection);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
QOpenGLVertexArrayObject::Binder{&VAO};
shaderProgram.setUniformValue("model",model);
this->glDrawArrays(GL_TRIANGLES, 0, 36);
glStencilMask(0x00);
glDisable(GL_DEPTH_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
shaderSingle.bind();
GLfloat scale = 1.1;
model.scale(scale,scale,scale);
shaderSingle.setUniformValue("model",model);
glDrawArrays(GL_TRIANGLES, 0, 36);
glStencilMask(0xFF);
glEnable(GL_DEPTH_TEST);
}
bool Widget::event(QEvent *e)
{
camera.handle(e);
return QWidget::event(e); //调用父类的事件分发函数
}