正如我们所知,opengl只会提供3D渲染和少量(甚至没有)GUI图形编程的接口。因此创建图形交互界面是我们使用opengl进行编程的第一步。诚如各平台所言,它们都提供了原声的图形交互界面的编程接口,由于众所周知的原因,各个平台提供的接口都是不可移植的,于是我在这里选择了Qt这个图形编程库,使得我的opengl应用真正地成为一个可移植的应用程式。
首先我会假设你已经知道了一些关于Qt编程的基本知识,这包括pro文件(qmake的配置文件)的编写。
本文所采用的Qt库的版本是Qt5.1.0,是从2013-03-29的git上checkout下来的,并且使用了vs2012进行了静态编译。opengl是Qt内置的。
基于某些个人编程的偏好原因,我并没有使用vs2012 IDE或者qt creator完成这个本文这个demo的编写。我使用一个叫sublime text2的编辑器进行编码(它的包扩展和对齐线使我非常喜欢它),在桌面上建立了一个bat的批处理脚本
Qt510VS11.bat
SET PATH=%PATH%;X:\Qt\Qt5\Qt510\StaticVS11x86\bin;X:\Qt\toolChain;C:\cygwin\bin;C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x86;
x:
title="Qt 5.1.0 Static VS11 x86"
%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" x86
cmd
这个路径:X:\Qt\toolChain,是我个人在团队内发起的一个基于Qt的跨平台基础库,诸君可不必理会。
另外,由于VS2012对xp平台的支持问题,我另外建立了一个bat文件在X:\Qt\toolChain目录下
v110_xpPlatformToolset.bat
set INCLUDE=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Include;%INCLUDE%
set PATH=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Bin;%PATH%
set LIB=%ProgramFiles(x86)%\Microsoft SDKs\Windows\7.1A\Lib;%LIB%
set CL=/D_USING_V110_SDK71_;%CL%
//set LINK=/SUBSYSTEM:WINDOWS,5.01
这个脚本的最后一行有问题,我把它破坏掉了。。。。
执行这个脚本后,在pro文件内给链接器添加/SUBSYSTEM:WINDOWS,5.01的选项,即可让编译出来的应用程序可在xp下执行。
这个demo包括以下文件,helloOpenGL.pro,main.cpp,MainWidget.h,MainWidget.cpp
文件层次如下:
|--helloOpenGL
|helloOpenGL.pro
|main.cpp
|--gui
|MainWidget.h
|MainWidget.cpp
文件内容如下:
helloOpenGL.pro--------------------
QT += gui opengl
TEMPLATE = app
TARGET = helloOpenGL
INCLUDEPATH += X:\\Qt\\toolChain
DEPENDPATH += X:\\Qt\\toolChain\\fdb
#linux/unix gcc compliler
contains(QMAKE_CXX,g++) {
message(g++ compiler)
Debug {
DESTDIR = GCCDebug
OBJECTS_DIR = $$DESTDIR\\.obj
MOC_DIR = $$DESTDIR\\.moc
RCC_DIR = $$DESTDIR\\.rcc
UI_DIR = $$DESTDIR\\.ui
}
Release {
DESTDIR = GCCRlease
OBJECTS_DIR = $$DESTDIR\\.obj
MOC_DIR = $$DESTDIR\\.moc
RCC_DIR = $$DESTDIR\\.rcc
UI_DIR = $$DESTDIR\\.ui
}
QMAKE_CXXFLAGS += -std=c++0x
CONFIG += -static #for linux static link
QMAKE_RPATHDIR += ./libs
}
#win32 cl compiler
contains(QMAKE_CXX,cl) { #微软的编译器,同时也说明了这是Windows
message(cl compiler)
Debug {
DESTDIR = Win32Debug
OBJECTS_DIR = $$DESTDIR\\.obj
MOC_DIR = $$DESTDIR\\.moc
RCC_DIR = $$DESTDIR\\.rcc
UI_DIR = $$DESTDIR\\.ui
}
Release {
DESTDIR = Win32Rlease
OBJECTS_DIR = $$DESTDIR\\.obj
MOC_DIR = $$DESTDIR\\.moc
RCC_DIR = $$DESTDIR\\.rcc
UI_DIR = $$DESTDIR\\.ui
}
QMAKE_LFLAGS += /MANIFESTUAC:\"level=\'requireAdministrator\' uiAccess=\'false\'\" /SUBSYSTEM:WINDOWS,5.01
QMAKE_POST_LINK += mt -manifest '$$DESTDIR\\$$TARGET'.exe.embed.manifest -outputresource:$$BINARY_PATH
}
#macox clang compiler
PLATFORM=$$system(uname -s)
#set macx-clang flags
contains(PLATFORM,Darwin) {
contains(QMAKE_CXX,clang++) {
message(Darwin + clang++ - set:QMAKE_CXXFLAGS += -std=c++0x -stdlib=c++ -mmacosx-version-min=10.7)
Debug {
DESTDIR = DarwinDebug
OBJECTS_DIR = $$DESTDIR\\.obj
MOC_DIR = $$DESTDIR\\.moc
RCC_DIR = $$DESTDIR\\.rcc
UI_DIR = $$DESTDIR\\.ui
}
Release {
DESTDIR = DarwinRlease
OBJECTS_DIR = $$DESTDIR\\.obj
MOC_DIR = $$DESTDIR\\.moc
RCC_DIR = $$DESTDIR\\.rcc
UI_DIR = $$DESTDIR\\.ui
}
QMAKE_CXXFLAGS += -std=c++0x -stdlib=libc++ -mmacosx-version-min=10.7
}
}
# Input
SOURCES += main.cpp
#gui
HEADERS += gui/MainWidget.h
SOURCES += gui/MainWidget.cpp
#//gui
main.cpp-------------------
//qt library
#include <QApplication>
//user
#include "gui/MainWidget.h"
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
CMainWidget* pMainWidget = new CMainWidget();
pMainWidget->show();
return (app.exec());
}
MainWidget.h---------------------------
#include <QGLWidget>
class CMainWidget : public QGLWidget {
Q_OBJECT
private:
public:
CMainWidget();
~CMainWidget();
protected:
void initializeGL();
void paintGL();
void resizeGL(int iWidth,int iHeight);
};
MainWidget.cpp---------------------------
#include "MainWidget.h"
CMainWidget::CMainWidget() {
this->setGeometry(50,50,320,240);
this->setWindowTitle(QString("Hello OpenGL"));
}
CMainWidget::~CMainWidget() {
}
void CMainWidget::initializeGL() {
glClearColor(0.0,0.0,0.0,0.0);
}
void CMainWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
}
void CMainWidget::resizeGL(int iWidth,int iHeight) {
}
这就是一个最小规模的使用Qt+OpenGL编写的demo了
打开前面的Qt510VS11.bat,到这个工程的根目录
执行
qmake helloOpenGL.pro
jom /j 8 (这是我放在toolChain下的一个nmake的替代品,它可以提供并行编译,如果你没有的话可以简单的执行nmake)
没有报错的话你就可以在Win32Debug目录下看到一个helloOpenGL.exe的应用程式了
如果你想发布
jom -f Makefile.Release /j 8(或者nmake -f Makefile.Release)
就可以。
后记:有人可能说了,听说Qt效率不怎么高,能应付3D渲染这种高效率的活吗?是的,Qt在GUI上的效率和原生GUI的效率确实没得比,但除非你以光速在UI上面进行操作,这个时候Qt的基于信号-槽的机制可能就捉襟见肘了,其余的时候还是应付得过来的,我使用Qt编程两年了,还没碰到过UI线程是因为纯粹的操作导致的响应不过来,多半时候是因为程序员在UI的线程上干逻辑层的活。另外基于Qt编写的UI动画也能非常流畅地运行,这些是在我所部署的四种平台上得到的验证(windows,linux,mac,andriod)。再说到前面的问题,3D渲染实际上在这里是由opengl完成的,跟qt没多大关系。qt带来的不是效率的提升,而是灵活性和部署效率的提升。