第24课:扩展、剪裁和TGA图像文件的手动加载 (参照NeHe)
这次教程中,我们将学会如何读取自己电脑显卡支持的OpenGL扩展,并在我们指定的剪裁区域把它显示出来,如何自己手动来加载TGA图像文件(作为补充内容,因为Qt有方法可以直接加载TGA图像文件)。这次教程有一些难度,但它会让你学会很多东西。
如果你在Windows平台下开发OpenGL程序,那么系统中自带的OpenGL库就是1.1的,如果想使用1.2或者更高版本的OpenGL库,那么只能使用OpenGL扩展。但我们在使用扩展之前,总应该知道我们能用哪些扩展吧?这次教程将交你如何读取自己电脑显卡支持的OpenGL扩展方面的内容并显示出来,如此就知道我们显卡支持哪些扩展了。
同时我们会在显示内容时使用剪裁技术,并且我们将学会如何自己根据TGA文件的格式来加载TGA图像文件。TGA图像文件是一种简单并且支持alpha通道的数字图像文件,它可以使我们更容易地创建酷的效果。
程序运行时效果如下:
下面进入教程:
我们这次将在第01课的基础上修改代码,但是其中不少代码与第21课重复,我会给出具体代码,不过就不再次详细解释了,我们会把解释的重点放在这节课新增的内容上。首先打开myglwidget.j文件,将类声明更改如下:
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QWidget>
#include <QGLWidget>
class MyGLWidget : public QGLWidget
{
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
~MyGLWidget();
protected:
//对3个纯虚函数的重定义
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
void keyPressEvent(QKeyEvent *event); //处理键盘按下事件
private:
GLuint loadTGATexture(QString filename); //加载TGA文件并转为纹理(补充的内容)
void buildFont(); //创建字体
void killFont(); //删除显示列表
//输出字符串
void glPrint(GLuint x, GLuint y, int set, const char *fmt, ...);
private:
bool fullscreen; //是否全屏显示
int m_Scroll; //用来滚动屏幕
int m_Maxtokens; //记录扩展名的个数
int m_Swidth; //剪裁宽度
int m_Sheight; //剪裁高度
GLuint m_Base; //字符显示列表的开始值
QString m_FileName; //图片的路径及文件名
GLuint m_Texture; //储存一个纹理
};
#endif // MYGLWIDGET_H
我们增加了4个整形变量,依次用来记录滚动屏幕的距离,记录OpenGL扩展名的个数,记录我们进行剪裁的宽度、高度。然后m_Base、m_FileName、m_Texture三个变量相信大家已经很熟悉了,不再解释。最后声明4个新函数,loadTGATexture()、buildFont()、killFont()和glPrint(),后三个大家也都很熟悉了,而loadTGATexture()函数是我们自己手动要用来加载TGA图像文件并转换为纹理的函数(这个函数会放在补充部分讲述,前面部分不会用到它)。
接下来,我们需要打开myglwidget.cpp,加上声明#include <QTimer>、#include <QMessageBox>,在构造函数中对新增变量进行修改并设置窗口的固定大小和增加一个定时器,然后修改析构函数,很简单不多解释,具体代码如下:
MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{
fullscreen = false;
setFixedSize(640, 480); //设置固定的窗口大小
m_Scroll = 0;
m_Maxtokens = 0;
m_FileName = "D:/QtOpenGL/QtImage/Font1.tga"; //应根据实际存放图片的路径进行修改
QTimer *timer = new QTimer(this); //创建一个定时器
//将定时器的计时信号与updateGL()绑定
connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
timer->start(10); //以10ms为一个计时周期
}
MyGLWidget::~MyGLWidget()
{
killFont(); //删除显示列表
}
下面,我们先来看下我们3个熟悉的函数buildFont()、killFont()和glPrint(),一些数值上的调整只是为了显示效果更好,不多解释,具体代码如下:<