1. 程式人生 > >QT中使用OpenGL(1)——畫一個三角形

QT中使用OpenGL(1)——畫一個三角形

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



相關推薦

QT使用OpenGL1——一個三角形

QOpenGLBuffer QT提供給我們使用OpenGL緩衝區的輔助類,使用此類由QT負責後端實現 我們可以自由的使用而不用擔心效率問題,如果呼叫了destroy(),緩衝區就變為了無效, 此時就不要在使用緩衝區。 QOpenGLVertexArrayObject 頂點陣

小白入門opengl三角形

在opengl中任何事物都在3D空間中,而螢幕與視窗確實2D的,由3D座標轉化為2D的處理過程是opengl的圖形渲染管線管理的。可以被劃分為兩個主要部分,第一部分把你的3D座標轉化為2D座標,第二部分則是把2D座標轉化為有顏色的畫素。 在圖形渲染管線上執行各自

Qt繪圖學習1

int() 繪圖 自動 程序 時機 如果 被調用的時機 被調用 學習 paintEvent()被調用的時機;1.當窗口第一次被show()的時候,Qt程序會自動產生一個繪圖事件,調用繪圖事件;2.重新調整窗口部件大小的時候,系統也會產生一個繪制事件。3.當窗口部件被其他窗口

Qt學習筆記1 — 深入瞭解Hello World的建立過程

年初的時候就準備學習Qt了,因為工作原因被擱淺好久,現在開始學也不晚,以後每週更新2遍博文作為總結。 學過Windows開發的,會覺得Qt很親切,學起來不是很費勁(PS: 環境搭建比較簡單,本文不作說明),但是還得從Hello World開始一步步來。下面,筆者將用4種不同的方

QT入門系列1 QT Creator下載與安裝 Helloworld

                        一、下載與安裝

給出n個學生的考試成績表,每條記錄由學號、姓名和分數和名次組成,設計演算法完成下列操作: 1設計一個顯示對學生資訊操作的選單函式如下所示: *************************

給出n個學生的考試成績表,每條記錄由學號、姓名和分數和名次組成,設計演算法完成下列操作: (1)設計一個顯示對學生資訊操作的選單函式如下所示: *************************        1、錄

python程式1獲取一個網頁的所有中文字元

所有的中文字元都是在html的各種標籤之中,因此我們需要拿到html的整個檔案。為此我們匯入requests庫,再者,我們需要去除標籤將全部內容進行文字化,此處是中英文都有的文字,為此我們引入beautifulsoup,因為get_text方法使得我們可以獲取所

Spring Boot學習實踐1建立一個簡單的spring boot應用

一、使用idea建立一個簡單的Spring Boot應用程式 環境準備: idea:2018.2 jdk: 1.8 spring boot:是2.0版本以上的 以上環境可以根據實際情況去調整。 (1)首先找到idea建立應用的New Project,選擇好

一個簡單的銀行、賬戶演示程式。 (1)定義一個賬戶類,包含使用者名稱、密碼、餘額等屬性、存錢、取錢等方法。 2定義一個銀行類,包含銀行名、賬戶列表等屬性,開賬戶、查賬戶的功能。賬戶列表可以使用集

做一個簡單的銀行、賬戶演示程式。 (1)定義一個賬戶類,包含使用者名稱、密碼、餘額等屬性、存錢、取錢等方法。 (2)定義一個銀行類,包含銀行名、賬戶列表等屬性,開賬戶、查賬戶的功能。賬戶列表可以使用

Tensorflow:Android呼叫Tensorflow Mobile版本API1-訓練一個網路

在這裡,我們訓練一個網路來擬合 y=x^2+1 程式碼如下: # y = x^2 + 1 import tensorflow as tf import numpy as np import r

Qt-學習筆記1:vs2015使用qt靜態庫5.7

一、QT靜態庫 可以自己編譯,也可以下載別人編譯好的,這裡是下載地址(QT靜態庫) 二、安裝Qt5Package 在vs2015的“擴充套件和更新”中尋找《Qt5Package》這個擴充套件,然後安裝,並重啟 開啟擴充套件QT5,配置QT靜態庫中的bin目錄,然後Re

QT入門系列1QT Creator下載與安裝 Helloworld

一、下載與安裝 1.1 下載 從QT官網下載,下載頁:https://www.qt.io/download-open-source/,要先註冊登入帳號才可以下載。點選Offline Installers(離線安裝包),選擇合適系統,我這裡是windows

【Cocos2D-X 】初窺門徑1 製作一個動態的精靈

原理: Cocos2D中有個導演控制整個遊戲流程,導演將場景新增到螢幕上,場景中有各種各樣的演員。 先通過顯示一張圖片來看看Cocos2D遊戲的流程: AppDelegate.cpp bool AppDelegate::applicationDidFinishLaunch

iOS應用開發入門1——第一個iOS應用

最近因為工作的原因,需要學習iOS應用開發。 本人現在在公司負責的是智慧裝置聯網模組,所謂的智慧裝置聯網,就是讓一些智慧裝置(多半是沒用螢幕的裝置)連上wifi,因為沒有螢幕,所以無法像手機和平板那樣通過螢幕選擇wifi和輸入wifi密碼,這個時候就需要手機來輔助,將手機上

iOS菜鳥成長筆記1——第一個iOS應用

前言:陽光小強最近抽時間學習iOS開發,在學習過程中發現了很多有趣的東西也遇到了很多問題,為了在學習過程中能和大家交流,記錄下學習的心得和學習成果,所以就有了這一個系列文章,希望這一系列文章能形成一個系統性的東西,讓和我一樣剛步入iOS開發的朋友少走彎路,用最少的時間獲得最大

java學習1一個java小程式執行解釋

上一篇文章簡單運行了一個java的小程式,其中有兩個命令一個是javac另一個是java。簡單解釋一下這兩個命令的作用,如有不正確的地方請大家多多指教。 javac是java的編譯命令,通過javac編譯原始檔後會生成**.class檔案,這是一種與平臺無關的

iOS 面試題1一個 Objective-C 物件的記憶體結構是怎樣的?

接下來分享的將會是唐老師一系列的iOS面試題,因為之前好幾期唐老師都刪掉了,說是要出書,所以轉載過來,需要的朋友們可以看下,也方便我自己鞏固、學習。 轉載自:http://mp.weixin.qq.com/s?__biz=MjM5NTIyNTUyMQ==&mid=

webpack3實戰1打包一個CDN引入的jQuery專案

前注: 如果可以,請給本專案加【Star】和【Fork】持續關注。 有疑義請點選這裡,發【Issues】。 1、需求列表 1、在html檔案裡,通過CDN引入了jQuery; 2、步驟 安裝依賴 npm install html檔案中引入

QT學習心得1--初學者

目前學習QT,我想實現按一個按鈕,調出檔案的對話方塊,選中檔名,供我進一步操作。可以在該按鈕對應的Slot函式中加入以下語句: QString s=QFileDialog::getOpenFileName("/anni123/project","AnyFile(*.*)",t

mysql 自定義函式1建立一個簡單函式

1、先建立一個無參的自定義函式: -- 如果有這個函式,就刪除 drop function if exists hello; -- 建立一個無參的函式 create function hello (