牛骨文教育服务平台(让学习变的简单)
博文笔记

QT中使用OpenGL(1)——画一个三角形

创建时间:2016-04-10 投稿人: 浏览次数:3729
QOpenGLBuffer
QT提供给我们使用OpenGL缓冲区的辅助类,使用此类由QT负责后端实现
我们可以自由的使用而不用担心效率问题,如果调用了destroy(),缓冲区就变为了无效,
此时就不要在使用缓冲区。


QOpenGLVertexArrayObject
顶点数组对象
典型用法是:对于每个可视化对象
绑定顶点数组
设置顶点状态、属性等
解绑定顶点数组


着色器QOpenGLShaderProgram

A generalized shader pipeline.


vertex.h

#ifndef VERTEX_H
#define VERTEX_H

#include <QVector3D>

class Vertex
{
public:
    // 构造函数
    Q_DECL_CONSTEXPR Vertex();
    Q_DECL_CONSTEXPR explicit Vertex(const QVector3D &position);
    Q_DECL_CONSTEXPR Vertex(const QVector3D &position, const QVector3D &color);

    // 访问器
    Q_DECL_CONSTEXPR const QVector3D& position() const;
    Q_DECL_CONSTEXPR const QVector3D& color() const;
    void setPosition(const QVector3D &position);
    void setColor(const QVector3D &color);

    // OpenGL辅助信息
    static const int PositionTupleSize = 3;
    static const int ColorTupleSize = 3;
    static Q_DECL_CONSTEXPR int positionOffset();
    static Q_DECL_CONSTEXPR int colorOffset();
    static Q_DECL_CONSTEXPR int stride();

private:
    QVector3D m_position;
    QVector3D m_color;
};

// Q_MOVABLE_TYPE意味着对象可以移动拷贝
Q_DECLARE_TYPEINFO(Vertex, Q_MOVABLE_TYPE);

// 构造函数
Q_DECL_CONSTEXPR inline Vertex::Vertex() {}
Q_DECL_CONSTEXPR inline Vertex::Vertex(const QVector3D &position) : m_position(position) {}
Q_DECL_CONSTEXPR inline Vertex::Vertex(const QVector3D &position, const QVector3D &color) : m_position(position), m_color(color) {}

// 访问器
Q_DECL_CONSTEXPR inline const QVector3D& Vertex::position() const { return m_position; }
Q_DECL_CONSTEXPR inline const QVector3D& Vertex::color() const { return m_color; }
void inline Vertex::setPosition(const QVector3D &position) { m_position = position; }
void inline Vertex::setColor(const QVector3D &color) { m_color = color; }

// OpenGL辅助信息
Q_DECL_CONSTEXPR inline int Vertex::positionOffset() { return offsetof(Vertex, m_position); }
Q_DECL_CONSTEXPR inline int Vertex::colorOffset() { return offsetof(Vertex, m_color); }
Q_DECL_CONSTEXPR inline int Vertex::stride() { return sizeof(Vertex); }

#endif // VERTEX_H


window.h

#ifndef WINDOW_H
#define WINDOW_H

#include <QOpenGLWindow>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>

class QOpenGLShaderProgram;

class Window: public QOpenGLWindow,
               protected QOpenGLFunctions
{
    Q_OBJECT

public:
    ~Window();

    void initializeGL();
    void resizeGL(int width, int height);
    void paintGL();
    void teardownGL();

private:
    // OpenGL状态信息
    QOpenGLBuffer m_vertex;
    QOpenGLVertexArrayObject m_object;
    QOpenGLShaderProgram *m_program;

private:
    // 私有辅助函数
    void printContextInformation();
};

#endif


window.cpp

#include "window.h"

#include <QDebug>
#include <QString>
#include <QOpenGLShaderProgram>
#include "vertex.h"

// 创建一个彩色三角形
static const Vertex sg_vertexes[] = {
  Vertex(QVector3D( 0.00f,  0.75f, 1.0f), QVector3D(1.0f, 0.0f, 0.0f)),
  Vertex(QVector3D( 0.75f, -0.75f, 1.0f), QVector3D(0.0f, 1.0f, 0.0f)),
  Vertex(QVector3D(-0.75f, -0.75f, 1.0f), QVector3D(0.0f, 0.0f, 1.0f))
};

Window::~Window()
{
    makeCurrent();
    teardownGL();
}

void Window::initializeGL()
{
    // 初始化 OpenGL 后端
    initializeOpenGLFunctions();
    printContextInformation();

    // 设置全局信息
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    // 应用程序相关初始化
    {
        // 创建Shader(VAO创建之前不要释放)
        m_program = new QOpenGLShaderProgram();
        m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert");
        m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/simple.frag");
        m_program->link();
        m_program->bind();

        // 创建Buffer(VAO创建之前不要释放)
        m_vertex.create();
        m_vertex.bind();
        m_vertex.setUsagePattern(QOpenGLBuffer::StaticDraw);
        m_vertex.allocate(sg_vertexes, sizeof(sg_vertexes));

        // 创建VAO(Vertex Array Object)
        m_object.create();
        m_object.bind();
        m_program->enableAttributeArray(0);
        m_program->enableAttributeArray(1);
        m_program->setAttributeBuffer(0, GL_FLOAT, Vertex::positionOffset(), Vertex::PositionTupleSize, Vertex::stride());
        m_program->setAttributeBuffer(1, GL_FLOAT, Vertex::colorOffset(), Vertex::ColorTupleSize, Vertex::stride());

        // 释放(解绑定)所有对象
        m_object.release();
        m_vertex.release();
        m_program->release();
    }
}

void Window::resizeGL(int width, int height)
{
    // 未做处理
}

void Window::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    // 渲染Shader
    m_program->bind();
    {
        m_object.bind();
        glDrawArrays(GL_TRIANGLES, 0, sizeof(sg_vertexes) / sizeof(sg_vertexes[0]));
        m_object.release();
    }
    m_program->release();
}

// 回收资源
void Window::teardownGL()
{
    m_object.destroy();
    m_vertex.destroy();
    delete m_program;
}

// 打印相关信息,调试用
void Window::printContextInformation()
{
    QString glType;
    QString glVersion;
    QString glProfile;

    // 获取版本信息
    glType = (context()->isOpenGLES()) ? "OpenGL ES" : "OpenGL";
    glVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));

    // 获取 Profile 信息
#define CASE(c) case QSurfaceFormat::c: glProfile = #c; break
    switch (format().profile())
    {
        CASE(NoProfile);
        CASE(CoreProfile);
        CASE(CompatibilityProfile);
    }
#undef CASE

    qDebug() << qPrintable(glType) << qPrintable(glVersion) << "(" << qPrintable(glProfile) << ")";
}

/*
void MyGlWidget::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_F2:
        fullscreen = !fullscreen;
        if (fullscreen)
        {
            showFullScreen();
        }
        else
        {
            showNormal();
            setGeometry(100, 100, 640, 480);
        }
        updateGL();
        break;
    case Qt::Key_Escape:
        close();
    }
}
*/

main.cpp

#include <QApplication>
#include "window.h"

int main(int argc, char *argv[])
{
  QGuiApplication app(argc, argv);

  // 设置 OpenGL 信息
  // 注意:必须在show()之前设置信息
  QSurfaceFormat format;
  format.setRenderableType(QSurfaceFormat::OpenGL);
  format.setProfile(QSurfaceFormat::CoreProfile);
  format.setVersion(3,3);

  Window window;
  window.setFormat(format);
  window.resize(QSize(800, 600));
  window.show();

  return app.exec();
}



声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。