X众期待的下篇终于来了。

不说废话了,让我们看看如何用Delphi编写OpenGL吧。
以前也有人写过Delphi如何编写OpenGL,不过都是根据OpenGL教科书将编程语言翻译成了Delphi而已,并没有体现出Delphi的方便高效。我的教学会让你见识到Delphi编写OpenGL的方便和高效的。
为了实现我的说法,你需要一个函数库。这是外国朋友写的,主要是为了方便Delphi编写OpenGL程序。以后你不用再使用Delphi自带的糟糕的Opengl函数库了。函数库叫 DOT,你可以去 delphi3d.net下载。或者下载本贴的附件。我修改了代码,增加了对累积缓存(Accumulations buffers)的支持。大家按需选择吧。
我讲讲如何使用吧。首先把下载得到的压缩包里所有的文件解压到某个目录里,比如 D:/DOT。然后,运行Delphi,选择Tools菜单下的Options,在Options里选择Library,然后点击Library path旁边的 ... 在打开的对话框里还是点击 ... 接着选择刚才解压的目录(如D:/DOT)然后点击确定,再点Add,这样你刚才的解压目录就加到了库搜索路径里。你还要在Browsing path里增加你的解压目录,过程和Library path一样,我就不重复了。
不过,上述设置以后,你还无法在你的程序里调用DOT函数库。你还需要在程序的 uses 里增加至少四个项目,如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DotWindow, GL, GLu, GLext;
最后四个就是你要增加的项目了。
现在,准备工作一切就绪,我们可以进入OpenGL的世界了!
首先,有几个窗体属性需要设置。在窗体设计窗口,单击选择窗体,然后在Object Inspector面板里,找到BorderIcons项,展开,把除了biSystemMenu以外的项都改成False。再找到BorderStyle,把值改成bsSingle。再把Height改成480,Width改成640。好了,窗体设置到此结束,可以写代码了。
新项目的代码如下,我们一步步让它画出一个可以由用户控制的正方形吧。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
首先是uses里增加DotWindow, GL, GLu, GLext,变成
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DotWindow, GL, GLu, GLext;
然后给窗体添加几个事件,增加几个变量和函数,最终代码如下
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DotWindow, GL, GLu, GLext;
type
TForm1 = class(TDotForm) //注意这里,要把原来的TForm改成现在的TDotForm
procedure FormPaint(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
bFullScreen : Bool; //决定是否用全屏显示
rX, rY : GLuint; //旋转角度
procedure DrawScene;
procedure LoadExtensions;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
程序首先创建窗体,产生OnCreate事件,这时调用FormCreate过程。在这个过程里,初始化OpenGL的一些参数
procedure TForm1.FormCreate(Sender: TObject);
begin
bFullScreen := False;
rX := 360;
rY := 360;
if bFullScreen then
begin
dotSetDisplayMode(800, 600, 32, 60);
Self.BorderStyle := bsNone;
Self.Height := 600;
Self.Width := 800;
Self.WindowState := wsMaximized;
Self.Context.DC := GetDC(Self.Handle);
ShowCursor(False);
end;
Self.Context.QuickPF(32, 0, 24, 0, 0);
Self.Context.InitGL;
LoadExtensions;
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 0);
glMatrixMode(GL_PROJECTION);
gluPerspective(60.0, Self.ClientWidth / Self.ClientHeight, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
end;
书上能找到的内容我就不讲了,我只讲DOT特有的函数
dotSetDisplayMode
要用到四个参数,前两个设置屏幕的分辨率(比如640,480;1024,768),第三个设置颜色深度(8,16,32 还是选择32吧,省得麻烦),最后一个设置屏幕刷新率(60最保险)
Self.Context.QuickPF
用于设置像素格式的。函数默认设置了双缓存,共有五个参数(原版是四个)。分别设置 色彩缓存位数,透明缓存位数,深度缓存位数,模版缓存位数以及 累积缓存位数。
Self.Context.InitGL
利用刚才设置的像素格式,生成OpenGL的Context(还是不要乱翻译的好 );
注意:Self. 可以不用写,我写出来是为了防止混乱。
LoadExtensions
用于调用OpenGL的扩展功能。函数定义如下
procedure TForm1.LoadExtensions;
procedure Load(const ext: String);
begin
if not glext_LoadExtension(ext) then
raise Exception.Create('This demo requires ' + ext + '!');
end;
begin
{*****************************************************************************
Load all required OpenGL extensions here, and throw an exception if any of
them are not found.
****************************************************************************}
Load('GL_ARB_multitexture');
Load('GL_EXT_texture_filter_anisotropic');
end;
OpenGL的初始化完成了。
窗体显示任何东西,都会产生OnPaint事件,所以在FormPaint过程里添加OpenGL的绘图函数
procedure TForm1.FormPaint(Sender: TObject);
begin
DrawScene;
end;
DrawScene 函数定义如下
procedure TForm1.DrawScene;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glTranslatef(0, 0, -3);
glRotatef(rX, 1, 0, 0);
glRotatef(rY, 0, 1, 0);
glBegin(GL_QUADS);
glColor3f(1, 0, 0);
glVertex3f(-0.5,-0.5, 0.5);
glVertex3f(0.5,-0.5, 0.5);
glVertex3f(0.5, 0.5, 0.5);
glVertex3f(-0.5, 0.5, 0.5);
///
glColor3f(0, 1, 0);
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(-0.5, 0.5,-0.5);
glVertex3f(0.5, 0.5,-0.5);
glVertex3f(0.5,-0.5,-0.5);
//
glColor3f(0, 0, 1);
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(-0.5,-0.5, 0.5);
glVertex3f(-0.5, 0.5, 0.5);
glVertex3f(-0.5, 0.5,-0.5);
//
glColor3f(1, 1, 0);
glVertex3f(0.5,-0.5,-0.5);
glVertex3f(0.5, 0.5,-0.5);
glVertex3f(0.5, 0.5, 0.5);
glVertex3f(0.5,-0.5, 0.5);
/
glColor3f(1, 0, 1);
glVertex3f(-0.5, 0.5,-0.5);
glVertex3f(-0.5, 0.5, 0.5);
glVertex3f(0.5, 0.5, 0.5);
glVertex3f(0.5, 0.5,-0.5);
glColor3f(1, 1, 1);
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(0.5,-0.5,-0.5);
glVertex3f(0.5,-0.5, 0.5);
glVertex3f(-0.5,-0.5, 0.5);
glEnd;
Self.Context.PageFlip;
end;
对了,别忘了在程序关闭时,会产生OnClose事件,所以要在FormClose过程里加一个函数调用
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
dotSetDisplayMode(0, 0, 0, 0);
end;
如果使用了全屏显示,调用dotSetDisplayMode(0, 0, 0, 0)可以恢复原来的屏幕设置。窗口模式调用此函数没有任何不良影响。
现在运行程序就能看见一个正方形了。但是还不能控制。这时就要用到FormKeyDown过程了。
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_UP:
begin
if rX = 0 then
rX := 360;
Dec(rX);
DrawScene;
end;
VK_DOWN:
begin
if rX = 720 then
rX := 360;
Inc(rX);
DrawScene;
end;
VK_LEFT:
begin
if rY = 0 then
rY := 360;
Dec(rY);
DrawScene;
end;
VK_RIGHT:
begin
if rY = 720 then
rY := 360;
Inc(rY);
DrawScene;
end;
VK_ESCAPE:
Close;
end;
end;
现在运行程序,就可以用键盘上的方向键控制正方体旋转了,而且只要按键盘的Esc键就能退出程序了。
怎么样,简单吗?
什么,不简单?!你按照OpenGL教材上的方法,或者用C/C++编写我这个程序以后再发表意见吧。
DOT让我们摆脱了繁琐的OpenGL初始化设置(当然不只如此,DOT更方便的功能需要你更深入的学习OpenGL才能体会到)。
Delphi让我们不用为创建、修改窗体,响应键盘消息等等基本Windows编程而费神。
两者的结合让我们可以轻松编写OpenGL程序了!
教学写完了,有不明白的地方,请发帖。我会加到教学里的。
或者联系我
QQ:245343050
本主题包含附件:
sf_20061020195543.rar (216671bytes)