欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Qt使用OpenGL實(shí)現(xiàn)繪制3D圖形

 更新時(shí)間:2023年10月23日 09:08:20   作者:電氣徐小江  
OpenGL是一個(gè)跨平臺(tái)的、用來(lái)渲染3D圖形的標(biāo)準(zhǔn)API,Qt對(duì)OpenGL提供了強(qiáng)大的支持,所以本文就來(lái)和大家介紹一下Qt如何使用OpenGL實(shí)現(xiàn)繪制3D圖形吧

前言

OpenGL是一個(gè)跨平臺(tái)的、用來(lái)渲染3D圖形的標(biāo)準(zhǔn)API,Qt對(duì)OpenGL提供了強(qiáng)大的支持。Qt4時(shí)代的QtOpenGL模塊在Qt5中已經(jīng)不再建議使用,OpenGL相關(guān)的類(lèi)被移到了QtGUI模塊。QtWidgets模塊中的QOpenGLWidget類(lèi)提供了一個(gè)可以渲染OpenGL圖形的部件,通過(guò)該部件可以輕松地將OpenGL圖形整合到Qt應(yīng)用程序中。

項(xiàng)目效果

一、Qt下使用OpenGL繪制圖形介紹

QOpenGLWidget類(lèi)是一個(gè)用來(lái)渲染OpenGL圖形的部件,它提供了在Qt應(yīng)用程序中顯示 OpenGL圖形的功能。這個(gè)類(lèi)使用起來(lái)很簡(jiǎn)單,只需要繼承該類(lèi),然后像使用其他QWidget 部件一樣來(lái)使用它即可。QGLWidget 提供了3個(gè)方便的虛函數(shù),可以在子類(lèi)中重新實(shí)現(xiàn)它們來(lái)執(zhí)行典型的 OpenGL任務(wù):

  • initializeGL():設(shè)置 OpenGL資源和狀態(tài),該函數(shù)只在第一次調(diào)用resizeGL()或paintGL()前被調(diào)用一次;
  • resizeGL():設(shè)置OpenGL的視口投影等,每次部件改變大小時(shí)都會(huì)調(diào)用該函數(shù);
  • paintGL():渲染OpenGL 場(chǎng)景,每當(dāng)部件需要更新時(shí)都會(huì)調(diào)用該函數(shù)。

這里介紹下Qt下一些類(lèi)的使用和OpenGL中重要的概念或名稱(chēng),

QOpenGLShader:用來(lái)創(chuàng)建和編譯著色器。著色器是使用 OpenGL著色語(yǔ)言(OpenGL Shading Language,GLSL)編寫(xiě)的一個(gè)小型函數(shù)。繪圖時(shí)需要至少指定兩個(gè)著色器;頂點(diǎn)著色器(vertexshader)和片段著色器(fragmentshader,也稱(chēng)為片元著色器)

QOpenGLShaderProgram:用來(lái)創(chuàng)建并設(shè)置著色器程序,可以鏈接多個(gè)著色器,并在OpenGL當(dāng)前環(huán)境(current context,也稱(chēng)為當(dāng)前上下文)中綁定著色器程序

QAbstractOpenGLFunctions:是一個(gè)類(lèi)族的基類(lèi),類(lèi)族中的類(lèi)涉及了所有 OpenGL 版本,并為相應(yīng)版本 OpenGL 的所有函數(shù)提供了訪(fǎng)問(wèn)接口

QOpenGLBuffer:用來(lái)創(chuàng)建并管理OpenGL緩存對(duì)象

QOpenGLTexture:封裝了一個(gè)OpenGL紋理對(duì)象,可以使用該類(lèi)來(lái)設(shè)置紋理

二、示例完整代碼

1.MyOpenGL.pro

QT += widgets

HEADERS += \
    myopenglwidget.h

SOURCES += \
    main.cpp \
    myopenglwidget.cpp

2.myopenglwidget.h

#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QOpenGLShaderProgram>
#include <QKeyEvent>

class QOpenGLTexture;
class QOpenGLShaderProgram;
class MyOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

public:
    explicit MyOpenGLWidget(QWidget *parent = 0);

protected:
    void initializeGL();
    void paintGL();
    void resizeGL(int width,int height);

    void keyPressEvent(QKeyEvent *event);

private:
    QOpenGLShaderProgram *program;
    QOpenGLBuffer vbo;
    QOpenGLTexture *textures[2];
    GLfloat translate,xRot,yRot,zRot;
};

#endif // MYOPENGLWIDGET_H

3.myopenglwidget.cpp

#include "myopenglwidget.h"

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    //初始化變量
    translate = -6.0;
    xRot = zRot = 0.0;
    yRot = -30.0;
}

void MyOpenGLWidget::initializeGL()
{
    //初始化紋理變量
    for(int i=0;i<2;i++)
    {
          textures[i] = new QOpenGLTexture(QImage(QString("../MyOpenGL/side%1.jpg").arg(i+1)).mirrored());
    }

    //為當(dāng)前環(huán)境初始化OpenGL環(huán)境
    initializeOpenGLFunctions();

    //開(kāi)啟深度測(cè)試
    glEnable(GL_DEPTH_TEST);

    //下列著色器使用書(shū)中代碼運(yùn)行報(bào)錯(cuò),進(jìn)行了修正
    //創(chuàng)建頂點(diǎn)著色器
    QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex,this);
    const char *vsrc = "#version 330\n"
                       "in vec4 vPosition;\n"
                       "in vec2 vTexCoord;\n"
                       "out vec2 texCoord;\n"
                       "uniform mat4 matrix;\n"
                       "void main()\n"
                       "{\n"
                       "    texCoord = vTexCoord;\n"
                       "    gl_Position = matrix * vPosition;\n"
                       "}\n";
    vshader->compileSourceCode(vsrc);

    //創(chuàng)建片段著色器
    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment,this);
    const char *fsrc = "#version 330\n"
                       "uniform sampler2D tex;\n"
                       "in vec2 texCoord;\n"
                       "out vec4 fColor;\n"
                       "void main()\n"
                       "{\n"
                       "    fColor = texture(tex,texCoord);\n"
                       "}\n";
    fshader->compileSourceCode(fsrc);

    //創(chuàng)建著色器程序
    program = new QOpenGLShaderProgram;
    program->addShader(vshader);
    program->addShader(fshader);
    program->link();
    program->bind();
}

void MyOpenGLWidget::paintGL()
{
    //設(shè)置視口為正方形
    int w = width();
    int h = height();
    int side = qMin(w,h);
    glViewport((w-side)/2,(h-side)/2,side,side);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //頂點(diǎn)位置
    GLfloat vertices[2][4][3] =
    {
        {{-0.8f,0.8f,0.8f},{-0.8f,-0.8f,0.8f},{0.8f,-0.8f,0.8f},{0.8f,0.8f,0.8f}},
        {{0.8f,0.8f,0.8f},{0.8f,-0.8f,0.8f},{0.8f,-0.8f,-0.8f},{0.8f,0.8f,-0.8f}}
    };

    //添加緩存
    vbo.create();
    vbo.bind();
    vbo.allocate(vertices,48*sizeof(GLfloat));
    GLuint vPosition = program->attributeLocation("vPosition");
    //glVertexAttribPointer(vPosition,2,GL_FLOAT,GL_FALSE,0,vertices);
    program->setAttributeBuffer(vPosition,GL_FLOAT,0,3,0);
    glEnableVertexAttribArray(vPosition);

    //頂點(diǎn)著色
    GLfloat coords[2][4][2] =
    {
        {{0.0f,1.0f},{0.0f,0.0f},{1.0f,0.0f},{1.0f,1.0f}},
        {{0.0f,1.0f},{0.0f,0.0f},{1.0f,0.0f},{1.0f,1.0f}}
    };
    vbo.write(24*sizeof(GLfloat),coords,16*sizeof(GLfloat));
    GLuint vTexCoord = program->attributeLocation("vTexCoord");
    program->setAttributeBuffer(vTexCoord,GL_FLOAT,24*sizeof(GLfloat),2,0);
    glEnableVertexAttribArray(vTexCoord);
    program->setUniformValue("tex",0);

    //頂點(diǎn)變換
    QMatrix4x4 matrix;
    matrix.perspective(45.0f,(GLfloat)w/(GLfloat)h,0.1f,100.0f);
    matrix.translate(0,0,translate);
    matrix.rotate(xRot,1.0,0.0,0.0);
    matrix.rotate(yRot,0.0,1.0,0.0);
    matrix.rotate(zRot,0.0,0.0,1.0);
    program->setUniformValue("matrix",matrix);

    //繪制函數(shù)
    for(int i=0;i<2;i++)
    {
        textures[i]->bind();
        glDrawArrays(GL_TRIANGLE_FAN,i*4,4);
    }
}

void MyOpenGLWidget::resizeGL(int,int)
{

}

//按鍵事件
void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{
    switch(event->key())
    {
    case Qt::Key_Up:
        xRot -= 10;
        break;
    case Qt::Key_Down:
        xRot += 10;
        break;
    case Qt::Key_Left:
        yRot -= 10;
        break;
    case Qt::Key_Right:
        yRot += 10;
        break;
    case Qt::Key_PageUp:
        zRot -= 10;
        break;
    case Qt::Key_PageDown:
        zRot += 10;
        break;
    case Qt::Key_Space:
        translate += 1;
        break;
    case Qt::Key_Alt:
        translate -= 1;
        break;
    default:
        break;
    }
    update();
    QOpenGLWidget::keyPressEvent(event);
}

4.main.cpp

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

int main(int argc,char *argv[])
{
    QApplication app(argc,argv);
    MyOpenGLWidget w;
    w.resize(400,300);
    w.show();
    return app.exec();
}

到此這篇關(guān)于Qt使用OpenGL實(shí)現(xiàn)繪制3D圖形的文章就介紹到這了,更多相關(guān)Qt OpenGL繪制3D圖形內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • OJ中G++和C++的區(qū)別

    OJ中G++和C++的區(qū)別

    今天小編就為大家分享一篇關(guān)于OJ中G++和C++的區(qū)別,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • C語(yǔ)言實(shí)現(xiàn)通訊錄的八種功能(添加、刪除、查找、修改、顯示、排序、退出、清空)

    C語(yǔ)言實(shí)現(xiàn)通訊錄的八種功能(添加、刪除、查找、修改、顯示、排序、退出、清空)

    本文主要介紹了C語(yǔ)言實(shí)現(xiàn)通訊錄的八種功能,主要包括添加、刪除、查找、修改、顯示、排序、退出、清空,感興趣的可以了解一下
    2023-09-09
  • C語(yǔ)言運(yùn)算符的重載詳解

    C語(yǔ)言運(yùn)算符的重載詳解

    這篇文章主要為大家詳細(xì)介紹C語(yǔ)言運(yùn)算符的重載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • 解決了個(gè)困擾了2天的問(wèn)題,定點(diǎn)運(yùn)算問(wèn)題

    解決了個(gè)困擾了2天的問(wèn)題,定點(diǎn)運(yùn)算問(wèn)題

    本文主要講解定點(diǎn)運(yùn)算問(wèn)題,需要的朋友可以參考一下。
    2016-06-06
  • C++11各種鎖的具體使用

    C++11各種鎖的具體使用

    本文主要介紹了C++11各種鎖的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • c語(yǔ)言小游戲程序之彈跳小球的實(shí)現(xiàn)代碼

    c語(yǔ)言小游戲程序之彈跳小球的實(shí)現(xiàn)代碼

    這篇文章主要介紹了c語(yǔ)言小游戲程序之彈跳小球的實(shí)現(xiàn)代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • C++中delete和delete[]的區(qū)別詳細(xì)介紹

    C++中delete和delete[]的區(qū)別詳細(xì)介紹

    一直對(duì)C++中的delete和delete[]的區(qū)別不甚了解,今天遇到了,上網(wǎng)查了一下,得出了結(jié)論,拿出來(lái)和大家分享一下
    2012-11-11
  • C++中的explicit關(guān)鍵字實(shí)例淺析

    C++中的explicit關(guān)鍵字實(shí)例淺析

    在C++程序中很少有人去使用explicit關(guān)鍵字,不可否認(rèn),在平時(shí)的實(shí)踐中確實(shí)很少能用的上,再說(shuō)C++的功能強(qiáng)大,往往一個(gè)問(wèn)題可以利用好幾種C++特性去解決。接下來(lái)給大家介紹 C++中的explicit關(guān)鍵字,需要的朋友可以參考下
    2017-03-03
  • C++分析講解類(lèi)的靜態(tài)成員變量是什么

    C++分析講解類(lèi)的靜態(tài)成員變量是什么

    在C++中,靜態(tài)成員是屬于整個(gè)類(lèi)的而不是某個(gè)對(duì)象,靜態(tài)成員變量只存儲(chǔ)一份供所有對(duì)象共用。所以在所有對(duì)象中都可以共享它。使用靜態(tài)成員變量實(shí)現(xiàn)多個(gè)對(duì)象之間的數(shù)據(jù)共享不會(huì)破壞隱藏的原則,保證了安全性還可以節(jié)省內(nèi)存
    2022-04-04
  • C語(yǔ)言實(shí)現(xiàn)單鏈表的示例詳解

    C語(yǔ)言實(shí)現(xiàn)單鏈表的示例詳解

    給需要考研的同學(xué)一個(gè)參考,單鏈表作為常見(jiàn)數(shù)據(jù)結(jié)構(gòu)的一種,這里記錄C語(yǔ)言實(shí)現(xiàn)單鏈表,文章通過(guò)代碼示例介紹的非常詳細(xì),具有一頂?shù)膮⒖純r(jià)值,需要的朋友可以參考下
    2023-09-09

最新評(píng)論