Qt使用OpenGL實現(xiàn)繪制3D圖形
前言
OpenGL是一個跨平臺的、用來渲染3D圖形的標準API,Qt對OpenGL提供了強大的支持。Qt4時代的QtOpenGL模塊在Qt5中已經(jīng)不再建議使用,OpenGL相關(guān)的類被移到了QtGUI模塊。QtWidgets模塊中的QOpenGLWidget類提供了一個可以渲染OpenGL圖形的部件,通過該部件可以輕松地將OpenGL圖形整合到Qt應(yīng)用程序中。
項目效果
一、Qt下使用OpenGL繪制圖形介紹
QOpenGLWidget類是一個用來渲染OpenGL圖形的部件,它提供了在Qt應(yīng)用程序中顯示 OpenGL圖形的功能。這個類使用起來很簡單,只需要繼承該類,然后像使用其他QWidget 部件一樣來使用它即可。QGLWidget 提供了3個方便的虛函數(shù),可以在子類中重新實現(xiàn)它們來執(zhí)行典型的 OpenGL任務(wù):
- initializeGL():設(shè)置 OpenGL資源和狀態(tài),該函數(shù)只在第一次調(diào)用resizeGL()或paintGL()前被調(diào)用一次;
- resizeGL():設(shè)置OpenGL的視口投影等,每次部件改變大小時都會調(diào)用該函數(shù);
- paintGL():渲染OpenGL 場景,每當部件需要更新時都會調(diào)用該函數(shù)。
這里介紹下Qt下一些類的使用和OpenGL中重要的概念或名稱,
QOpenGLShader:用來創(chuàng)建和編譯著色器。著色器是使用 OpenGL著色語言(OpenGL Shading Language,GLSL)編寫的一個小型函數(shù)。繪圖時需要至少指定兩個著色器;頂點著色器(vertexshader)和片段著色器(fragmentshader,也稱為片元著色器)
QOpenGLShaderProgram:用來創(chuàng)建并設(shè)置著色器程序,可以鏈接多個著色器,并在OpenGL當前環(huán)境(current context,也稱為當前上下文)中綁定著色器程序
QAbstractOpenGLFunctions:是一個類族的基類,類族中的類涉及了所有 OpenGL 版本,并為相應(yīng)版本 OpenGL 的所有函數(shù)提供了訪問接口
QOpenGLBuffer:用來創(chuàng)建并管理OpenGL緩存對象
QOpenGLTexture:封裝了一個OpenGL紋理對象,可以使用該類來設(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()); } //為當前環(huán)境初始化OpenGL環(huán)境 initializeOpenGLFunctions(); //開啟深度測試 glEnable(GL_DEPTH_TEST); //下列著色器使用書中代碼運行報錯,進行了修正 //創(chuàng)建頂點著色器 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); //頂點位置 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); //頂點著色 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); //頂點變換 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實現(xiàn)繪制3D圖形的文章就介紹到這了,更多相關(guān)Qt OpenGL繪制3D圖形內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言實現(xiàn)通訊錄的八種功能(添加、刪除、查找、修改、顯示、排序、退出、清空)
本文主要介紹了C語言實現(xiàn)通訊錄的八種功能,主要包括添加、刪除、查找、修改、顯示、排序、退出、清空,感興趣的可以了解一下2023-09-09C++中delete和delete[]的區(qū)別詳細介紹
一直對C++中的delete和delete[]的區(qū)別不甚了解,今天遇到了,上網(wǎng)查了一下,得出了結(jié)論,拿出來和大家分享一下2012-11-11