分享
 
 
 

DELPHI中OPENGL程序设计

王朝delphi·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

OPENGL图形程序设计

OPENGL是一个三维图形和模型库,由于它在三维图形方面的杰出性能,目前许多高级语言都提供了与OPENGL的接口,如:VC、DELPHI、C++Builder等。使用OPENGL可以极大地减少用户开发图形、图像的难度,使用户制作高水准的商业广告、图形CAD、三维动画、图形仿真和影视采集。

一、OPENGL的功能

OPENGL原来是工作站上的一个图形软件库,由于它在商业、军事、医学、航天航空等领域的广泛应用,目前在低档电脑也可以开发出符合用户要求的图形。OPENGL不仅可以绘制基本图像,而且提供了大量处理图形图像的函数与过程。

1、图形变换

是图形显示与制作的基础,动画设计和动画显示都离不开图形的变换,图形变换在数学上是由矩形的乘法来实现的,变换一般包括平移、旋转和缩放。按图形的显示性质来分:视点变换、模型变换、投影变换、剪裁变换和视口变换等。

2、光照效果

不发光的物体的颜色是由物体反射外界光所形成的,这是光照。在三维图形中,如果光照使用不当,三维图形就会失去真实的立体感,OPENGL把光照分为:辐射光、环境光、散射光、反射光等。

3、纹理映射

通过纹理映射可以在三维表面添加显示现实世界中的纹理。如:一个矩形它不能表示真实世界中的物体,如果填上"本质"纹理,就逼真了。

4、图形特效

混合函数、反走样函数和雾函数,可以处理三维图形听之任之物体的透明和半透明、使用线段理加光滑以及提供雾化的效果。

5、图像特效

处理位图的基本函数:图像绘制、图像拷贝和存储、映射和转移、图像的缩放等。位图操作函数可以人绘图原的低层说明中文字符的形成过程。

二、创建OPENGL应用程序

1、一般原则

A 有uses中添加OPENGL支持单元:OpenGL;

B 在窗体的OnCreate事件过程中初始化OPENGL;

C 在窗口的OnPaing 事件过程中初始化OPENGL;

D 在窗口的OnResize事件过程中初始化OPENGL;

E 在窗口的OnDestroy 事件过程中初始化 OPENGL;

2、简单实例

A 创建一个工程FILE->New Application

B 在OnCreate事件中添加代码:

procedure TfrmMain.FormCreate(Sender: TObject);

var

pfd:TPixelFormatDescriptor; //设置描述表

PixelFormat:Integer;

begin

ControlStyle:=ControlStyle+[csOpaque];

FillChar(pfd,sizeof(pfd),0);

with pfd do

begin

nSize:=sizeof(TPixelFormatDescriptor);

nVersion:=1;

dwFlags:=PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;

iPixelType:=PFD_TYPE_RGBA;

cColorBits:=24;

cDepthBits:=32;

iLayerType:=PFD_MAIN_PLANE;

end;

PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);

SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);

hrc:=wglCreateContext(Canvas.Handle);

w:=ClientWidth;

h:=ClientHeight;

end;

C 在OnDestroy事件中的代码

procedure TfrmMain.FormDestroy(Sender: TObject);

begin

wglDeleteContext(hrc);

end;

D 在OnPaint事件中的代码

procedure TfrmMain.FormPaint(Sender: TObject);

begin

wglMakeCurrent(Canvas.Handle,hrc);

glClearColor(1,1,1,1);

glColor3f(1,0,0);

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

MyDraw;

glFlush;

SwapBuffers(Canvas.Handle);

end;

E 在OnResize事件中的代码

procedure TfrmMain.FormResize(Sender: TObject);

begin

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);

glViewPort(0,0,ClientWidth,ClientHeight);

MyDraw;

end;

F 在MyDraw函数中的代码(用户在窗口类中声明)

procedure TfrmMain.MyDraw;

begin

glPushMatrix;

Sphere:=gluNewQuadric;

gluQuadricDrawStyle(Sphere,GLU_LINE);

gluSphere(Sphere,0.5,25,25);

glPopMatrix;

SwapBuffers(Canvas.handle);

gluDeleteQuadric(Sphere);

end;

附本程序原码:

unit MainFrm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, OpenGL;

type

TfrmMain = class(TForm)

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormPaint(Sender: TObject);

procedure FormResize(Sender: TObject);

private

{ Private declarations }

hrc:HGLRC;

w,h:glFloat;

Sphere:GLUquadricObj;

public

{ Public declarations }

procedure MyDraw;

end;

var

frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);

var

pfd:TPixelFormatDescriptor;

PixelFormat:Integer;

begin

ControlStyle:=ControlStyle+[csOpaque];

FillChar(pfd,sizeof(pfd),0);

with pfd do

begin

nSize:=sizeof(TPixelFormatDescriptor);

nVersion:=1;

dwFlags:=PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;

iPixelType:=PFD_TYPE_RGBA;

cColorBits:=24;

cDepthBits:=32;

iLayerType:=PFD_MAIN_PLANE;

end;

PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);

SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);

hrc:=wglCreateContext(Canvas.Handle);

w:=ClientWidth;

h:=ClientHeight;

end;

procedure TfrmMain.FormDestroy(Sender: TObject);

begin

wglDeleteContext(hrc);

end;

procedure TfrmMain.FormPaint(Sender: TObject);

begin

wglMakeCurrent(Canvas.Handle,hrc);

glClearColor(1,1,1,1);

glColor3f(1,0,0);

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

MyDraw;

glFlush;

SwapBuffers(Canvas.Handle);

end;

procedure TfrmMain.MyDraw;

begin

glPushMatrix;

Sphere:=gluNewQuadric;

gluQuadricDrawStyle(Sphere,GLU_LINE);

gluSphere(Sphere,0.5,25,25);

glPopMatrix;

SwapBuffers(Canvas.handle);

gluDeleteQuadric(Sphere);

end;

procedure TfrmMain.FormResize(Sender: TObject);

begin

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);

glViewPort(0,0,ClientWidth,ClientHeight);

MyDraw;

end;

end.

三、OPENGL变量和函数的约定

1、OPENGL的库约定

它共三个库:基本库、实用库、辅助库。在DELPHI中,基本库由OpenGL单元实现,在Windows环境中,一般不使用辅助库。

2、OPENGL常数约定

OPENGL常数均使用大写字母,以"GL"开头,词汇之间使用下划线分隔,如:GL_LINES,表示使用基本库绘制直线。

3、OPENGL函数的命名约定

A 第一部分以gl或wgl开头,如glColor3f中的gl。

B 第二部分是用英文表示的函数功能,单词的首字母大写出。

C 第三部分是数字,表示函数的参数。

D 第四部分是小写字母,表示函数的类型。

b 9位整数

s 16位整数

i 32位整数

f 32位浮点数

d 64位浮点数

ub 9位无符号整数

例:glVertex2f(37,40); {两个32位的浮点数作参数}

glVertex3d(37,40,5); {三个64位的浮点数作参数}

p[1..3]:array of glFloat;

glVertes3fv(p); {3f表示三个浮点数,v表示调用一个数组作为顶点坐标输入}

四、OPENGL的初始化

1、PIXELFORMATDESCRIPTOR结构

主要描述像素点的性质,如像素的颜色模式和红、绿、蓝颜色构成方式等。

tagPIXELFORMATDESCRIPTOR = packed record

nSize: Word;

nVersion: Word;

dwFlags: DWORD;

iPixelType: Byte;

cColorBits: Byte;

cRedBits: Byte;

cRedShift: Byte;

cGreenBits: Byte;

cGreenShift: Byte;

cBlueBits: Byte;

cBlueShift: Byte;

cAlphaBits: Byte;

cAlphaShift: Byte;

cAccumBits: Byte;

cAccumRedBits: Byte;

cAccumGreenBits: Byte;

cAccumBlueBits: Byte;

cAccumAlphaBits: Byte;

cDepthBits: Byte;

cStencilBits: Byte;

cAuxBuffers: Byte;

iLayerType: Byte;

bReserved: Byte;

dwLayerMask: DWORD;

dwVisibleMask: DWORD;

dwDamageMask: DWORD;

end;

TPixelFormatDescriptor = tagPIXELFORMATDESCRIPTOR;

dwFlags代表点格式的属性:

PFD_DRAW_TO_WINDOW 图形绘在屏幕或设备表面

PFD_DRAW_TO_BITMAP 在内存中绘制位图

PFD_SUPPORT_GDI 支持GDI绘图

PFD_SUPPORT_OPENGL 支持OPENGL函数

PFD_DOUBLEBUFFER 使用双缓存

PFD_STEREO 立体缓存

PFD_NEED_PALLETTE 使用RGBA调色板

PFD_GENERIC_FORMAT 选择GDI支持的格式绘图

PFD_NEED_SYSTEM_PALETTE 使用OPENGL支持的硬件调色板

iPixelType设置像素颜色模式:PFD_TYPE_RGBA或PFD_TYPE_INDEX.。

cColorBits设置颜色的位,如是9表示有256种颜色表示点的颜色。

cRedBits、cGreenBits、cBlueBits 使用RGBA时,三原色所使用的位数。

cRedShitfs、cGreenShifts、cBlueShifts 使用RGBA时,三原色可以调节的位数。

cAlphaBits、cAlphaShifts 使用RGBA时,Alpha使用的位数与可调节的位数。

cAccumBits设置累积缓存区的位面总数。

cAccumRedBits、cAccumGreenBits、cAccumBlueBits设置累积缓存区的三原色位面总数。

cAccumAlphaBits设置累积缓存区的Alpha位面总数。

cDepthBits设置浓度缓存的深度。

cStencilBits设置Stencil缓存的深度。

cAuxBuffers指辅助缓存的大小。

iLayerType指定层的类型。

bReserved不使用,必须是零。

dwLayerMask指定覆盖层的屏蔽。

dwDamageMask设置在相同的框架缓存下是否共用同一种像素模式。

2、OPENGL的初始化步骤

A 使用Canvas.Handle获得窗口句柄。

B 创建一个TPixelFormatDescriptor变量定义像素格式。

C 使用ChoosePixelFormat函数选择像素格式。

D 使用SetPixelFormat函数使用像素格式生效。

E 使用wglCreateContext函数建立翻译描述表。

F 使用wglMakeCurrent函数把建立的翻译描述表作为当前翻译描述表。

3、资源释放

A 使用wglDeleteContext过程删除像素描述表。

B 使用ReleaseDC过程释放窗口内存。

在窗口的OnDestroy事件中:

begin

if hrc<>null then

wglDeleteCurrent(hrc);

if hdc<>null then

ReleaseDC(Handle,hdc);

end;

五、OPENGL基本图形的绘制

1、图形的颜色

注意底色的设置,颜色设置通常与像素描述变量有关,即与TPixelFormatDescriptor定义中的iPixelType成员有关。

iPixelType:=PFD_TYPE_COLORINDEX;

则只能使用glIndexd,glIndexf,glIndexi,glIndexs,glIndexv,glIndexfv,glIndexiv,glIndexsv过程设置图形颜色。

iPixelType:=PFD_TYPE_RGBA;

则只能使用 glColor3b,glColor3f,glColor4b,glColor4f,glColor4fv设置图形颜色。

A 图形底色:屏幕与窗口的颜色,即颜色缓冲区的颜色。改变图形底色首先应使用glClearColor过程设定底色,然后使用glClear过程以这种底色刷新窗口和屏幕。

procedure glClearColor(red:GLClampf,green:GLClampf,blue:GLClampf,alpha:GLClampf);

procedure glClear(mask:GLBitField);

red,green,blue,alpha是准备设置的底色,它们的取值是0到1。mask是刷新底色的方式。

例:将绘声绘色图窗口设置为绿色

glClearColor(0,1,0,1);

glClear(GL_COLOR_BUFFER_BIT);

mask的取值和意义:

GL_COLOR_BUFFER_BIT 设置当前的颜色缓冲

GL_DEPTH_BUFFER_BIT 设置当前的深度缓冲

GL_ACCUM_BUFFER_BIT 设置当前的积累缓冲

GL_STENCIL_BUFFER_BIT 设置当前的STENCIL(模板)缓冲

绘图窗口设置为灰色

glClearColor(0.3,0.3,0.3,1);

glClear(GL_COLOR_BUFFER_BIT);

B 图形颜色

使用glClear3f与glClear4f可以设置图形的绘制颜色。若用三个参数,则分别指设置红、蓝、绿三色光。若用四个参数,则第四个表示RGBA值。

例设置当前的绘图颜色为蓝色:

glColor3f(0,0,1);

设置绘图颜色为白色:

glColor3f(1,1,1);

2、简单图形的绘制

在glBegin与glEnd过程之间绘制简单图形,如点、线、多边形等。

glBegin(mode:GLenum);{绘制过程}glEnd;

mode的取值:

GL_POINTS 画多个点

GL_LINES 画多条线,每两点绘制一条直线

GL_LINE_STRIP 绘制折线

GL_LINE_LOOP 绘制首尾相接的封闭多边形

GL_TRIANGLES 绘制三角形

GL_TRIANGLE_STRIP 绘制三边形,每三个点绘制绘制一个三边形

GL_TRIANGLE_FAN 绘制三角形

GL_QUADS 绘制四边形

GL_QUAD_STRIP 绘制四边条,每四点绘制一个四边条

GL_POLYGON 绘制多边形

例绘制三个点:

begin

glPushMatrix;

glBegin(GL_POINT);

glVertex2f(0.1,0.1);

glVertex2f(0.5,0.5);

glVertex2f(0.1,0.3);

glEnd;

SwapBuffers(Canvas.Handle);

end;

如果将GL_POINT改为GL_LINES,则将画一条线.第三个点无效.在glVertex2f之前执行glColor3f(0,0,1)则将线条的颜色改为绿色. 如果将GL_LINES改为GL_LINE_STRIP则可以绘制两条直线.

使用glPointSize过程可以设置点的大小;使用glLineWidth过程可以设置线的宽度.

使用glLineStipple过程设置点划线的样板,使用glEnable(GL_LINE_STIPPLE)过程和对应参数使绘图能够绘制点划线.glDisable(GL_LINE_STIPPLE)过程和对应参数关闭点划线.

procedure glLineStipple(factor:GLint,pattern:GLushort);

参数factor表示点划线样板Pattern的重复次数,factor取值1255,Pattern是二进制序列.

glLineStipple(1,0,0x11C);{0x11C表示为10001110,0表示不画点,1表示画点}

例: begin

glColor3f(1,0,0);

glLineWidth(2);

glLineStipple(1,$11C);

glEnable(GL_LINE_STIPPLE);

glBegin(GL_LINES);

glVertex2f(-0.9,0.3);

glVertex2f(0.9,0.3);

glEnd;

glDisable(GL_LINE_STIPPLE);

glColor3f(1,0,1);

glLineStipple(2,$11C);

glEnable(GL_LINE_STIPPLE);

glBegin(GL_LINES);

glVertex2f(-0.9,0.1);

glVertex2f(0.9,0.1);

glEnd;

glDisable(GL_LINE_STIPPLE);

SwapBuffers(Canvas.Handle);

end;

多边形绘制与点线相似,要改变参数为GL_POLYGON,GL_QUADS,GL_TRANGLES.在绘制时的注意事项:

A 多边形的边与边只在顶点相交

B 多边形必须是凸多边形,如果是凹多边形,用户只有折成凸多边形,加快绘制速度.

例: glBegin(GL_POLYGON);

glVertex2f(-0.9,0.3);

glVertex2f(0.9,0.3);

glVertex2f(0.9,-0.6);

glVertex2f(0.5,-0.6);

glVertex2f(-0.9,-0.2);

glEnd;

多边形有正面与反面,与之相关的过程:

glPolygonMode 控制多边形正,反面绘图模式

glFrontface 指定多边形的正面

glCullFace 显示多边形是设置消除面

glPolygonStripple 形成多边形填充的样式

3、简单二次曲面

圆柱,圆环和球都属于二次曲面.

A 圆柱

gluCylinder(qobj:GLUquadricObj,baseRadius:GLdouble,topRadius:GLdouble,height:GLdouble,

slices:GLint,stacks:GLint);

qobj指定一个二次曲面,baseRadius为圆柱的底半径;topRadius为所绘制圆柱的上顶面半径;height为圆柱的高;slices为绕Z轴的分割线数;stacks为沿Z轴的分割线数.

如果baseRadius和topRadius不相等,则可以绘制锥台与圆锥.

procedure TfrmMain.MyDraw;

var

qObj:GLUQuadricObj;

begin

glPushMatrix;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glColor3f(1,0,0);

qObj:=gluNewQuadric;

gluQuadricDrawStyle(qObj,GLU_LINE);

gluCylinder(qObj,0.5,0.1,0.2,10,10);

end;

B 圆环

gluDisk(qobj:GLUquadricObj,innerRadius:GLdouble,outerRadius:GLdouble,slices:GLint,

loops:GLint);

procedure TfrmMain.MyDraw;

var

qObj:GLUQuadricObj;

begin

glPushMatrix;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glColor3f(1,0,0);

qObj:=gluNewQuadric;

gluQuadricDrawStyle(qObj,GLU_LINE);

gluDisk(qObj,0.2,0.5,10,5);

SwapBuffers(Canvas.Handle);

end;

C 半圆环

gluPartialDisk(qobj:GLUquadricObj,innerRadius:GLdouble,outerRadius:GLdouble,slices:GLint,

loops:GLint,startAngle:GLdouble,sweepAngle:GLdouble);

startAngle,sweepAngle是半圆环的起始角与终止角.

procedure TfrmMain.MyDraw;

var

qObj:GLUQuadricObj;

begin

glPushMatrix;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glColor3f(1,0,0);

qObj:=gluNewQuadric;

gluQuadricDrawStyle(qObj,GLU_LINE);

gluPartialDisk(qObj,0.2,0.5,10,5,90,190);

SwapBuffers(Canvas.Handle);

end;

D 球体

function gluSphere(qObj:GLUquadricObj,radius:GLdouble,slices:GLint,stacks:GLint);

procedure TfrmMain.MyDraw;

var

qObj:GLUQuadricObj;

begin

glPushMatrix;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glColor3f(1,0,0);

qObj:=gluNewQuadric;

gluQuadricDrawStyle(qObj,GLU_LINE);

{ silhouette[ silu(:)5et ]n.侧面影象, 轮廓}

gluSphere(qObj,0.5,20,20);

SwapBuffers(Canvas.Handle);

end;

E 关于二次曲面的过程

gluNewQuadric 创建一个新的二次曲面对象

gluDeleteQuadric 删除一个二次曲面对象

gluQuadricDrawStyle 指定要绘制的二次曲面类型

gluQuadricNormal 设置二次曲面的法矢量

gluQuadricOrientation 设置二次曲面是内旋还是外旋转

gluQuadricTexture 设置二次曲面是否使用纹理

F 绘制二次曲面的一般步骤

首先定义一个GLUquadricObj对象;

其次创建一个曲面对象gluNewQuadric;

再次设置二次曲面的特性(gluQuadricDrawStyle, gluQuadricTexture)

绘制二次曲面(gluCylinder,gluSphere,gluDisk, gluPartialDisk)

六、OPENGL中的变换

变换是动画设计的基础,包括图形的平移,旋转,缩放等操作,在数学上是通过矩阵来实现的。

1 glLoadIdentity过程

能够把当前矩阵变为单位矩阵。

2 glLoadMatrix过程

能够把指定的矩阵设为当前矩阵。

procedure glLoadmatrixd(m:GLdouble);

procedure glLoadmatrixf(m:GLfloat);

m表示4X4矩阵,下面的代码定义并使之成为当前矩阵

M:array[1..4,1..4] of GLfloat;

glLoadMatrix(@M);

3 glMultMatrix过程

能够将当前矩与指定矩阵相乘,并把结果作为当前矩.

procedure glMultMatrixd(M:GLdouble);

procedure glMultMatrixf(M:GLfloat);

4 glPushMatrix和glPopmatrix

glPushMatrix能够把当前矩压入矩阵堆栈, glPopMatrix能够把当前矩弹出矩阵堆栈.

glPushMatrix能够记忆矩阵当前位置,glPopmatrix能够返回以前所在的位置.

注:glPushMatrix与glPopMatrix必须放在glBegin与glEnd之外.

5 投影变换

A glOrtho能够创建一个正投影矩阵,把当前矩乘以该正投影矩阵,其结果作为当前矩阵.

function glOrtho(left:GLdouble,right:GLdouble,bottom:GLdouble,top:GLdouble,

near:GLdouble,far:GLdouble);

procedure TfrmMain.FormResize(Sender: TObject);

var

nRange:GLfloat;

begin

nRange:=50.0;

w:=clientWidth;

h:=clientHeight;

if h=0 then

h:=1;

glViewPort(0,0,w,h);

if w<=h then

glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,

-nRange,nRange)

else

glOrtho(-nRange*h/w,nRange*h/w,-nRange,nRange,

-nRange,nRange);

repaint;

end;

B glOrtho2D只定义正投影视景体前,后,左,右.

procedure glOrtho(left:GLdouble,right:GLdouble,bottom:GLdouble,top:GLdouble);

C glMatrixMode过程

能够设置当前操作矩阵的类型

procedure glMatrixMode(mode:GLenum);

mode的取值:

GL_MODELVIEW 指定以后的矩阵操作为模型矩阵堆栈

GL_PROJECTION 指定以后的矩阵操作为投影矩阵堆栈

GL_TEXTURE 指定以后的矩阵操作为纹理矩阵堆栈

D glFrustum过程

创建一个透视斜投影矩阵,并把当前矩阵乘以该斜投影矩阵,其结果为当前矩阵.

procedure glFrustum(left:GLdouble,right:GLdouble,bottom:GLdouble,top:GLdouble,

next:GLdouble,far:GLdouble);

这些参数定义了斜投影的左,右,上,下,前,后剪裁面.

E gluPerspective过程

能够定义一个以Z轴为中线的四棱台视景体.

procedure gluPerspetive(fovy:GLdouble,aspect:GLdouble,zNear:GLdouble,zFar:GLdouble);

fovy定义了xoz平面的视角,aspect定义了x和y方向上的比例,zNear和zFar分别定义了视点到剪裁面和后剪裁面的距离.

procedure TfrmMain.FormResize(Sender: TObject);

var

aspect:GLfloat;

begin

w:=ClientWidth;

h:=ClientHeight;

if h=0 then

h:=1;

glViewPort(0,0,clientWidth,Clientheight);

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

aspect:=w/h;

gluPerspective(30.0,aspect,1.0,50.0);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity;

end;

6 几何变换矩阵

三维物体的运动姿态变换,是指物体的平移,旋转,缩放.

A glTranslate过程能够把坐标原点移到(x,y,z),它的声明语法:

procedure glTranslated(x:GLdouble,y:GLdouble,z:GLdouble);

procedure glTranslatef(x:GLdouble,y:GLdouble,z:GLdouble);

B glRotate能够使物体旋转一定的角度,它的声明语法:

procedure glRotated(angle:GLdobule,x:GLdouble,y:GLdouble,z:GLdouble);

procedure glRotatef(angle:GLdobule,x:GLdouble,y:GLdouble,z:GLdouble);

其中angle为旋转角,旋转的中心轴是由(0,0,0)与(x,y,z)两点的连线.

C glScale能够对坐标系进行缩放,它的声明语法为:

procedure glScaled(x:GLdouble,y:GLdoble,z:GLdouble);

procedure glScalef(x:GLdouble,y:GLdoble,z:GLdouble);

x,y,z的值大于1表示放大,小于1表示缩小.

例子原代码:

unit MainFrm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, OpenGL, ExtCtrls;

type

TfrmMain = class(TForm)

Timer1: TTimer;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormPaint(Sender: TObject);

procedure FormKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

procedure FormResize(Sender: TObject);

procedure Timer1Timer(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

private

{ Private declarations }

hrc:HGLRC;

w,h:Integer;

latitude,longitude:GLfloat;

radius:GLdouble;

public

{ Public declarations }

procedure MyDraw;

procedure InitializeGL(var width:GLsizei;height:GLsizei);

end;

var

frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);

var

pfd:TPixelFormatDescriptor;

PixelFormat:Integer;

begin

ControlStyle:=ControlStyle+[csOpaque];

FillChar(pfd,sizeof(pfd),0);

with pfd do

begin

nSize:=sizeof(TPixelFormatDescriptor);

nVersion:=1;

dwFlags:=PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;

iPixelType:=PFD_TYPE_RGBA;

cColorBits:=24;

cDepthBits:=32;

iLayerType:=PFD_MAIN_PLANE;

end;

PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);

SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);

hrc:=wglCreateContext(Canvas.Handle);

w:=ClientRect.Right;

h:=ClientRect.Bottom;

InitializeGL(w,h);

end;

procedure TfrmMain.FormDestroy(Sender: TObject);

begin

wglDeleteContext(hrc);

end;

procedure TfrmMain.FormPaint(Sender: TObject);

begin

wglMakeCurrent(Canvas.Handle,hrc);

glClearColor(1,1,1,1);

glColor3f(1,0,0);

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

MyDraw;

glFlush;

end;

procedure TfrmMain.MyDraw;

var

qObj:GLUQuadricObj;

begin

glPushMatrix;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glColor3f(1,0,0);

glRotated(0.5,0.0,1.0,0.0);

glRotated(-latitude,1.0,0.0,0.0);

glrotated(longitude,0.0,0.0,1.0);

qObj:=gluNewQuadric;

gluQuadricDrawStyle(qObj,GLU_LINE);

gluSphere(qObj,0.5,20,20);

SwapBuffers(Canvas.Handle);

end;

{procedure TfrmMain.FormResize(Sender: TObject);

var

nRange:GLfloat;

begin

nRange:=50.0;

w:=clientWidth;

h:=clientHeight;

if h=0 then

h:=1;

glViewPort(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

if w<=h then

glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,

-nRange,nRange)

else

glOrtho(-nRange*h/w,nRange*h/w,-nRange,nRange,

-nRange,nRange);

glMatrixMode(GL_MODELVIEW);

glLoadidentity;

repaint;

end;

}

procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

begin

if Key=VK_ESCAPE then

Close;

if Key=VK_UP then

glRotatef(-5,1.0,0.0,0.0);

if Key=VK_DOWN then

glRotatef(5,1.0,0.0,0.0);

if Key=VK_LEFT then

glRotatef(-5,0.0,1.0,0.0);

if Key=VK_RIGHT then

glRotatef(5.0,0.0,1.0,0.0);

repaint;

end;

procedure TfrmMain.FormResize(Sender: TObject);

begin

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);

glViewPort(0,0,clientWidth,clientHeight);

repaint;

invalidate;

end;

procedure TfrmMain.InitializeGL(var width: GLsizei; height: GLsizei);

var

maxObjectSize,aspect:GLfloat;

near_plane:GLdouble;

begin

glClearindex(0);

glClearDepth(1.0);

glEnable(GL_DEPTH_TEST);

glMatrixMode(GL_PROJECTION);

aspect:=1.0;

gluPerspective(45.0,aspect,3.0,7.0);

glmatrixMode(GL_MODELVIEW);

near_plane:=0.3;

maxObjectSize:=0.3;

radius:=near_plane+maxObjectSize/2.0;

latitude:=0.3;

longitude:=0.6;

end;

procedure TfrmMain.Timer1Timer(Sender: TObject);

begin

timer1.Enabled:=false;

MyDraw;

Yield;

Timer1.Enabled:=true;

end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);

begin

timer1.Enabled:=false;

if hrc<>null then

wglDeleteContext(hrc);

end;

end.

七、OPENGL的光照与纹理

都是增强三维立体效果和色彩效果的手段,光照能够增加图形的亮度和三维效果,纹理能够使用图形更加趋近现实。通过使用光照,可以将物体的外观很强列的表现出来,纹理则可以使物体显示多种多样的外观。

1 光照和光源过程及应用

A glIndex过程能够使颜色索引表中的某一种颜色成为当前颜色。

procedure glIndexd(c:GLdouble);

procedure glIndexf(c:GLdouble);

procedure glIndexi(c:GLdouble);

procedure glIndexs(c:GLdouble);

参数C为索引值,如果使用glIndex过程,则TPiexlFormatDescriptor结构中的iPixelType成员设置为PFD_TYPE_COLORINDEX。

B glShadeModel过程

glShadeModel过程设置填充模式,取值:GL_SMOOTH.

procedure glShadeModel(mode:GLenum);

注:以上两个过程只能在glBegin.....glEnd之外使用。

C glLight过程定义光源

procedure glLightf(light:GLenum,pname:GLenum,param:GLfloat);

procedure glLighti(light:GLenum,pname:GLenum,param:GLfloat);

参数light定义光源,其值可取:GL_LIGHT0.....GL_LIGHTN,N值小于GL_MAX_LIGHT.

参数pname指定光源参数:

GL_AMBIENT 环境光的分量强度

GL_DIFFUSE 散射光的分量强度

GL_SPECULAR 反射光的分量强度

GL_POSITION 光源位置

GL_SPOT_DIRECTION 光源的聚光方向

GL_SPOT_EXPONENT 光源的聚光指数

GL_SPOT_CUTOFF 光源的聚光方向

GL_CONSTANT_ATTENUATION 光常数衰退因子

GL_LINEAR_ATTENUATION 光二次衰减因子

启用和关闭光源使用glEnable()与glDisable()过程

glEnable(GL_LIGHTING); //启用光源

glDisable(GL_LIGHTING); //关闭光源

glEnable(GL_LIGHT0); //启用第0个光源

glDisable(GL_LIGHT0); //关闭第0个光源

设置光源的实例:

var

sdirection:Array[1..4] of GLfloat:={0.0,1.0,0.0,0.0};

glLightfv(GL_LIGHT0,GL_SPOT_CUTOFF,60);

glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,sdirection);

2 材质和光照模型

A glMaterial过程设置材质参数

procedure glMaterialf(face:GLenum,pname :GLenum,param:GLfloat);

procedure glMateriali(face:GLenum,pname :GLenum,param:GLfloat);

procedure glMaterialfv(face:GLenum,pname :GLenum,param:GLfloat);

procedure glMaterialiv(face:GLenum,pname :GLenum,param:GLfloat);

参数face指定物体表面,它的取值:GL_FRONT,GL_BACK,GL_FRONT_BACK.

pname,param本资料没作介绍.

B glLightModel过程

procedure glLightModelf(pname:GLenum,param:GLfloat);

参数pname为光源模型参数,可以取值GL_LIGHT_MODEL_AMBIENT,

GL_LIGHT_MODEL_LOCAL_VIEWER,GL_LIGHT_MODEL_TWO_SIDE.

实例代码:

procedure TfrmMain.SetLighting;

var

MaterialAmbient:array[1..4] of GLfloat;

MaterialDiffuse:Array[1..4] of GLfloat;

MaterialSpecular:Array[1..4] of GLfloat;

AmbientLightPosition:Array[1..4] of GLfloat;

LightAmbient:Array[1..4] of GLfloat;

MaterialShininess:GLfloat;

begin

MaterialAmbient[1]:=0.5;

MaterialAmbient[2]:=0.8;

MaterialAmbient[1]:=0.2;

MaterialAmbient[1]:=1.0;

MaterialDiffuse[1]:=0.4;

MaterialDiffuse[2]:=0.8;

MaterialDiffuse[3]:=0.1;

MaterialDiffuse[4]:=1.0;

MaterialSpecular[1]:=1.0;

MaterialSpecular[2]:=0.5;

MaterialSpecular[3]:=0.1;

MaterialSpecular[4]:=1.0;

materialShininess:=50.0;

AmbientLightPosition[1]:=0.5;

AmbientLightPosition[2]:=1.0;

AmbientLightPosition[3]:=1.0;

AmbientLightPosition[4]:=0.0;

LightAmbient[1]:=0.5;

LightAmbient[2]:=0.2;

LightAmbient[3]:=0.8;

LightAmbient[4]:=1.0;

glMaterialfv(GL_FRONT,GL_AMBIENT,@MaterialAmbient);

glMaterialfv(GL_FRONT,GL_DIFFUSE,@MaterialDiffuse);

glMaterialfv(GL_FRONT,GL_SPECULAR,@MaterialSpecular);

glMaterialfv(GL_FRONT,GL_SHININESS,@MaterialShininess);

glLightfv(GL_LIGHT0,GL_POSITION,@AmbientLightPosition);

glLightModelfv(GL_LIGHT_MODEL_AMBIENT,@LightAmbient);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

GLShadeModel(GL_SMOOTH);

end;

3 纹理的应用

A glTexImage1D定义一维纹理映射.

procedure glTexImage1D(target:GLenum,level:GLint,components:GLint,width:GLsizei,

border:GLint,format:GLenum,type:GLenum,pixels:GLvoid);

参数targer值为GL_TEXTURE_1D,定义为纹理映射,level为多级分辨率的纹理图像的等级,width为纹理宽,值为2n,n取值为32,64,129等.border为纹理的边界,其值为0或1,Pixel为纹理在内存中的位置.Component指定RGBA的混合和调整:

1 选择B成分

2 选择B,A成分

3 选择R,G,B成分

4 选择R,G,B,A成分

B glTexImage2D定义二维纹理映射

procedure glTexImage2D(target:GLenum,level:GLint,components:GLint,width:GLsizei,

border:GLint,format:GLenum,type:GLenum,pixels:GLvoid);

若参数target为GL_TEXTURE_2D,意义为二维纹理映射,height为纹理的高,函数中的其它参数与glTexImage1D相同.component参数取值同上.

实例代码:

procedure TfrmMain.SetTextures;

var

bits:Array[1..64,1..64,1..64] of GLubyte;

bmp:TBitmap;

i,j:Integer;

begin

bmp:=TBitmap.Create;

bmp.LoadFromFile('d:\dsoft\1119\01\logon.bmp');

for i:=1 to 64 do

for j:=1 to 64 do

begin

bits[i,j,1]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));

bits[i,j,2]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));

bits[i,j,3]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));

bits[i,j,4]:=255;

end;

{0代表为单色着色水平,GL_RGBA表示混合值

64X64代表纹理的高和宽,0表示无边界,

GL_RGBA代表纹理类型,GL_UNSIGNED_TYPE代表数据类型,@代对象地址}

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,64,0,GL_RGBA,

GL_UNSIGNED_BYTE,@bits);

glEnable(GL_TEXTURE_2D);

end;

C glTexParameter过程设置纹理参数

procedure glTexParameterf(target:GLenum,pname:GLenum,param:GLfloat);

procedure glTexParameteri(target:GLenum,pname:GLenum,param:GLfloat);

参数target代表GL_TEXTURE_1D或GL_TEXTURE_2D,param为纹理值.

D glTexEnv函数设置纹理的环境参数

function glTexEnvf(target:GLenum,pname:GLenum,param:GLfloat);

function glTexEnvi(target:GLenum,pname:GLenum,param:GLfloat);

参数target为GL_TEXTURE_ENV,

参数pname为纹理参数值,取值为GL_TEXTURE_ENV_MODE

参数param为环境值,取值为GL_MODULATE,GL_DECAL和GL_BLEND.

本程序示例代码:

unit MainFrm;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, OpenGL, ExtCtrls;

type

TfrmMain = class(TForm)

Timer1: TTimer;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure FormPaint(Sender: TObject);

procedure FormKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

procedure FormResize(Sender: TObject);

procedure Timer1Timer(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

private

{ Private declarations }

hrc:HGLRC;

w,h:Integer;

latitude,longitude:GLfloat;

radius:GLdouble;

public

{ Public declarations }

procedure SetLighting;

procedure SetTextures;

procedure MyDraw;

procedure InitializeGL(var width:GLsizei;height:GLsizei);

end;

var

frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);

var

pfd:TPixelFormatDescriptor;

PixelFormat:Integer;

begin

ControlStyle:=ControlStyle+[csOpaque];

FillChar(pfd,sizeof(pfd),0);

with pfd do

begin

nSize:=sizeof(TPixelFormatDescriptor);

nVersion:=1;

dwFlags:=PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;

iPixelType:=PFD_TYPE_RGBA;

cColorBits:=24;

cDepthBits:=32;

iLayerType:=PFD_MAIN_PLANE;

end;

PixelFormat:=ChoosePixelFormat(Canvas.Handle,@pfd);

SetPixelFormat(Canvas.Handle,PixelFormat,@pfd);

hrc:=wglCreateContext(Canvas.Handle);

w:=ClientRect.Right;

h:=ClientRect.Bottom;

InitializeGL(w,h);

end;

procedure TfrmMain.FormDestroy(Sender: TObject);

begin

wglDeleteContext(hrc);

end;

procedure TfrmMain.FormPaint(Sender: TObject);

begin

wglMakeCurrent(Canvas.Handle,hrc);

glClearColor(1,1,1,1);

glColor3f(1,0,0);

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

SetTextures;

MyDraw;

SetLighting;

glFlush;

end;

procedure TfrmMain.MyDraw;

var

qObj:GLUQuadricObj;

begin

glPushMatrix;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glColor3f(1,0,0);

glRotated(0.5,0.0,1.0,0.0);

glRotated(-latitude,1.0,0.0,0.0);

glrotated(longitude,0.0,0.0,1.0);

qObj:=gluNewQuadric;

gluQuadricDrawStyle(qObj,GLU_LINE);

gluSphere(qObj,0.5,20,20);

SwapBuffers(Canvas.Handle);

SetLighting;

SetTextures;

end;

{procedure TfrmMain.FormResize(Sender: TObject);

var

nRange:GLfloat;

begin

nRange:=50.0;

w:=clientWidth;

h:=clientHeight;

if h=0 then

h:=1;

glViewPort(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

if w<=h then

glOrtho(-nRange,nRange,-nRange*h/w,nRange*h/w,

-nRange,nRange)

else

glOrtho(-nRange*h/w,nRange*h/w,-nRange,nRange,

-nRange,nRange);

glMatrixMode(GL_MODELVIEW);

glLoadidentity;

repaint;

end;

}

procedure TfrmMain.FormKeyDown(Sender: TObject; var Key: Word;

Shift: TShiftState);

begin

if Key=VK_ESCAPE then

Close;

if Key=VK_UP then

glRotatef(-5,1.0,0.0,0.0);

if Key=VK_DOWN then

glRotatef(5,1.0,0.0,0.0);

if Key=VK_LEFT then

glRotatef(-5,0.0,1.0,0.0);

if Key=VK_RIGHT then

glRotatef(5.0,0.0,1.0,0.0);

repaint;

end;

procedure TfrmMain.FormResize(Sender: TObject);

begin

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

glFrustum(-1.0,1.0,-1.0,1.0,3.0,7.0);

glViewPort(0,0,clientWidth,clientHeight);

repaint;

invalidate;

end;

procedure TfrmMain.InitializeGL(var width: GLsizei; height: GLsizei);

var

maxObjectSize,aspect:GLfloat;

near_plane:GLdouble;

begin

glClearindex(0);

glClearDepth(1.0);

glEnable(GL_DEPTH_TEST);

glMatrixMode(GL_PROJECTION);

aspect:=1.0;

gluPerspective(45.0,aspect,3.0,7.0);

glmatrixMode(GL_MODELVIEW);

near_plane:=0.3;

maxObjectSize:=0.3;

radius:=near_plane+maxObjectSize/2.0;

latitude:=0.3;

longitude:=0.6;

end;

procedure TfrmMain.Timer1Timer(Sender: TObject);

begin

timer1.Enabled:=false;

MyDraw;

Yield;

Timer1.Enabled:=true;

end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);

begin

timer1.Enabled:=false;

if hrc<>null then

wglDeleteContext(hrc);

end;

procedure TfrmMain.SetLighting;

var

MaterialAmbient:array[1..4] of GLfloat;

MaterialDiffuse:Array[1..4] of GLfloat;

MaterialSpecular:Array[1..4] of GLfloat;

AmbientLightPosition:Array[1..4] of GLfloat;

LightAmbient:Array[1..4] of GLfloat;

MaterialShininess:GLfloat;

begin

MaterialAmbient[1]:=0.5;

MaterialAmbient[2]:=0.8;

MaterialAmbient[1]:=0.2;

MaterialAmbient[1]:=1.0;

MaterialDiffuse[1]:=0.4;

MaterialDiffuse[2]:=0.8;

MaterialDiffuse[3]:=0.1;

MaterialDiffuse[4]:=1.0;

MaterialSpecular[1]:=1.0;

MaterialSpecular[2]:=0.5;

MaterialSpecular[3]:=0.1;

MaterialSpecular[4]:=1.0;

materialShininess:=50.0;

AmbientLightPosition[1]:=0.5;

AmbientLightPosition[2]:=1.0;

AmbientLightPosition[3]:=1.0;

AmbientLightPosition[4]:=0.0;

LightAmbient[1]:=0.5;

LightAmbient[2]:=0.2;

LightAmbient[3]:=0.8;

LightAmbient[4]:=1.0;

glMaterialfv(GL_FRONT,GL_AMBIENT,@MaterialAmbient);

glMaterialfv(GL_FRONT,GL_DIFFUSE,@MaterialDiffuse);

glMaterialfv(GL_FRONT,GL_SPECULAR,@MaterialSpecular);

glMaterialfv(GL_FRONT,GL_SHININESS,@MaterialShininess);

glLightfv(GL_LIGHT0,GL_POSITION,@AmbientLightPosition);

glLightModelfv(GL_LIGHT_MODEL_AMBIENT,@LightAmbient);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

GLShadeModel(GL_SMOOTH);

end;

procedure TfrmMain.SetTextures;

var

bits:Array[1..64,1..64,1..64] of GLubyte;

bmp:TBitmap;

i,j:Integer;

begin

bmp:=TBitmap.Create;

bmp.LoadFromFile('d:\dsoft\1119\02\logon.bmp');

for i:=1 to 64 do

for j:=1 to 64 do

begin

bits[i,j,1]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));

bits[i,j,2]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));

bits[i,j,3]:=GLbyte(GetRValue(bmp.Canvas.Pixels[i,j]));

bits[i,j,4]:=255;

end;

glPixelStorei(GL_UNPACK_ALIGNMENT,4);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);

{0代表为单色着色水平,GL_RGBA表示混合值

64X64代表纹理的高和宽,0表示无边界,

GL_RGBA代表纹理类型,GL_UNSIGNED_TYPE代表数据类型,@代对象地址}

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,64,0,GL_RGBA,

GL_UNSIGNED_BYTE,@bits);

glEnable(GL_TEXTURE_2D);

glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);

end;

end.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有