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);

五、总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值