不说废话了,让我们看看如何用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程序了! |