OpenGL+Qt界面(二) 创建界面,并增加显示OpenGL的组件

开发环境

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的基本交互+代码

参考

如何在Qt5中嵌入一个OpenGL程序部件
QOpenGLShaderProgram文档


版权声明:本文为qq_23440561原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。