QT+OpenGL实现Coordinate Systems,绘制立方体
将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.h
和stb_image.cpp
,stb_image.h
直接下载,stb_image.cpp
只需要两行代码
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
QOpenGL控件
新建一个QOpenGL控件类CoordinateSystemsMultipleWidget
,继承QOpenGLWidget
类,并重载initializeGL
、resizeGL
、paintGL
三个方法,包含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、ourShader
、texture1
和texture2
变量报错,将initializeGL()
中他们的定义的移动到函数外或类内,并修改相应的初始化代码和调用代码
3、将SCR_WIDTH
和SCR_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,绘制立方体相关推荐
- android平台下OpenGL ES 3.0绘制立方体的几种方式
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- OpenGL ES for Android 绘制立方体
立方体有6个面,8个顶点,因此绘制立方体其实就是绘制6个面. 顶点shader attribute vec4 a_Position; attribute vec4 a_color; varying v ...
- android平台下OpenGL ES 3.0绘制圆点、直线和三角形
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- android平台下OpenGL ES 3.0绘制纯色背景
OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...
- OpenGL ES for Android 绘制旋转的地球
No 图 No Code,我们先来欣赏下旋转的地球: 是不是很酷炫,要想绘制出上面酷炫的效果需要3个步骤: 计算球体顶点数据 地球纹理贴图 通过MVP矩阵旋转地球 计算球体顶点数据 我们知道OpenG ...
- 采用QT进行OpenGL开发(二)绘制立方体
在OpenGL中三维实体会被拆分成一个个小的平面图形来进行绘制.比如我们绘制的立方体,可以拆分成六个平面来进行绘制.这里我们以一个带纹理的正方体来说明一下三维实体的绘制方法. 绘制立方体 由于正方体的 ...
- 【Modern OpenGL】坐标系统 Coordinate Systems
说明:跟着learnopengl的内容学习,不是纯翻译,只是自己整理记录. 强烈推荐原文,无论是内容还是排版. 原文链接 本文地址: http://blog.csdn.net/aganlengzi/a ...
- OpenGL(十八)——Qt OpenGL绘制一个3D世界
OpenGL(十八)--Qt OpenGL绘制一个3D世界 一.说明 本篇介绍构建一个3D的世界. 二.简介 加载3D世界,并在其中漫游: 在这一课中,你将学会如何加载3D世界,并在3D世界中漫游. ...
- OpenGL coordinate systems坐标系统的实例
OpenGL coordinate systems坐标系统 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> ...
最新文章
- [Treap]JZOJ 4737 金色丝线将瞬间一分为二
- 如何安装vscode网页版_Windows10专业版/企业版如何安装Microsoft store
- php 怎么防注入,php 防止注入的几种办法
- .Net Core下如何管理配置文件
- 【虚拟化】docker部署nginx
- 在C++中调用DLL中的函数
- Grid game CodeForces - 1104C 放格子|思维|找规律
- android edittext不可复制_Android 禁止输入框 EditText 复制粘贴
- 通过maven test 报org.apache.ibatis.binding.BindingException: Invalid bound statement
- python代码求和_python求和代码
- 设备接入(LWM2M协议)
- 如何在网上隐藏自己的IP地址(转)
- 有趣的Javascript:只需一个JS让万恶的IE5、IE6、IE7、IE8全都支持H5原生Canvas绘图(有演示demo)
- 灵性图书馆:好书推荐-《在荷欧波诺波诺中遇见真正的自己》
- 阈值、阙值 有没有阀值?
- 程序设计 模拟排球比赛分析
- CSS Flexbox 青蛙游戏
- 前端利用docker在linux上部署nginx服务
- 利用Dynamo建立桥梁下部结构—桥墩系梁盖梁
- 因果推理(三):关联和因果在因果图中的流动
热门文章
- 七年级用计算机写作教案,七年级信息技术《建立工作表》的教案设计
- 用Arduino结合OLED、DHT11测量温湿度
- 【软件分析/静态程序分析学习笔记】2.中间表示(Intermediate Representation)
- 一阶低通滤波器方程_一阶低通滤波器_一阶低通滤波器公式_一阶低通滤波器原理...
- 计算机素养大赛基础赛项,全国大学生计算机应用能力与信息素养大赛竞赛大纲ICGS4赛项.DOC...
- 微信新版本7.0.4,漂流瓶真的凉了......
- 第三方软件测试的重要性
- BannerPlugin插件使用
- Pyth笔记-高级装饰器
- NPDP产品经理小知识:创意工具-PESTLE分析