OpenGL入门第二步:颜色、纹理设置(解析)-CSDN博客
目录
1、矩阵变换
这里矩阵变换,使用4*4的矩阵,既可以表示位移,也可以表示缩放。
原因:
添加4维矩阵变量
initializeGL()函数:在着色器里面添加变换矩阵,改变坐标位置
设计一个随时间变换 ,所有重写TimerEvent
调用update触发paintGL()函数:
具体代码
#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QElapsedTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class openGLWidget; }
QT_END_NAMESPACE
class openGLWidget : public QOpenGLWidget
{
Q_OBJECT
public:
openGLWidget(QWidget *parent = nullptr);
~openGLWidget();
protected:
virtual void timerEvent(QTimerEvent *event) override;
virtual void initializeGL() override;
virtual void resizeGL(int w, int h) override;
virtual void paintGL() override;
private:
QOpenGLShaderProgram shaderProgram;
QOpenGLBuffer vbo;
QOpenGLBuffer ebo {QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)};
QOpenGLVertexArrayObject vao;
QOpenGLTexture *texture1;
QOpenGLTexture *texture2;
QMatrix4x4 trans;
QElapsedTimer time;
private:
Ui::openGLWidget *ui;
};
#endif // OPENGLWIDGET_H
#include "openGLWidget.h"
#include "./ui_openGLWidget.h"
#include <QOpenGLFunctions>
#include <QtMath>
openGLWidget::openGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
, ui(new Ui::openGLWidget)
{
ui->setupUi(this);
}
openGLWidget::~openGLWidget()
{
makeCurrent();
vao.destroy();
vbo.destroy();
ebo.destroy();
delete texture1;
delete texture2;
doneCurrent();
delete ui;
}
void openGLWidget::timerEvent(QTimerEvent *event)
{
trans.setToIdentity();
// trans.translate(0.5f, -0.5f, 0.0f);
trans.rotate(time.elapsed() / 50.f, 0.0f, 0.0f, 1.0f);
update();
}
void openGLWidget::initializeGL()
{
texture1 = new QOpenGLTexture(QImage("images/container.jpg").mirrored());
texture1->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
texture2 = new QOpenGLTexture(QImage("images/awesomeface.png").mirrored());
texture2->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
// 设置用来清空屏幕的颜色 这里设置为黑色
QOpenGLFunctions *f = context()->functions();
f->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 顶点着色器
shaderProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 vTexCoord;
uniform mat4 uTransform;
void main()
{
gl_Position = uTransform * vec4(aPos, 1.0);
vTexCoord = aTexCoord;
}
)");
// 片段着色器
shaderProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, R"(
#version 330 core
out vec4 FragColor;
in vec2 vTexCoord;
// texture samplers
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;
void main()
{
FragColor = mix(texture(uTexture1, vTexCoord),texture(uTexture2, vTexCoord), 0.2);
}
)");
// 编译链接
if(!shaderProgram.link()) {
qDebug() << shaderProgram.log();
};
// 顶点数据
float vertices[] = {
// ---- 位置 -- - 纹理坐标 -
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // 右上
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // 右下
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // 左下
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // 左上
};
// 顶点索引
uint indices[] = {
0, 1, 2, // 第一个三角形
0, 2, 3, // 第二个三角形
};
// 创建VAO VBO EBO
vao.create();
vao.bind();
vbo.create();
vbo.bind();
ebo.create();
ebo.bind();
vbo.allocate(vertices, sizeof(vertices));
ebo.allocate(indices, sizeof(indices));
shaderProgram.enableAttributeArray(0);
shaderProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, 5 * sizeof(float));
shaderProgram.enableAttributeArray(1);
shaderProgram.setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 2, 5 * sizeof(float));
startTimer(1);
}
void openGLWidget::resizeGL(int w, int h)
{
// 窗口尺寸发生变化时,设置视口大小, 这里把视口设置与窗口一样大
QOpenGLFunctions *f = context()->functions();
f->glViewport(0, 0, w, h);
}
void openGLWidget::paintGL()
{
QOpenGLFunctions* f = context()->functions();
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderProgram.bind();
vao.bind();
texture1->bind(0);
texture2->bind(1);
shaderProgram.setUniformValue("uTexture1", 0);
shaderProgram.setUniformValue("uTexture2", 1);
shaderProgram.setUniformValue("uTransform", trans);
f->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// f->glDrawArrays(GL_TRIANGLES, 2, 3);//从顶点数据的第2组开始取3组
}
2、坐标系统
函数加载的时候,设置视图矩阵,以及设置好需要产生物体的点。
initializeGL()函数:
resizeGL(int w, int h)函数:
paintGL()函数:
timerEvent函数:只需要调用 update()函数。
具体代码
#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QElapsedTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class openGLWidget; }
QT_END_NAMESPACE
class openGLWidget : public QOpenGLWidget
{
Q_OBJECT
public:
openGLWidget(QWidget *parent = nullptr);
~openGLWidget();
protected:
virtual void timerEvent(QTimerEvent *event) override;
virtual void initializeGL() override;
virtual void resizeGL(int w, int h) override;
virtual void paintGL() override;
private:
QOpenGLShaderProgram shaderProgram;
QOpenGLBuffer vbo;
QOpenGLBuffer ebo {QOpenGLBuffer(QOpenGLBuffer::IndexBuffer)};
QOpenGLVertexArrayObject vao;
QOpenGLTexture *texture1;
QOpenGLTexture *texture2;
QMatrix4x4 projection;
QMatrix4x4 view;
QElapsedTimer time;
QVector<QVector3D> cubePositions;
private:
Ui::openGLWidget *ui;
};
#endif // OPENGLWIDGET_H
#include "openGLWidget.h"
#include "./ui_openGLWidget.h"
#include <QOpenGLFunctions>
#include <QtMath>
openGLWidget::openGLWidget(QWidget *parent)
: QOpenGLWidget(parent)
, ui(new Ui::openGLWidget)
{
ui->setupUi(this);
time.start();
view.translate(0.0f, 0.0f, -3.0f);
//盒子产生的位置
cubePositions << QVector3D( 0.0f, 0.0f, 0.0f)
<< QVector3D( 2.0f, 5.0f, -15.0f)
<< QVector3D(-1.5f, -2.2f, -2.5f)
<< QVector3D(-3.8f, -2.0f, -12.3f)
<< QVector3D( 2.4f, -0.4f, -3.5f)
<< QVector3D(-1.7f, 3.0f, -7.5f)
<< QVector3D( 1.3f, -2.0f, -2.5f)
<< QVector3D( 1.5f, 2.0f, -2.5f)
<< QVector3D( 1.5f, 0.2f, -1.5f)
<< QVector3D(-1.3f, 1.0f, -1.5f);
}
openGLWidget::~openGLWidget()
{
makeCurrent();
vao.destroy();
vbo.destroy();
ebo.destroy();
delete texture1;
delete texture2;
doneCurrent();
delete ui;
}
void openGLWidget::timerEvent(QTimerEvent *event)
{
update();
}
void openGLWidget::initializeGL()
{
texture1 = new QOpenGLTexture(QImage("images/container.jpg").mirrored());
texture1->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
texture2 = new QOpenGLTexture(QImage("images/awesomeface.png").mirrored());
texture2->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
// 设置用来清空屏幕的颜色 这里设置为黑色
QOpenGLFunctions *f = context()->functions();
f->glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 启用深度测试
f->glEnable(GL_DEPTH_TEST);
// 顶点着色器
shaderProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, R"(
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
uniform mat4 uProjection;
uniform mat4 uView;
uniform mat4 uModel;
out vec2 vTexCoord;
void main()
{
gl_Position = uProjection * uView * uModel * vec4(aPos, 1.0);
vTexCoord = aTexCoord;
}
)");
// 片段着色器
shaderProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, R"(
#version 330 core
out vec4 FragColor;
in vec2 vTexCoord;
// texture samplers
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;
void main()
{
FragColor = mix(texture(uTexture1, vTexCoord),texture(uTexture2, vTexCoord), 0.2);
}
)");
// 编译链接
if(!shaderProgram.link()) {
qDebug() << shaderProgram.log();
};
// 顶点数据
float 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, 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,
-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
};
// 创建VAO VBO EBO
vao.create();
vao.bind();
vbo.create();
vbo.bind();
ebo.create();
ebo.bind();
vbo.allocate(vertices, sizeof(vertices));
shaderProgram.enableAttributeArray(0);
shaderProgram.setAttributeBuffer(0, GL_FLOAT, 0, 3, 5 * sizeof(float));
shaderProgram.enableAttributeArray(1);
shaderProgram.setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 2, 5 * sizeof(float));
startTimer(1);
}
void openGLWidget::resizeGL(int w, int h)
{
// 窗口尺寸发生变化时,设置视口大小, 这里把视口设置与窗口一样大
QOpenGLFunctions *f = context()->functions();
f->glViewport(0, 0, w, h);
projection.setToIdentity();
projection.perspective(45.0f, float(w) / float(h), 0.1f, 100.f);
}
void openGLWidget::paintGL()
{
QOpenGLFunctions* f = context()->functions();
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderProgram.bind();
vao.bind();
texture1->bind(0);
texture2->bind(1);
shaderProgram.setUniformValue("uTexture1", 0);
shaderProgram.setUniformValue("uTexture2", 1);
shaderProgram.setUniformValue("uProjection", projection);
shaderProgram.setUniformValue("uView", view);
for(int i = 0; i < cubePositions.size(); ++i) {
QMatrix4x4 model;
model.translate(cubePositions[i]);
model.rotate(time.elapsed() / 20.f + 20 * i, 1.5f, 0.3f, 0.5f);
shaderProgram.setUniformValue("uModel", model);
f->glDrawArrays(GL_TRIANGLES, 0, 36);
}
// f->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// f->glDrawArrays(GL_TRIANGLES, 2, 3);//从顶点数据的第2组开始取3组
}