Qt OpenGL 創建一個OpenGL窗口


在這個教程里,我們將在Qt Creator環境中創建OpenGL對象,它將顯示一個空的OpenGL窗口,可以在窗口和全屏模式下切換,按ESC退出,它將是我們后面應用程序的基礎框架。
Qt中寫OpenGL與在VC上還是有不少差別的,對Qt機制不熟悉的朋友,請先大致了解下Qt的機制,再往下看教程。
程序運行時效果如下:
下面進入教程:
新建空的Qt項目,項目名稱為myOpenGL,然后往項目中添加新的C++類,類名為MyGLWidget,基類為QGLWidget,類型信息選擇“繼承自QWidget”。添加完成后,打開項目文件myOpenGL.pro,將代碼補全如下:
 1 TARGET = myOpenGL  2 TEMPLATE = app  3  
 4 HEADERS += \  5  myglwidget.h  6  
 7 SOURCES += \  8  main.cpp \  9  myglwidget.cpp 10  
11 QT       += core gui 12  
13 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 14  
15 QT       += opengl

然后保存該文件。下面打開myglwidget.h文件,將類聲明補全如下:

 1 #ifndef MYGLWIDGET_H  2 #define MYGLWIDGET_H
 3  
 4 #include <QWidget>
 5 #include <QGLWidget>
 6  
 7 class MyGLWidget : public QGLWidget  8 {  9  Q_OBJECT 10 public: 11     explicit MyGLWidget(QWidget *parent = 0); 12     ~MyGLWidget(); 13     
14 protected: 15     //對3個純虛函數的重定義
16     void initializeGL(); 17     void resizeGL(int w, int h); 18     void paintGL(); 19     
20     void keyPressEvent(QKeyEvent *event);           //處理鍵盤按下事件
21     
22 private: 23     bool fullscreen;                                //是否全屏顯示
24 }; 25  
26 #endif // MYGLWIDGET_H

再到myglwidget.cpp文件中先包含#include<GL/glu.h>,#include<QKeyEvent>頭文件,然后添加類中函數的定義:

 1 MyGLWidget::MyGLWidget(QWidget *parent) :  2  QGLWidget(parent)  3 {  4     fullscreen = false;  5 }  6  
 7 MyGLWidget::~MyGLWidget()  8 {  9     
10 }
構造函數中只需對fullscreen初始化,析構函數暫時並不需要做什么。
下面是initializeGL()的定義:
 1 void MyGLWidget::initializeGL()                         //此處開始對OpenGL進行所以設置
 2 {  3     glClearColor(0.0, 0.0, 0.0, 0.0);                   //黑色背景
 4     glShadeModel(GL_SMOOTH);                            //啟用陰影平滑
 5     
 6     glClearDepth(1.0);                                  //設置深度緩存
 7     glEnable(GL_DEPTH_TEST);                            //啟用深度測試
 8     glDepthFunc(GL_LEQUAL);                             //所作深度測試的類型
 9     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //告訴系統對透視進行修正
10 }
glClearColor()函數用來設置清除屏幕時使用的顏色,4個參數分別用來設置紅、綠、藍顏色分量和Alpha值,它們的取值范圍都是0.0~1.0,這里4個參數都為0.0,表示純黑色。然后設置了陰影平滑,這樣可以使色彩和光照更加精細。
接下來的三行必須做的是關於depth buffer(深度緩存)的。將深度緩存設想為屏幕后面的層。深度緩存不斷地對物體進入屏幕內部有多深進行跟蹤。我們本節的程序其實沒有真正的使用深度緩存,但幾乎所有在屏幕上顯示3D場景OpenGL程序都使用深度緩存。它的排序決定那個物體先畫。這樣就不會將一個圓形后面的正方形畫到圓形前面來。深度緩存是OpenGL十分重要的部分。最后我們希望進行最好的透視修正。這會十分輕微的影響性能,但使得透視圖看起來好一點。
下面是resizeGL()的定義:
 1 void MyGLWidget::resizeGL(int w, int h)                 //重置OpenGL窗口的大小
 2 {  3     glViewport(0, 0, (GLint)w, (GLint)h);               //重置當前的視口
 4     glMatrixMode(GL_PROJECTION);                        //選擇投影矩陣
 5     glLoadIdentity();                                   //重置投影矩陣  6     //設置視口的大小
 7     gluPerspective(45.0, (GLfloat)w/(GLfloat)h, 0.1, 100.0);  8     glMatrixMode(GL_MODELVIEW);                         //選擇模型觀察矩陣
 9     glLoadIdentity();                                   //重置模型觀察矩陣
10 }
glViewport()函數用來設置視口的大小。使用glMatrixMode()設置了投影矩陣,投影矩陣用來為場景增加透視,后面使用了glLoadIdentity()重置投影矩陣,這樣可以將投影矩陣恢復到初始狀態。gluPerspective()用來設置透視投影矩陣,這里設置視角為45°,縱橫比為窗口的縱橫比,最近的位置為0.1,最遠的位置為100,這兩個值是場景中所能繪制的深度的臨界值。可以想象,離我們眼睛比較近的東西看起來比較大,而比較遠的東西看起來就比較小。最后設置並重置了模型視圖矩陣。
下面是paintGL()的定義:
1 void MyGLWidget::paintGL()                              //從這里開始進行所以的繪制
2 { 3     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度緩存
4     glLoadIdentity();                                   //重置當前的模型觀察矩陣
5 }
paintGL()函數包含了所以的繪圖代碼,任何想在屏幕上顯示的東西都將在此段代碼中出現。以后每個教程中都會在這個函數增加代碼,已達到繪圖目的。
最后是鍵盤事件處理函數KeyPressEvent()的定義,由於這與OpenGL關系不大,不做過多解釋:
 1 void MyGLWidget::keyPressEvent(QKeyEvent *event)  2 {  3     switch (event->key())  4  {  5     //F1為全屏和普通屏的切換鍵
 6     case Qt::Key_F1:  7         fullscreen = !fullscreen;  8         if (fullscreen)  9  { 10  showFullScreen(); 11  } 12         else
13  { 14  showNormal(); 15  } 16  updateGL(); 17         break; 18     //ESC為退出鍵
19     case Qt::Key_Escape: 20  close(); 21  } 22 }

最后再向項目中添加main.cpp文件,更改內容如下:

 1 #include <QApplication>
 2 #include "myglwidget.h"
 3  
 4 int main(int argc, char *argv[])  5 {  6  QApplication app(argc, argv);  7     
 8  MyGLWidget w;  9     w.resize(400, 300); 10  w.show(); 11     
12     return app.exec(); 13 }

現在就可以運行程序查看效果了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM