OpenGL中环境搭建

近期由于需要做一个GUI展示的OpenGL程序,因此想到用QT来做界面,需要在QT中写OpenGL,配完环境后,在这里总计一下。

QT基础

总体看来,QT的版本较为混乱,有时候傻傻弄不清楚,QT dialog/widget/mainwindow。又需要有界面,又要有pro文件,一圈下来,加上网上教程版本混乱,已经凌乱了。后来在同学帮助下,看了一些博客教程,综合了一下,总算把架子搭起来了。本文使用的版本信息如下:
QT版本:QT 5.6.2
VS版本:VS 2013

工程选择:
本文选择的是QT的widgt类别,QT各个类别的区别在于继承于不同的基类,正常的widgt是最基础的,不默认含有菜单栏这些东西,需要的话我们自己添加。选择建立工程时不建立UI文件,在编程中发现使用UI文件会较为混乱,不方便控制,因此代码中所有的UI都是由代码控制的。以下是代码结构:

// main.cpp
// main是主入口,QApplication是生成一个QT应用,widget是继承自Qwidget的子类,具有show函数,实例化后将会产生一个窗口,同时我们也可以在main函数中实例化多个窗口,将会有多个界面,比如实例化一个button。
#include "widget.h"
#include <QApplication>
#include <QPushButton>int main(int argc, char *argv[])
{QApplication a(argc, argv);
// 主窗口Widget w;w.show();
// 实例化一个buttonQPushButton q;q.show();return a.exec();
}

实例化button的效果:

所以,主要的工作就是往我们的widget类中添加控件,实现功能即可。主widget代码如下,继承自QWeidget:

class Widget : public QWidget
{Q_OBJECT// 一个宏,声明为QT的object,方便传参public:Widget(QWidget *parent = 0);~Widget();    Q_OpenGL *q_widget_1;Q_OpenGL *q_widget_2;QGridLayout * main_layout;QPushButton * q_pushbutton_1;QPushButton * q_pushbutton_2;QMenuBar * q_menubar;QMenu * q_menu;QStatusBar * q_status;QLabel * q_label;public slots:void triggerMenu(QAction * qa);
};

QT中的OpenGL

QT中为我们把OpenGL进行了封装,使用较原生OpenGL简单

  • QT中的OpenGL,已经包含了OpenGL的大部分功能,包含如下头文件

    • OpenGLWindow
    • QOpenGLWidget
    • QOpenGLFunctions
    • QOpenGLBuffer

在QT中写OpenGL需要继承自QOpenGLWidget,同时重写两个函数initializeGL【初始化OpenGL环境】和paintGL【主绘画的循环】。相对于原生的OpenGL复杂的初始化和绘制过程,十分简洁。以下是头文件和部分源代码。

// .h
class Q_OpenGL:public QOpenGLWidget,protected QOpenGLFunctions
{Q_OBJECTpublic:explicit Q_OpenGL(QWidget *parent = 0);~Q_OpenGL();void initializeGL();// 初始化void paintGL();// 主绘制void setUp();void compileShader();QOpenGLShaderProgram *program;Shader * shader;Model * model;
};// .cpp
// 初始化OpenGL
void Q_OpenGL::initializeGL()
{initializeOpenGLFunctions();glClearColor(1.0f, 0.0f, 0.0f, 1.0f);setUp();compileShader();    }
// 编译shader
void Q_OpenGL::compileShader()
{std::ifstream vs("E:\\Documents\\Qt\\qtWindows\\normal.vs");std::string vertexCode;std::string fragmentCode;if (vs.is_open()){std::string line;while (getline(vs, line)) {vertexCode.append(line);vertexCode.append("\n");}vs.close();}vs.open("E:\\Documents\\Qt\\qtWindows\\normal.fs");//qDebug()<<"8989"<<endl;if (vs.is_open()) {std::string line;while (getline(vs, line)) {fragmentCode.append(line);fragmentCode.append("\n");}vs.close();}qDebug() << "hhhh" << endl;QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);vshader->compileSourceCode(vertexCode.c_str());QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);fshader->compileSourceCode(fragmentCode.c_str());program = new QOpenGLShaderProgram;program->addShader(vshader);program->addShader(fshader);//program->bindAttributeLocation("vertex", PROGRAM_VERTEX_ATTRIBUTE);//program->bindAttributeLocation("texCoord", PROGRAM_TEXCOORD_ATTRIBUTE);program->link();program->bind();//program->setUniformValue("texture", 0);
}
// 传递数据到VBO
void Q_OpenGL::setUp()
{int coords[3][2] = { -1, -1, 0, 1, 1, -1 };QVector<float> vertData;for (int i = 0; i < 3; ++i)for (int j = 0; j < 2; ++j)         vertData.append(coords[i][j]);vbo.create();vbo.bind();vbo.allocate(vertData.constData(), vertData.count() * sizeof(float));
}// 主绘制函数
void Q_OpenGL::paintGL()
{glClear(GL_COLOR_BUFFER_BIT);program->enableAttributeArray(PROGRAM_VERTEX_ATTRIBUTE);//program->enableAttributeArray(PROGRAM_TEXCOORD_ATTRIBUTE);program->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 2, 2 * sizeof(float));//program->setAttributeBuffer(PROGRAM_VERTEX_ATTRIBUTE, GL_FLOAT, 0, 3, 0 * sizeof(GLfloat));//program->setAttributeBuffer(PROGRAM_TEXCOORD_ATTRIBUTE, GL_FLOAT, 3 * sizeof(GLfloat), 2, 5 * sizeof(GLfloat));glDrawArrays(GL_TRIANGLES, 0, 3);
}

以上代码基本展示QT中OpenGL的编写过程,代码有一些不匹配,可以查看QT官方的OpenGL例子即可。【我参考的是textures例子】

QT中使用原生OpenGL

在使用中,发现QT中的OpenGL与原生差异较大,移植代码会有一些问题。所以考虑将原生OpenGL移植到QT中,使用QT的OpenGL进行初始化,但在绘制,shader方面使用原生的OpenGL。

但在实践中发现,QT中的OpenGL和原生的OpenGL会出现冲突,无法同时初始化。网上找了解决方案,需要将原生的OpenGL与QT的OpenGL进行隔离,不能出现在同一个cpp中,于是将类的声明和定义分离【==原来图方便写在了一起】,主要是shader编译类,模型类。在头文件中声明,定义和初始化OpenGL延迟到cpp时,再将头文件引入到主程序中,这样就可以使用原生OpenGL

tips:在实际操作时,不知道为何glad无法初始化,改用glew才成功。以下是通过的代码:

// shader.h
#ifndef SHADER_H
#define SHADER_H
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>class Shader
{
public:unsigned Program;Shader(const char* vertexPath, const char* fragmentPath);~Shader();void Use();void setBool(const std::string &name, bool value) const;void setInt(const std::string &name, int value) const;void setFloat(const std::string &name, float value) const;void setVec2(const std::string &name, const glm::vec2 &value) const;void setVec2(const std::string &name, float x, float y) const;void setVec3(const std::string &name, const glm::vec3 &value) const;void setVec3(const std::string &name, float x, float y, float z) const;void setVec4(const std::string &name, const glm::vec4 &value) const;void setVec4(const std::string &name, float x, float y, float z, float w) const;void setMat2(const std::string &name, const glm::mat2 &mat) const;void setMat3(const std::string &name, const glm::mat3 &mat) const;void setMat4(const std::string &name, const glm::mat4 &mat) const;
};#endif// shader.cpp,只列出部分
//#include <glad/glad.h>
#define GLEW_STATIC
#include <gl/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "shader.h"
using namespace std;Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{}Shader::~Shader()
{}void Shader::Use()
{glUseProgram(this->Program);
}// model.h
#pragma once
#include "shader.h"
class Model
{
public:void setUp();void draw(Shader *);unsigned VAO;unsigned VBO;
};// 更新后的qtOpenGL
#ifndef Q_OPENGL_H
#define Q_OPENGL_H#include <QOpenGLWindow>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include "shader.h"
#include "model.h"QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram);
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)class Q_OpenGL:public QOpenGLWidget,protected QOpenGLFunctions
{Q_OBJECTpublic:explicit Q_OpenGL(QWidget *parent = 0);~Q_OpenGL();void initializeGL();void paintGL();void setUp();void compileShader();QOpenGLShaderProgram *program;Shader * shader;Model * model;
};#endif // Q_OPENGL_H// QOpenGL实现
#include "q_opengl.h"
#include <QOpenGLBuffer>
#include <QMouseEvent>
#include <QOpenGLShaderProgram>
#include <QFile>
#include <QVector>
#include <fstream>
#include <string>
#include <iostream>Q_OpenGL::Q_OpenGL(QWidget *parent):QOpenGLWidget(parent)
{}void Q_OpenGL::initializeGL()
{initializeOpenGLFunctions();glClearColor(1.0f, 0.0f, 0.0f, 1.0f);   shader = new Shader("E:\\Documents\\Qt\\qtWindows\\normal.vs", "E:\\Documents\\Qt\\qtWindows\\normal.fs");model = new Model();model->setUp();
}void Q_OpenGL::paintGL()
{glClear(GL_COLOR_BUFFER_BIT);model->draw(shader);
}Q_OpenGL::~Q_OpenGL()
{}

效果图如下:

如有问题欢迎联系指出~

QT中OpenGL开发起步相关推荐

  1. 基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件

    [开源]基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件 码云地址 https://gitee.com/Barryda/QtScrcpy github地址 https://github. ...

  2. qt中opengl窗口的创建

    该笔记借鉴自 : "懂deeee珍惜"的 现代OpenGL+Qt学习笔记之二:程序框架 "爱种鱼的猫"的 QT中使用OpenGL(0)--创建一个窗口 引用引自 ...

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

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

  4. Qt中openGL的四个重要事件(initializeGL() resizeGL() paintGL() pdateGL())调用规则

    initializeGL函数由于是初始化,所以只调用一次 而resizeGL和paintGL会多次调用 resizeGL在正常的情况下,触发的条件是,窗口大小发生变化时,resizeGL被调用,之后会 ...

  5. Qt学习笔记-Qt中OpenGL的使用

    现在窗口中心即为坐标原点,X轴从左到右,Y轴从下到上,Z轴从里到外. 程序运行截图如下: 源码如下: myglwidget.h #ifndef MYGLWIDGET_H #define MYGLWID ...

  6. QT中使用OpenGL绘制图形

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  7. Qt中使用OpenGL进行绘图

    Qt Creator中的3D绘图及动画教程(参照NeHe) 刚刚学习了Qt Creator,发现Qt提供了QtOpenGL模块,对OpenGL做了不错的封装,这使得我们可以很轻松地在Qt程序中使用Op ...

  8. Qt中使用GLEW进行OpenGL开发

    Qt中使用GLEW进行OpenGL开发(Windows平台) 为什么要使用GLEW 使用VS创建Qt项目 设置Widget 重新实现paintEngine 添加GLEW库到工程 设置OpenGL上下文 ...

  9. Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染

    Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染 上一篇文章讲到了利用C++这个桥梁,我们实现了QML和Java的交互.Qt 5大力推崇的QML/JS开发,让轻量.高速开发的QML/J ...

最新文章

  1. linux 2.6.35 arm map_lowmem,第一次玩arm和linux,9261移植2.6.39无法挂载jiffys2文件系统,谁能指点一下...
  2. 微信小程序AES加密解密
  3. 2016 湖南省省赛B题《有向无环图》
  4. Windows批处理(cmd/bat)常用命令
  5. new Date('2014/04/30') 和 new Date('2014-04-30') 的区别
  6. TortoiseGit 单文件版本对比_入门试炼_09
  7. .net core 开发 Windows Forms 程序
  8. 瑞典禁止在5G网络中用华为和中兴设备 同时也将移除老设备
  9. Linux中使用tar打包解包查看的使用方法
  10. [转载]SVN使用教程
  11. 怎样让手机打电话显示不在服务器,要怎样设置才让对方打电话进来是空号?
  12. Java8实战[1-4]章要义笔记
  13. [笔记分享] [Camera] 相机的flash led功能小结
  14. Spring源码解析系列汇总
  15. 网易云信短信功能使用
  16. 怎么取消计算机文件共享,Win10系统怎么取消文件共享
  17. 不积跬步 无以至千里
  18. html明月几时有古诗,古诗词赏析|苏轼《水调歌头·明月几时有》
  19. 虚拟化kvm-虚拟化概述
  20. Excel VBA保护工作表

热门文章

  1. Fibonacci数 南阳理工ACM 题目13
  2. Linux 下监控USB设备拔插事件
  3. 谷歌浏览器的快捷键一览(图片)
  4. Linux的gedit没有权限,Ubuntu下有关gedit的各种问题
  5. Kali系统工具介绍 从入门到入狱
  6. 如何用阿里云腾讯云服务器部署属于自己的私有云盘/网盘?
  7. 操作系统练习题(5)第六章文件管理
  8. 函数声明后面的const用法
  9. JavaScript中分号;的使用注意
  10. matlab 基础函数 floor、conv、histeq、im2bw