分享
 
 
 

讲解Delphi下的OpenGL开发入门

王朝delphi·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

OpenGL最初是由Silicon图形公司开发的底层图形库规范。你的系统中准确实现这个规范的部分,通常被称为OpenGL驱动,它允许你使用几何集合(点,线,多边形,图像等等)来描述你希望表现的场景。让肉眼观察起来较为舒适的中等规模场景,通常在毫秒级的速度上实现,这意味着该库文件有足够的能力来支持你创建一个生机勃勃的虚拟世界。

OpenGL驱动一般以二进制库文件的形式提供。它能够动态的连接到你的程序中。在Windows平台上,它将是成为DLL的形式(在你的系统目录下检查opengl.dll)。自从Delphi能够使用任何DLL开始,它对OpenGL 3D编程的能力就像其他任何语言一样容易了。本文将帮助你获得在Delphi中进行OpenGL开发的有效知识。

数学基础

OpenGL拥有强大的数学基础,因此对它功能的限制完全取决于你的想象能力(译者注:没有做不到,只有想不到)。对于理解那些公理和引理,更好的是让我们立刻认识一个简单的3D坐标系统,它是3D编程中惯用的坐标系统。如下:

你应该如何理解你的屏幕(蓝色的方块)在场景中的放置位置呢?发出四条射线并形成屏幕的那个点,是该想象空间中的视点(point of view)。OpenGL让你调用两个简单的函数来定义这个场景

glMatrixMode(GL_PROJECTION);

glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);

在这个调用的过程中的-0.1,0.1,-0.1,0.1定义了这个可视屏幕的左上角和右下角坐标;0.3指定视愕狡聊坏木嗬?就好象“近剪贴板”(near clipping plane))同时25.0指定“远剪贴板”(far clipping plane)。任何近剪贴板前面的物体以及远剪贴板后面的物体都将不可见。当然,你能够任意摆弄这些数字,以使他们适合你需要的场景。

从基本元素(primitive)到对象

现在开始最有意思的部分:对象。OpenGL仅仅支持以下几种基本几何图形:点,线和多边形。没有表面或者更高级的图形(比如球状图形)能被作为基本图形元素绘制。但是它们能够用多边形完美的模仿出来。随意看看现代3D游戏,你会发现它们完全由三角形建立。因此,我们不会被此限制所约束。

对象的绘制非常类似Pascal语言编程。每个块都应该被begin-end包含着,更为确切的说是glBegin()和glEnd()。如同下面的例子:

const S=1.0; D=5.0;

...

glBegin(GL_TRIANGLES);

glVertex3f( -S, 0, D); glVertex3f(S, 0, D); glVertex3f(0, S, D);

glEnd;

这是个简单的三角形。它距离你的视点有5个单位,自身高1个单位,宽2个单位。

这是屏幕截图:

即使它看起来不象3D图形,但它是我们的初始块。在下面你可以看到这个例子的源代码。

在你开始钻研代码前,还有些话要说。每次OpenGL编程,都包含一些初始化输出设备的OS设定(OS-specific)代码。如果你使用Win32,你将需要设置像素格式以及建立显示上下文环境脱离windows设备上下文环境。如果windows系统级编程你并不很在行,你可以把如下的代码作为模版使用。FormCreate中被调用函数的详细信息可以参考帮助文档。

FILE: Tri.pas

unit Tri;

interface

uses

OpenGL, Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, ExtCtrls, ComCtrls;

type

TForm1 = class(TForm)

procedure FormCreate(Sender: TObject);

procedure FormPaint(Sender: TObject);

private

procedure Draw; //Draws an OpenGL scene on request

public

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

procedure setupPixelFormat(DC:HDC);

const

pfd:TPIXELFORMATDESCRIPTOR = (

nSize:sizeof(TPIXELFORMATDESCRIPTOR); // size

nVersion:1; // version

dwFlags:PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or

PFD_DOUBLEBUFFER; // support double-buffering

iPixelType:PFD_TYPE_RGBA; // color type

cColorBits:24; // preferred color depth

cRedBits:0; cRedShift:0; // color bits (ignored)

cGreenBits:0; cGreenShift:0;

cBlueBits:0; cBlueShift:0;

cAlphaBits:0; cAlphaShift:0; // no alpha buffer

cAccumBits: 0;

cAccumRedBits: 0; // no accumulation buffer,

cAccumGreenBits: 0; // accum bits (ignored)

cAccumBlueBits: 0;

cAccumAlphaBits: 0;

cDepthBits:16; // depth buffer

cStencilBits:0; // no stencil buffer

cAuxBuffers:0; // no auxiliary buffers

iLayerType:PFD_MAIN_PLANE; // main layer

bReserved: 0;

dwLayerMask: 0;

dwVisibleMask: 0;

dwDamageMask: 0; // no layer, visible, damage masks

);

var pixelFormat:integer;

begin

pixelFormat := ChoosePixelFormat(DC, @pfd);

if (pixelFormat = 0) then

exit;

if (SetPixelFormat(DC, pixelFormat, @pfd) < TRUE) then

exit;

end;

procedure GLInit;

begin

// set viewing projection

glMatrixMode(GL_PROJECTION);

glFrustum(-0.1, 0.1, -0.1, 0.1, 0.3, 25.0);

// position viewer

glMatrixMode(GL_MODELVIEW);

glEnable(GL_DEPTH_TEST);

end;

procedure TForm1.FormCreate(Sender: TObject);

var DC:HDC;

RC:HGLRC;

i:integer;

begin

DC:=GetDC(Handle); //Actually, you can use any windowed control here

SetupPixelFormat(DC);

RC:=wglCreateContext(DC); //makes OpenGL window out of DC

wglMakeCurrent(DC, RC); //makes OpenGL window active

GLInit; //initialize OpenGL

end;

procedure TForm1.Draw;

const S=1.0; D=5.0;

begin

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glLoadIdentity;

glTranslatef(0.0, 0.0, -12.0);

glBegin(GL_TRIANGLES);

glVertex3f( -S, 0, D); glVertex3f(S, 0, D); glVertex3f(0, S, D);

glEnd;

SwapBuffers(wglGetCurrentDC);

end;

procedure TForm1.FormPaint(Sender: TObject);

begin

Draw;

end;

end.

FILE: Tri.dfm

object Form1: TForm1

BorderStyle = bsDialog

Caption = \'BASIC OpenGL Program\'

ClientHeight = 318

ClientWidth = 373

OnCreate = FormCreate

OnPaint = FormPaint

end

3D历险

好了,让我们开始真正的3D吧。将先前的代码作为框架,我们增加一些画线的代码建立一个带阴影面的四面体。应该如何用基本图形元素来构建呢?我们使用四个三角形。一个在底部,另外三个作为侧面。这里就是生成他们的代码:

procedure TForm1.Draw;

const D=1.5;

H1=D/1.732;

H2=D*1.732-H1; // D/H = tg(30) = 1/sqrt(3)

HY=3.0;

const //vertexes

a1:TGLArrayf3=(-D, 0, -H1); //bootom left

a2:TGLArrayf3=( D, 0, -H1); //bootom right

a3:TGLArrayf3=( 0, 0, H2); //bootom back

a4:TGLArrayf3=( 0, HY, 0); //top

begin

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glLoadIdentity;

glTranslatef(0.0, 0.0, -12.0);

glBegin(GL_TRIANGLES);

glVertex3fv(@a1); glVertex3fv(@a3); glVertex3fv(@a2);

glVertex3fv(@a1); glVertex3fv(@a2); glVertex3fv(@a4);

glVertex3fv(@a2); glVertex3fv(@a3); glVertex3fv(@a4);

glVertex3fv(@a3); glVertex3fv(@a1); glVertex3fv(@a4);

glEnd;

SwapBuffers(wglGetCurrentDC);

end;

虽然看起来有点复杂,不过当你面对下面这张图时,它就很容易理解了。

我们定义顶点a1 ? a4同时依据4个顶点位置建立指定的三角形。当你定义自己的三角形(或者其他的多边形),请使用如下的规则:始终按照逆时针顺序排列定点序号,就像你正在外部观看侧面一样。通过这个规则,我们可以指定指定a1-a2-a4,a1-a3-a2(仰视),a2-a3-a4和a3-a1-a4。

现在就替换Tri.pas中TForm1.Darw()部分,程序运行的效果不会体现出过多的变化。它看起来仍然不象三维图形。这是因为我们还没有设定任何光源。

LIGHTS! CAMERA! OPENGL!

在OpenGL中光源模式有两部分:光源自身(颜色,强度等等)和对象材质。材质,依次包括颜色,一些物理参数(比如不透明性光泽性)以及纹理。深入其中,这会是一个巨大的世界,我们将一步步地接近。

定义一个光源相当容易。

procedure GLInit;

const

light0_positi

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有