将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. Ironic 的 Rescue 救援模式实现流程
  2. Shell 数组中 @ 跟 * 的区别
  3. ReactNative生成android平台的bundle文件命令
  4. Javascript中的valueOf与toString
  5. js对当前时间的相关操作
  6. 幼儿园视频监控系统设计方案
  7. 梦幻星空PSD分层海报素材,通过临摹打开思路。
  8. 剑指 Offer II 024. 反转链表
  9. *第二周*数据结构实践项目一【交换】
  10. 使用jquery获取父元素或父节点的方法
  11. 【RRT三维路径规划】基于matlab RRT算法无人机三维路径规划【含Matlab源码 1270期】
  12. gradle配置阿里Maven仓库
  13. SAP MM组织结构及概念
  14. ZooKeeper session has been expired
  15. windos无法对计算机进行,电脑提示windows无法完成格式化如何解决
  16. 地球币earthcoin表情包征图大赛正式筹备准备中
  17. SpringBoot配置文件中spring.profiles.active配置详解
  18. js电影票预订座位网页js特效
  19. 2019年天津大学计算机专业本校保研经验帖
  20. python携程gevent_python gevent 协程

热门文章

  1. 会画画的计算机学霸,国际班超牛学霸 琴棋书画全能的计算机高手
  2. jvm相关,垃圾收集算法,垃圾收集器,jvm调优--学习笔记
  3. 2019年猪年颁奖典礼、公司年会、跨年晚会、科技会议、年终答谢会之幕布背景展板PSD模板-第二部分...
  4. 麦肯锡报告笔记-银行盈利能力分析
  5. 人工智能前沿——「全域全知全能」人类新宇宙ChatGPT
  6. 第五届ACM/IEEE边缘计算国际研讨会 论文征集
  7. 关于“不要重复造轮子”的不同看法
  8. 移动地图时地图自动获取当前地图中心地区
  9. 【网单服务端】团队索尼克赛车PC端赛车类游戏单机服务端
  10. 今天下载了一个刷机大师,结果把android的端口给占了。郁闷了很久