6. 坐标系统
头文件
#include <QOpenGLWidget> #include <QOpenGLExtraFunctions> #include <QOpenGLFunctions_3_3_Core> #include <QOpenGLShader> #include <QOpenGLShaderProgram> class CoreFunctionWidget : public QOpenGLWidget , protected /*QOpenGLExtraFunctions*/QOpenGLFunctions_3_3_Core { Q_OBJECT public: explicit CoreFunctionWidget(QWidget *parent = nullptr); ~CoreFunctionWidget(); protected: virtual void initializeGL(); virtual void resizeGL(int w, int h); virtual void paintGL(); private: QOpenGLShaderProgram shaderProgram; QTimer* m_pTimer = nullptr; int m_nTimeValue = 0; };
源文件
#include "CoreFunctionWidget.h" #include <QDebug> #include <QTimer> static GLuint VBO, VAO, texture1, texture2; CoreFunctionWidget::CoreFunctionWidget(QWidget *parent) : QOpenGLWidget(parent) { m_pTimer = new QTimer(this); connect(m_pTimer, &QTimer::timeout, this, [=] { m_nTimeValue += 1; update();//重绘函数 }); m_pTimer->start(40);//每次经过40ms发送一次timeout信号 } CoreFunctionWidget::~CoreFunctionWidget() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); } void CoreFunctionWidget::initializeGL() { this->initializeOpenGLFunctions(); bool success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "textures.vert"); if (!success) { qDebug() << "shaderProgram addShaderFromSourceFile failed!" << shaderProgram.log(); return; } success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "textures.frag"); if (!success) { qDebug() << "shaderProgram addShaderFromSourceFile failed!" << shaderProgram.log(); return; } success = shaderProgram.link(); if (!success) { qDebug() << "shaderProgram link failed!" << shaderProgram.log(); } //开启深度测试,因为现在已经是3D了 glEnable(GL_DEPTH_TEST); //VAO,VBO data float vertices[] = { //每个面需要画两个三角形,所以一个面6个点,一共36个点,纹理的顺序和三角形顺序保持一致 -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, //z*面上的纹理,此上两个都是从左下角两个逆时针画 从(0,0)开始纹理 -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, //x*面的纹理 逆时针 -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 //y*面的纹理 顺时针 //xz*面顺时针,y*面逆时针? //坐标z相反,xy同向? }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // texture coord attribute glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glGenTextures(1, &texture1); glBindTexture(GL_TEXTURE_2D, texture1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); QImage img1 = QImage("container.jpg").convertToFormat(QImage::Format_RGB888); if (!img1.isNull()) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img1.width(), img1.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, img1.bits()); glGenerateMipmap(GL_TEXTURE_2D); } glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); QImage img2 = QImage("awesomeface.png").convertToFormat(QImage::Format_RGBA8888).mirrored(true, true); if (!img2.isNull()) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img2.width(), img2.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img2.bits()); glGenerateMipmap(GL_TEXTURE_2D); } shaderProgram.bind(); shaderProgram.setUniformValue("texture1", 0); shaderProgram.setUniformValue("texture2", 1); //建立模型矩阵之后我们位于(0,0,0),使用的是右手定则 //视图矩阵 QMatrix4x4 view; view.translate(QVector3D(0.0f, 0.0f, -3.0f));//这里将视图向后移动了,也就相当于把摄像机向前移动了 shaderProgram.setUniformValue("view", view); //投影矩阵,这个矩阵会交换坐标成为左手定则 QMatrix4x4 projection; /* 它的第一个参数定义了fov的值,它表示的是视野(Field of View), 并且设置了观察空间的大小。如果想要一个真实的观察效果,它的值通常设置为45.0f, 第二个参数设置了宽高比,由视口的宽除以高所得。 第三和第四个参数设置了*截头体的*和远*面。 我们通常设置*距离为0.1f,而远距离设为100.0f。所有在**面和远*面内且处于*截头体内的顶点都会被渲染。 */ projection.perspective(45.0f, 1.0f * width() / height(), 0.1f, 100.0f);//第二个参数控制的是比例缩放 shaderProgram.setUniformValue("projection", projection); shaderProgram.release(); } void CoreFunctionWidget::resizeGL(int w, int h) { glViewport(0, 0, w,h); } static QVector3D 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) }; void CoreFunctionWidget::paintGL() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 现在需要清空颜色和深度的缓存 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture2); shaderProgram.bind(); // render boxes glBindVertexArray(VAO); for (unsigned int i = 0; i < 10; i++) { // 模型矩阵 QMatrix4x4 model; model.translate(cubePositions[i]);//*移操作 float angle = (i + 1.0f) * m_nTimeValue;//旋转的角度 model.rotate(angle, QVector3D(1.0f, 0.3f, 0.5f));//旋转操作 shaderProgram.setUniformValue("model", model);//连接到着色器 glDrawArrays(GL_TRIANGLES, 0, 36);//从0开始绘制 } shaderProgram.release(); }
顶点着色器
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(){ gl_Position = projection * view * model * vec4(aPos, 1.0f); TexCoord = aTexCoord; }
片段着色器
#version 330 core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D texture1; uniform sampler2D texture2; void main() { FragColor = mix(texture2D(texture1, TexCoord), texture2D(texture2, TexCoord), 0.2f); }