Qt实现OpenGL的经典教程⑥——坐标系统

本帖将参考LearnOpenGL这一经典教程,使用Qt的原生环境完成教程中所提的所有流程,并尽量和原教程保持一致,如有错误,欢迎评论!

为了方便大家参考,我将项目分享至了gitee,并实时进行更行:Qt实现OpenGL的经典教程: (gitee.com)

教程中文网站:LearnOpenGLCN 

教程原网站:LearnOpenGL

Qt版本:6.7

操作系统:Windows10

进入3D

为了真正地进入3D空间,我们分别实现projection ,view ,model矩阵,其中model负责将模型转换为世界坐标,view则是摄像机变换,projection则是透视变换。我们对上一篇博文结尾的顶点着色器做进一步修改:

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
	TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

这里分别左乘了model,view和projection三个矩阵,这一顺序不能变,因为矩阵的乘法没有交换律。

随后,我们对PaintGL中的代码进行修改:

void MyOpenGLWidget::paintGL()
{
    //由于继承了QOpenGLFunctions,可以直接使用OpenGL中的函数
    // render
    // ------
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // bind Texture
    glActiveTexture(GL_TEXTURE0);
    _texture->bind();
    glActiveTexture(GL_TEXTURE1);
    _texture1->bind();

    QMatrix4x4 model;
    QMatrix4x4 view;
    QMatrix4x4 projection;
    model.rotate(-55.0f, 1.0f, 0.0f, 0.0f);
    view.translate(QVector3D(0.0f, 0.0f, -3.0f));
    projection.perspective(45.0f,
                           float(this->width())/float(this->height()),
                           0.1f,
                           100.0f);


    // update shader uniform
    _shaderProgram->bind();
    _shaderProgram->setUniformValue("model", model);
    _shaderProgram->setUniformValue("view", view);
    _shaderProgram->setUniformValue("projection", projection);

    // render the triangle
    _vao->bind();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

我们分别创建model,view和projection的单位矩阵,然后让模型沿着x轴旋转-55°,将摄像机移动到z轴上-3的位置,并设置变换视角为透视视角,fov为45°,并将这三个矩阵分别赋值给顶点着色器中设置的uniform,点击运行:

为了提高效率,你也可以 将projection的赋值工作放到初始化阶段。

更加3D

我们开始用这个箱子面来画一个真正的立方体了!首先我们加载更多的顶点(36个顶点):

 float vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };

然后,我们修改PaintGL的绘制方式:

void MyOpenGLWidget::paintGL()
{
    //由于继承了QOpenGLFunctions,可以直接使用OpenGL中的函数
    // render
    // ------
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // bind Texture
    glActiveTexture(GL_TEXTURE0);
    _texture->bind();
    glActiveTexture(GL_TEXTURE1);
    _texture1->bind();

    QMatrix4x4 model;
    QMatrix4x4 view;
    QMatrix4x4 projection;
    model.rotate(qRadiansToDegrees(QTime::currentTime().msecsSinceStartOfDay()/1000.0f),
                 0.5f,
                 1.0f,
                 0.0f);
    view.translate(QVector3D(0.0f, 0.0f, -3.0f));
    projection.perspective(45.0f,
                           float(this->width())/float(this->height()),
                           0.1f,
                           100.0f);


    // update shader uniform
    _shaderProgram->bind();
    _shaderProgram->setUniformValue("model", model);
    _shaderProgram->setUniformValue("view", view);
    _shaderProgram->setUniformValue("projection", projection);

    // render the triangle
    _vao->bind();
    glDrawArrays(GL_TRIANGLES, 0, 36);
}

我们让正方体随时间旋转,同时修改绘制方式画36个点,点击运行,我们得到了一个奇怪的旋转正方体:

这是因为没有开启深度测试,我们开启深度测试:

glEnable(GL_DEPTH_TEST);

并在PaintGL中清除深度缓冲:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

再次点击运行,变一切正常了!

更多的立方体

为了创建更多的立方体,我们在MyOpenGLWidget类声明中定义更多的位置信息:

private:
    QOpenGLShaderProgram *_shaderProgram;
    QOpenGLTexture *_texture;
    QOpenGLTexture *_texture1;
    QOpenGLVertexArrayObject *_vao;
    QOpenGLBuffer *_vbo;
    QOpenGLBuffer *_ebo;

    QList<QVector3D> _cubePositions = {
        QVector3D( 0.0f,  0.0f,  0.0f),
        QVector3D( 2.0f,  5.0f, -15.0f),
        QVector3D(-1.5f, -2.2f, -2.5f),
        QVector3D(-3.8f, -2.0f, -12.3f),
        QVector3D( 2.4f, -0.4f, -3.5f),
        QVector3D(-1.7f,  3.0f, -7.5f),
        QVector3D( 1.3f, -2.0f, -2.5f),
        QVector3D( 1.5f,  2.0f, -2.5f),
        QVector3D( 1.5f,  0.2f, -1.5f),
        QVector3D(-1.3f,  1.0f, -1.5f)
    };

我们添加了一个_cubePositions来指示立方体位置,在渲染阶段我们修改model矩阵来在每一次调用中创建十个立方体:

void MyOpenGLWidget::paintGL()
{
    //由于继承了QOpenGLFunctions,可以直接使用OpenGL中的函数
    // render
    // ------
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清除颜色和深度缓冲

    // bind Texture
    glActiveTexture(GL_TEXTURE0);
    _texture->bind();
    glActiveTexture(GL_TEXTURE1);
    _texture1->bind();

    QMatrix4x4 model;
    QMatrix4x4 view;
    QMatrix4x4 projection;

    view.translate(QVector3D(0.0f, 0.0f, -3.0f));
    projection.perspective(45.0f,
                           float(this->width())/float(this->height()),
                           0.1f,
                           100.0f);


    // update shader uniform
    _shaderProgram->bind();
    _shaderProgram->setUniformValue("view", view);
    _shaderProgram->setUniformValue("projection", projection);

    // render the triangle
    _vao->bind();
    for(int i = 0; i < _cubePositions.size(); ++i){

        model = QMatrix4x4();
        model.translate(_cubePositions[i]);
        model.rotate(20.0f * i, 1.0f, 0.3f, 0.5f);
        _shaderProgram->setUniformValue("model", model);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
}

点击运行,我就得到了和LearnOpenGL中一样的结果了!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值