QtOpenGL(一)简单的三维点

1 篇文章 0 订阅

QtOpenGL(一) 简单的三维点的绘制


前言

OpenGL网上的例子也很多,之前也一直在用,最近又系统的看了一下,也总结了一下,我我们开始吧。
1、Qt里面内嵌了OpenGL的环境,对于出初学者很友好,至少我开始学习的时候没有那么的头疼。
2、其次吧有时候要在Linux下进行,又回到Qt跨平台上面了,emmmmmm。
3、Qt里面至少还是有一些Opengl的文档可以直接看的。不会了直接F1。

好了我们开始吧。


一、Qt中的OpenGL

Qt中的OpenGL也是经过包装的,本篇主要基于的是Qt5.14.2里面的QOpenGLWidget和QOpenGLFunctions_3_3_Core。当让也有其他的,我们就暂时用这两个吧。

二、效果

在这里插入图片描述

三、代码

1-- .h文件

class SpiderOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    SpiderOpenGLWidget(QWidget *parent = nullptr);
    ~SpiderOpenGLWidget();
private:
    void initializeGL();
    void paintGL();
    void resizeGL(int width, int height);
    
	unsigned int draw_PointDara();
public slots:
    void BuildPoint();
private:  
	Ui::SpiderOpenGLWidget *ui;
    QOpenGLShaderProgram shaderProgram_point;
    
    unsigned int VBO_Point;
    unsigned int VAO_Point;
    unsigned int point_count;
	QVector<float> m_pointData;
    QTimer* m_BulidPoint;
    QMutex  m_PointLook;
};

2–.cpp文件

代码如下(示例):

SpiderOpenGLWidget::SpiderOpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
    , ui(new Ui::SpiderOpenGLWidget)
{
    ui->setupUi(this);
    //抗锯齿
    QSurfaceFormat format;
    format.setSamples(4);
    setFormat(format);
    QSurfaceFormat fmt;
    fmt.setDepthBufferSize(24);
    setFormat(fmt);
	//造点
    m_BulidPoint = new QTimer;
    connect(m_BulidPoint,SIGNAL(timeout()),this,SLOT(BuildPoint()));
    m_BulidPoint->setInterval(100);
    m_BulidPoint->start();
    m_pointData.clear();
    m_pointData.append(0);//X轴
    m_pointData.append(10);//Y轴
    m_pointData.append(10);//Z轴
    m_pointData.append(100);
SpiderOpenGLWidget::~SpiderOpenGLWidget()
{
    delete ui;
    makeCurrent();
    glDeleteBuffers(1, &VBO_Point);
    glDeleteVertexArrays(1, &VAO_Point);
    shaderProgram_point.release();
    doneCurrent();
}

void SpiderOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);
    //点
    shaderProgram_point.bind();
    shaderProgram_point.addShaderFromSourceFile(QOpenGLShader::Vertex, "E:/4D/SpiderOpenGl/shader/shader_point.vs");
    shaderProgram_point.addShaderFromSourceFile(QOpenGLShader::Fragment, "E:/4D/SpiderOpenGl/shader/shader_point.fs");
    shaderProgram_point.link();
    shaderProgram_point.release();
}
void SpiderOpenGLWidget::paintGL()
{
    QMatrix4x4 projection, view, model;
    projection.perspective(zoom, (float)width() / (float)height(), 1.0f, 100.0f);
    view.lookAt(QVector3D(0.0, 0.0, 50.0), QVector3D(0.0, 0.0, 1.0), QVector3D(0.0, 1.0, 0.0));
    model.translate(0, 0, 0.0);
    model.rotate(-80.0, 1.0, 0.0, 0.0);
    model.rotate(0.0, 0.0, 0.0, 1.0);
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除缓存区

    //点
    m_PointLook.lock();
    shaderProgram_point.bind();
    shaderProgram_point.setUniformValue("projection", projection);
    shaderProgram_point.setUniformValue("view", view);
    shaderProgram_point.setUniformValue("model", model);
    point_count = draw_PointDara();
    glBindVertexArray(VAO_Point);
    glPointSize(5.0f);//点的大小
    glDrawArrays(GL_POINTS, 0, point_count);
    glDeleteBuffers(1, &VBO_Point);
    glDeleteVertexArrays(1, &VAO_Point);
    shaderProgram_point.release();
    m_PointLook.unlock();
}

void SpiderOpenGLWidget::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
}
void SpiderOpenGLWidget::BuildPoint()
{
//下面又两种不同常用造点方式,随机点
    qDebug()<<"PointDataPointData"<<m_pointData.size();
    if(m_pointData.size()>=1200)
    {
          m_pointData.clear();
//          glDeleteBuffers(500,&VAO_Point);
    }
    QTime randtime;
    randtime = QTime::currentTime();
    qsrand(randtime.msec()+randtime.second()*1000); //以当前时间ms为随机种子

    QRandomGenerator generator1 = QRandomGenerator::securelySeeded();
    float randomNumber1 = generator1.bounded(100);
    QRandomGenerator generator2 = QRandomGenerator::securelySeeded();
    float randomNumber2 = generator2.bounded(100);
    QRandomGenerator generator3 = QRandomGenerator::securelySeeded();
    float randomNumber3 = generator3.bounded(100);
    int n = qrand() % 100;    //产生100以内的随机整数
    float fn = float(n)/10;   //产生10以内的随机浮点数,精度为小数点后1位
//    qDebug()<<"BuildPointBuildPointBuildPoint"<<n;
    m_pointData.append(fn);//X轴
    m_pointData.append(randomNumber1);//Y轴
    m_pointData.append(randomNumber2);//Z轴
    m_pointData.append(randomNumber3);
    update();
}

unsigned int SpiderOpenGLWidget::draw_PointDara()
{
    unsigned point_count = 0;
    glGenVertexArrays(1, &VAO_Point);
    glGenBuffers(1, &VBO_Point);

    glBindVertexArray(VAO_Point);

    glBindBuffer(GL_ARRAY_BUFFER, VBO_Point);
    glBufferData(GL_ARRAY_BUFFER, m_pointData.size() * sizeof(float), &m_pointData[0], GL_STREAM_DRAW );//GL_STATIC_DRAW

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glBindVertexArray(0);

    point_count = m_pointData.size() / 4;
    return point_count;

}

四、注意

1、初始化

首先呢OpenGL的初始化是在initializeGL() 里面进行的。

1、当然Qt给我们提供了一个函数initializeOpenGLFunctions(); 我们只需要调用就好了。剩下的不用管。如果不使用的话将无法使用OpenL的函数。
2、接下来我们开启深度测试。

    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);

3、添加顶点着色器和片段着色器。着色器是OpenGL重要的一个部分,后面我们会细说。

    shaderProgram_axis.bind();
    shaderProgram_axis.addShaderFromSourceFile(QOpenGLShader::Vertex, "E:/4D/SpiderOpenGl/shader/shader_point.vert");
    shaderProgram_axis.addShaderFromSourceFile(QOpenGLShader::Fragment, "E:/4D/SpiderOpenGl/shader/shader_point.frag");
    shaderProgram_axis.link();
    shaderProgram_axis.release();

其中顶点着色器.vert如下所示:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aIntensity;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 ourColor;
void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    ourColor = vec3(0.0f, 1.0f, 1.0f);
}

其中片段着色器.frag如下所示:

#version 330 core
out vec4 FragColor;
in vec3 ourColor;
void main()
{
    FragColor = vec4(ourColor, 1.0f);
}

2、绘图

1、设置观测矩阵、投影矩阵、模型矩阵。
2、清除之前绘制的内容。

    QMatrix4x4 projection, view, model;
    projection.perspective(zoom, (float)width() / (float)height(), 1.0f, 100.0f);
    view.lookAt(QVector3D(0.0, 0.0, 50.0), QVector3D(0.0, 0.0, 1.0), QVector3D(0.0, 1.0, 0.0));
    model.translate(x_trans, y_trans, 0.0);
    model.rotate(x_rotate, 1.0, 0.0, 0.0);
    model.rotate(z_rotate, 0.0, 0.0, 1.0);
    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除缓存区

3、启用QOpenGLShaderProgram,绑定。
4、设置QOpenGLShaderProgram中的矩阵数据等。

    shaderProgram_point.bind();
    shaderProgram_point.setUniformValue("projection", projection);
    shaderProgram_point.setUniformValue("view", view);
    shaderProgram_point.setUniformValue("model", model);

5、VBO(Vertex Buffer Object,顶点缓冲对象)他管理建立在GUP上的顶点数据。在使用前我们先要生成一个VBO对象。
6、VAO(Vertex Array Object,顶点数组对象)他记录这已经配置好的顶点属性。绑定以后即便有多个VBO对象,只需要执行一次渲染的API就可以了。

    glGenVertexArrays(1, &VAO_Point);
    glGenBuffers(1, &VBO_Point);
    glBindVertexArray(VAO_Point);
    glBindBuffer(GL_ARRAY_BUFFER, VBO_Point);

7、完成上述初始化操作后我们将数据绑定到当前的缓冲上,也就是将造出来的点拷贝到缓存对象上。
8、然后将当前属性与VBO连接起来。在这里就是告诉显卡如何解析缓冲里的属性值。
5、然后开启VAO管理的第一个值。

    glBufferData(GL_ARRAY_BUFFER, m_pointData.size() * sizeof(float), &m_pointData[0], GL_STREAM_DRAW );//GL_STATIC_DRAW
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

9、解绑VBO

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

10、绘图

glDrawArrays(GL_POINTS, 0, point_count);

11、释放内存,如果进行的连续update,我们要进行内存的释放否则有大量的内存泄露。

    glDeleteBuffers(1, &VBO_Point);
    glDeleteVertexArrays(1, &VAO_Point);

五、总结

根据上面的代码,我们是绘制出来了三维的点,但是看起来有不是,黑压压一片就几个点,看起来没有那么直观,后面我们应该让视角动起来。这样就能直观的感觉到三维的点了。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
QtOpenGLQt的一个模块,它提供了在Qt应用程序中进行3D图形渲染的功能。在QtOpenGL中,可以使用OpenGL的API来创建和操作3D图形,包括模型的导入、矩阵变换和简单的视角变换等等。 QtOpenGL提供了一系列的类和函数,用于实现3D游戏开发框架。其中,可以使用QGLWidget类来创建一个OpenGL窗口,用于显示3D场景。可以通过重写QGLWidget的paintGL函数来实现对场景的绘制。可以使用QGLFunctions类来访问OpenGL的函数,进行各种图形操作。可以使用QGLBuffer类来管理顶数据和纹理数据。可以使用QGLShaderProgram类来管理着色器,实现光照效果等。可以使用QMatrix4x4类来进行矩阵变换,实现模型的旋转、平移和缩放等。可以使用QVector3D类来表示三维坐标,进行向量计算等。 除了QtOpenGL,还有其他一些开源的3D游戏开发框架可以使用,如Unity、Unreal Engine和CryEngine等。这些框架提供了更高级的功能和更丰富的资源,适用于开发更复杂的3D游戏。但是,如果你熟悉Qt并且想要在Qt应用程序中集成一些简单的3D图形,那么QtOpenGL是一个不错的选择。<span class="em">1</span> #### 引用[.reference_title] - *1* [qt OpenGL 3d游戏开发框架](https://download.csdn.net/download/kangkanglhb88008/11156007)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值