将learningopengl入门篇的Coordinate Systems代码在QT框架下实现,绘制一些带纹理贴图的动态立方体


目录

  • 一、环境
  • 二、代码实现
    • glm
    • 着色器类 shader.h
    • 着色器
    • 纹理贴图
    • stb_image.h
    • QOpenGL控件
    • 初始化
    • 渲染 render
    • timer刷新和动态
  • 相关链接和参考

一、环境

操作系统:Windows 11
IDE:Microsoft Visual Studio Community 2022 (64 位)
QT:5.12.12

二、代码实现

learningopengl Hello Triangle章节教程:

https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/

我们要做的是这节教程最后的绘制10个立方体,相应的GLFW框架下的代码:

https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/6.3.coordinate_systems_multiple/coordinate_systems_multiple.cpp

对照GLFW框架下代码进行以下修改

glm

和二维渲染不同,在三维空间下显示、渲染涉及到物体的平移、旋转和相机的计算,需要大量的矩阵运算,OpenGL内没有实现矩阵运算的方法,常用的第三方库是GLM,教程中的代码使用的也是这个库

我使用的版本是glm0.9.9.8,下载链接:

https://github.com/g-truc/glm/tags

GLM是一个header only库,只需要包括了相应的头文件就可以使用它提供的类和函数。不需要进行额外的编译,只要设置工程的头文件包含目录即可。

着色器类 shader.h

教程中实现了一个自己的着色器类

https://learnopengl.com/code_viewer_gh.php?code=includes/learnopengl/shader.h

这部分代码直接拿过来用,需要进行一些修改

glad->QOpenGLFunctions
对头文件进行替换

//#include <glad/glad.h>
#include <QOpenGLFunctions>

QT框架下Shader类需要继承QOpenGLFunctions类,才能初始化和使用OpenGL的方法

class Shader : protected QOpenGLFunctions
{.........
}

初始化OpenGL函数指针,在构造函数最前面调用initializeOpenGLFunctions

 Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr){this->initializeOpenGLFunctions();.........}

删除所有utility uniform functions相关方法的const修饰,这个应该是编译器差异的问题

着色器

教程中着色器代码写在了两个文件中

https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/6.3.coordinate_systems_multiple/6.3.coordinate_systems.vs
https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/6.3.coordinate_systems_multiple/6.3.coordinate_systems.fs

直接创建两个相同的文件,并确保程序运行时能找到这两个文件

纹理贴图

教程中用到了木箱和笑脸的两个贴图

https://learnopengl-cn.github.io/img/01/06/container.jpg
https://learnopengl-cn.github.io/img/01/06/awesomeface.png

将他们下载下来放在resources\textures\目录下,下面程序调用时是从这个目录读取

stb_image.h

读取纹理贴图时用到了这个单头像图像加载库stb_image.h

https://github.com/nothings/stb/blob/master/stb_image.h

使用这个库需要两个文件stb_image.hstb_image.cppstb_image.h直接下载,stb_image.cpp只需要两行代码

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

QOpenGL控件

新建一个QOpenGL控件类CoordinateSystemsMultipleWidget,继承QOpenGLWidget类,并重载initializeGLresizeGLpaintGL三个方法,包含glm的头文件和stb_image.h,代码如下

#include "CoordinateSystemsMultipleWidget.h"
#include "stb_image.h"#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <qDebug>CoordinateSystemsMultipleWidget::CoordinateSystemsMultipleWidget(QWidget* parent): QOpenGLWidget(parent)
{}CoordinateSystemsMultipleWidget::~CoordinateSystemsMultipleWidget()
{}void CoordinateSystemsMultipleWidget::initializeGL()
{this->initializeOpenGLFunctions();    //为当前上下文初始化提供OpenGL函数解析
}void CoordinateSystemsMultipleWidget::resizeGL(int w, int h)
{glViewport(0.0f, 0.0f, w, h);    //调整视口
}void CoordinateSystemsMultipleWidget::paintGL()
{}

初始化

复制将教程中main函数中while (!glfwWindowShouldClose(window))之前的初始化代码,找到上一步新建的CoordinateSystemsMultipleWidget控件类的initializeGL()方法,在initializeOpenGLFunctions后粘贴。

1、删除最前面的GLFW初始化的代码和GLAD初始化的代码。

2、替换VAO相关的代码

 unsigned int VAO; // 声明glGenVertexArrays(1, &VAO); // 创建glBindVertexArray(VAO); // 绑定glBindVertexArray(0); // 解绑

分别替换为

    QOpenGLVertexArrayObject VAO; // 声明VAO.create(); // 创建if(!VAO.isCreated()){qDebug()<<"vao is not created.";}VAO.bind(); // 绑定VAO.release(); // 解绑

3、stbi_load使用的FileSystem::getPath获取路径的方法报错,删除他们,直接写入字符串即可

渲染 render

复制将教程中main函数中while (!glfwWindowShouldClose(window))中渲染部分的代码,粘贴到CoordinateSystemsMultipleWidget控件类的paintGL()方法中

1、删除键盘、鼠标时间响应的代码processInput(window)和最后面glfw相关的两行代码

2、ourShadertexture1texture2变量报错,将initializeGL()中他们的定义的移动到函数外或类内,并修改相应的初始化代码和调用代码

3、将SCR_WIDTHSCR_HEIGHT改为this->width()this->height()

4、修改glBindVertexArray(VAO);VAO.bind();

5、cubePositions报错,将其定义从initializeGL()中移动到函数外。

timer刷新和动态

到目前为止,教程中的代码已经全部在QT框架下实现,编译运行就能看到空间中的立方体,表面覆盖了木箱和笑脸的纹理贴图

但是显示的内容是静止的,这是因为在代码中每个立方体的位置和姿态都是静止的,并且我们也没有不断的调用paintGL()中的渲染代码。

initializeGL()方法的最后面开启一个定时器,定时调用update()方法,实现界面的不断刷新

void CoordinateSystemsMultipleWidget::initializeGL()
{.........timer = new QTimer();timer->setInterval(33);connect(timer, SIGNAL(timeout()), this, SLOT(update()));timer->start();
}

paintGL()方法中,在model = glm::translate(model, cubePositions[i]);后增加一行代码让模型旋转起来

     model = glm::rotate(model, angle, glm::vec3(0.5f, 1.0f, 0.0f));

最终paintGL()方法的代码为:

void CoordinateSystemsMultipleWidget::paintGL()
{// render// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now!// bind textures on corresponding texture unitsglActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, texture1);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, texture2);// activate shaderourShader->use();// create transformationsglm::mat4 view = glm::mat4(1.0f); // make sure to initialize matrix to identity matrix firstglm::mat4 projection = glm::mat4(1.0f);projection = glm::perspective(glm::radians(45.0f), (float)this->width() / (float)this->height(), 0.1f, 100.0f);view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));// pass transformation matrices to the shaderourShader->setMat4("projection", projection); // note: currently we set the projection matrix each frame, but since the projection matrix rarely changes it's often best practice to set it outside the main loop only once.ourShader->setMat4("view", view);// render boxesVAO.bind();static float angle = 0;angle += 0.1;if (angle >= 360)angle -= 360;for (unsigned int i = 0; i < 10; i++){// calculate the model matrix for each object and pass it to shader before drawingglm::mat4 model = glm::mat4(1.0f);model = glm::translate(model, cubePositions[i]);model = glm::rotate(model, angle, glm::vec3(0.5f, 1.0f, 0.0f));float angle = 20.0f * i;model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));ourShader->setMat4("model", model);glDrawArrays(GL_TRIANGLES, 0, 36);}
}

再次编译运行,界面中的每个立方体都旋转起来了。


相关链接和参考

https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/
https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/6.3.coordinate_systems_multiple/coordinate_systems_multiple.cpp
https://blog.csdn.net/qq_42537915/article/details/104146135

QT+OpenGL实现Coordinate Systems,绘制立方体相关推荐

  1. android平台下OpenGL ES 3.0绘制立方体的几种方式

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  2. OpenGL ES for Android 绘制立方体

    立方体有6个面,8个顶点,因此绘制立方体其实就是绘制6个面. 顶点shader attribute vec4 a_Position; attribute vec4 a_color; varying v ...

  3. android平台下OpenGL ES 3.0绘制圆点、直线和三角形

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  4. android平台下OpenGL ES 3.0绘制纯色背景

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  5. OpenGL ES for Android 绘制旋转的地球

    No 图 No Code,我们先来欣赏下旋转的地球: 是不是很酷炫,要想绘制出上面酷炫的效果需要3个步骤: 计算球体顶点数据 地球纹理贴图 通过MVP矩阵旋转地球 计算球体顶点数据 我们知道OpenG ...

  6. 采用QT进行OpenGL开发(二)绘制立方体

    在OpenGL中三维实体会被拆分成一个个小的平面图形来进行绘制.比如我们绘制的立方体,可以拆分成六个平面来进行绘制.这里我们以一个带纹理的正方体来说明一下三维实体的绘制方法. 绘制立方体 由于正方体的 ...

  7. 【Modern OpenGL】坐标系统 Coordinate Systems

    说明:跟着learnopengl的内容学习,不是纯翻译,只是自己整理记录. 强烈推荐原文,无论是内容还是排版. 原文链接 本文地址: http://blog.csdn.net/aganlengzi/a ...

  8. OpenGL(十八)——Qt OpenGL绘制一个3D世界

    OpenGL(十八)--Qt OpenGL绘制一个3D世界 一.说明 本篇介绍构建一个3D的世界. 二.简介 加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游. ...

  9. OpenGL coordinate systems坐标系统的实例

    OpenGL coordinate systems坐标系统 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> ...

最新文章

  1. [Treap]JZOJ 4737 金色丝线将瞬间一分为二
  2. 如何安装vscode网页版_Windows10专业版/企业版如何安装Microsoft store
  3. php 怎么防注入,php 防止注入的几种办法
  4. .Net Core下如何管理配置文件
  5. 【虚拟化】docker部署nginx
  6. 在C++中调用DLL中的函数
  7. Grid game CodeForces - 1104C 放格子|思维|找规律
  8. android edittext不可复制_Android 禁止输入框 EditText 复制粘贴
  9. 通过maven test 报org.apache.ibatis.binding.BindingException: Invalid bound statement
  10. python代码求和_python求和代码
  11. 设备接入(LWM2M协议)
  12. 如何在网上隐藏自己的IP地址(转)
  13. 有趣的Javascript:只需一个JS让万恶的IE5、IE6、IE7、IE8全都支持H5原生Canvas绘图(有演示demo)
  14. 灵性图书馆:好书推荐-《在荷欧波诺波诺中遇见真正的自己》
  15. 阈值、阙值 有没有阀值?
  16. 程序设计 模拟排球比赛分析
  17. CSS Flexbox 青蛙游戏
  18. 前端利用docker在linux上部署nginx服务
  19. 利用Dynamo建立桥梁下部结构—桥墩系梁盖梁
  20. 因果推理(三):关联和因果在因果图中的流动

热门文章

  1. 七年级用计算机写作教案,七年级信息技术《建立工作表》的教案设计
  2. 用Arduino结合OLED、DHT11测量温湿度
  3. 【软件分析/静态程序分析学习笔记】2.中间表示(Intermediate Representation)
  4. 一阶低通滤波器方程_一阶低通滤波器_一阶低通滤波器公式_一阶低通滤波器原理...
  5. 计算机素养大赛基础赛项,全国大学生计算机应用能力与信息素养大赛竞赛大纲ICGS4赛项.DOC...
  6. 微信新版本7.0.4,漂流瓶真的凉了......
  7. 第三方软件测试的重要性
  8. BannerPlugin插件使用
  9. Pyth笔记-高级装饰器
  10. NPDP产品经理小知识:创意工具-PESTLE分析