开发环境
vs2015+Qt5
实现结果
我最后实现的目标就是在界面中嵌入一个组件,然后组件显示opengl和进行交互。
实现步骤
创建拖放组件
- 创建一个Qt工程
- 在.ui文件上拖放一个Widget组件
- 创建一个用于显示的SceneWindow的类
- 在.ui文件中将Widget提升为SceneWindow类
显示基本的图形
- 创建Shader文件
- 使用加载shader,创建相应的VAO VBO
- 绘制相应的立方体
具体实现与代码
1 创建Qt工程
2 创建之后打开learnqt.ui文件
拖放左侧的Widget组件到界面中
3 创建用于显示的SceneWindow类
scenewindow.hpp文件
#pragma once
#include <QtWidgets/QOpenGLWidget>
#include <QtGui/QOpenGLFunctions_3_3_Core>
#include <vector>
#include <QOpenGLShaderProgram>
class SceneWindow : public QOpenGLWidget,
protected QOpenGLFunctions_3_3_Core
{
Q_OBJECT
public:
SceneWindow(QWidget *parent = 0);
~SceneWindow();
void initializeGL();
void resizeGL(int width, int height);
void paintGL();
private:
//着色器程序 VAO VBO EBO
QOpenGLShaderProgram shaderCube;
GLuint NumVAOGw = 2; //VAO的数目
GLuint NumVBOGw = 2; //VBO的数目
GLuint NumEBOGw = 1; //EBO的数目
std::vector<GLuint> IDVAO;
std::vector<GLuint> IDVBO;
std::vector<GLuint> IDEBO;
};
scenewindow.cpp文件
#include <iostream>
#include <QtGui/QMouseEvent>
#include "scenewindow.hpp"
SceneWindow::SceneWindow(QWidget *parent)
:QOpenGLWidget(parent)
{
//设置OpenGL的版本信息
QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3, 3);
setFormat(format);
}
SceneWindow::~SceneWindow()
{
}
void SceneWindow::initializeGL()
{
//初始化OpenGL函数
initializeOpenGLFunctions();
//设置全局变量
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
}
void SceneWindow::paintGL()
{
//清理屏幕
glClear(GL_COLOR_BUFFER_BIT);
//实现参数的刷新
update();
//强制刷新缓冲区,保证命令被执行
glFlush();
}
void SceneWindow::resizeGL(int width, int height)
{
//未使用
Q_UNUSED(width);
Q_UNUSED(height);
}
4 将.ui文件中的widget提升为 SceneWindow组件
打开learnqt.ui,右击选择提升为:
增加SceneWindow类以及对应的头文件,之后选择提升
5 创建Shader文件
我们需要创建一个 顶点着色器和一个片段着色器
新建一个shader文件夹,创建simple.vert 和simple.grag两个文件
simple.vert
#version 330 core
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 vColor;
out vec3 Color;
void main()
{
gl_Position = vec4(vPosition, 1.0);
Color = vColor;
}
simple.frag
#version 330 core
in vec3 Color;
out vec4 fColor;
void main()
{
fColor = vec4(Color, 1.0f);
}
6 使用加载shader,创建相应的VAO VBO
完善initializeGL函数
void SceneWindow::initializeGL()
{
//初始化OpenGL函数
initializeOpenGLFunctions();
//设置全局变量
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
//初始化立方体着色器程序
shaderCube.addShaderFromSourceFile(QOpenGLShader::Vertex, "shader/simple.vert");
shaderCube.addShaderFromSourceFile(QOpenGLShader::Fragment, "shader/simple.frag");
shaderCube.link();
//初始化VAO VBO EBO
IDVAO.resize(NumVAOGw);
IDVBO.resize(NumVBOGw);
IDEBO.resize(NumEBOGw);
/******************************** 设置顶点数据 ********************************/
//正方体
GLfloat vertices[] =
{
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f
};
GLuint indices[] =
{
0, 1, 2, 2, 3, 0, //前
4, 5, 6, 6, 7, 4, //后
0, 4, 7, 7, 3, 0, //左
1, 5, 6, 6, 2, 1, //右
0, 4, 5, 5, 1, 0, //上
3, 7, 6, 6, 2, 3 //下
};
// VAO VBO
/* 创建相关对象 */
glGenVertexArrays(NumVAOGw, &IDVAO[0]);
glGenBuffers(NumVBOGw, &IDVBO[0]);
glGenBuffers(NumEBOGw, &IDEBO[0]);
/* 显示立方体 */
glBindVertexArray(IDVAO[0]); //开始记录状态信息
glBindBuffer(GL_ARRAY_BUFFER, IDVBO[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IDEBO[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0); //结束记录状态信息
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); //在VAO后解绑,是为了不让VAO把解绑EBO的信息包含进入
/* 固定属性区域 */
glEnable(GL_DEPTH_TEST); //开启深度测试
}
7 绘制相应的立方体
完善 paintGL 函数
void SceneWindow::paintGL()
{
//清理屏幕
glClear(GL_COLOR_BUFFER_BIT);
//实现参数的刷新
update();
//渲染彩色正方体
shaderCube.bind();
glBindVertexArray(IDVAO[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); //释放VAO
//强制刷新缓冲区,保证命令被执行
glFlush();
}
下一篇 OpenGL+Qt界面(三) Qt中实现OPENGL的基本交互+代码
参考
版权声明:本文为qq_23440561原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。