在這個教程里,我們將在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 }
現在就可以運行程序查看效果了!