2024年5月11日发(作者:)

2010年海南省机械工程学会

Ⅱ-45

VB环境下OpenGL编程初探

杨亮曹阳

(海南优势资源化工材料应用技术教育部重点实验室,硅锆钛资源综合开发与利用

海南省重点实验室,海南大学材料与化工学院,海南海口570228)

摘要:

OpenGL是一种被广泛使用的三维图形与模型库,通常由C语言所开发。在种情况下,重

点讲述了VB中实现OpenGL图形开发的基本原理和具体实现方法,并针对OpenGL的像素格式、模型

变换、光照、材质、纹理、位图操作、平移、旋转、绘制几何图形等基本操作都作了细致的描述,

旨在将VB的应用拓展到三维图像处理领域,提高Opnegl编程效率和开发周期,结合两者的长处开发

出优秀的软件。

关键词:

VBOpenGL三维API

1引言

OpenGraphicsLibrary(开放性图形库)缩写

为OpenGL,是一套三维图形处理库,也是该领

域的工业标准。OpenGL被设计成独立于硬件,

独立于窗口系统,在运行各种操作系统的计算

机上都可用,并能在网络环境下以客户/服务器

模式工作,是专业图形处理、科学计算等高端

应用领域的标准图形库,主要应用方向包括飞

行训练、分子结构、研究、影视广告、CAD/

CAM/CAE、游戏娱乐、医学成像、计算机动

画制作和虚拟现实等。特别是Kinetix公司

的3DStudioMax就是其应用的突出的代表。

OpenGL是一组绘图命令的API集合,利用

这些API能够方便地描述二维和三维几何物体,

OpenGL的API集还提供了几何描述和图像图元、

显示列表、模型变换、反走样、物体、平移、

旋转、缩放、光照、纹理、材质、像素、位图、

文字、交互以及提高显示性能等方面的功能。

但是,OpenGL是一个包含120多个图形函数组

成的图形库,不包括任何窗口管理、用户交

互或文件I/O函数,使得OpenGL丧失了处

理窗口、用户输入命令的能力和缺乏面向对象

能力,不符合当前流行的软件设计思想。所以

必须在一定的语言环境中才能实现对OpenGL函

数的引用,最早使用OpenGL的编程语言是C语

[2]

[1]

言,随后又采用了C++或VC++,对于其它

语言环境下利用OpenGL图形函数开发图形应用

程序却较少有人研究,其他语言环境下OpenGL

编程方面的资料收集相对困难,这样更限制了

OpenGL在其他高级语言中的应用。

Vb是目前使用最广泛的编程语言,拥有数

目巨大的使用者。在VB编程环境下对OpenGL引

用来开发应用程序的研究较少,这对众多的VB

使用者来说是一种巨大的损失。VB中可利用

Windows提供的动态链接库OpenGL32.DLL和

GLU32.DLL来实现对OpenGL的调用来对图形进

行绘制

[4,5]

[3]

,而且还可以利用SCI公司提供的

GLUT32.DLL直接调用更多的图形函数进行图

形的开发,这样使OpenGL的开发更容易,同时

也使VB在能拓展到3D领域,使众多的VB使用

者能开发出美丽三维图像。

2实现过程

2.1Vb环境设置

新建一个标准EXE工程,在工程菜单下选

择引用,打开“引用”对话框,然后勾取“VB

OpenGLAPI1.2(ANSI)”项,从而实现VB对

OpenGL函数库的引用。然后在窗体stage上放置

两个PictureBox控件和一个时钟控件,并添加两

个模块。

一个OpenGL应用程序首先必须创建一个图

形操作描述表,然后再启动它,最后在所定义

Ⅱ-46

2010年海南省机械工程学会

的窗口内按常规方式调用OpenGL函数绘制图形。

Vb是基于窗口系统的可视化编程环境,对于每

个OpenGL程序都必须处理设备描述表,在创建

一个图形操作描述表之前,首先必须设置像素

格式。像素格式含有设备绘图界面的属性,这

些属性包括绘图界面是用RGBA模式还是颜色

表模式,像素缓存是用单缓存还是双缓存,以

及颜色位数、深度缓存和模板缓存所用的位数,

还有其它一些属性信息。每个OpenGL显示

设备都支持一种指定的像素格式。一般用一个

名为PIXELFORMATDESCRIPTOR的结构

来表示某个特殊的像素格式。我们将

FIXELFORMATDESCRIPTOR的结构放在一个名

为OpenGL的标准模块中EnableOpenGL过程中,

首先要定义FIXELFORMATDESCRIPTOR的像素

格式结构,代码如下:

ZeroMemorypfd,Len(pfd)用零来填充内存

区域,起点为PDF,大小为LEN(PDF)

pfd.nSize=Len(pfd)

pfd.nVersion=1

结构大小

版本号

wglMakeCurrentghDC,hRC使之成为当前绘

图描述表

这一模块的作用是创建了一个渲染上下文,

每一个OpenGL程序都必须和一个渲染上下文

(RC)相连接,在本程序中渲染上下文定义为

HRC,为了使能在窗口中绘制图像,必须定义上

下文句柄为HRC,渲染上下文可以使OpenGL把

绘制作用到设备上下文(DC)中来,设备上下

文连接图像设备接口(GDI)而渲染上下文则把

OpenGL连接到设备上下文。必须创建图形操作

描述表并启用渲染上下文后,才能调用OpenGL

函数在窗口内进行各种图形操作

[6]

2.2.加载图片并转化为纹理

建立一个名为LoadBMP的模块,用来加载

位图信息并转化为纹理。加载的位图图像的宽和

高必须是2的n次方,宽度和高度最小必须是64象

素,并且出于兼容性的原因,图像的宽度和高度

不应超过256象素。可用相应的处理软件将要转

化成纹理的图片加工成OpenGL要求的大小。声

明一个名为loadBMP的函数,用它来加载图片并

将其转化为二进制的数据信息。这里用一个

PictureBox控件来加载图片,必须将PictureBox控

件的ScaleMode属性设置为3-Pixd格式,才能调

用LoadBMP函数得到图片的像素信息。

PrivateFunctionloadBMP(ByValFilenameAs

String,ByRefTextureImg()AsGLubyte)AsBoolean

DimxAsLong,yAsLong,tempAsLong定义

临时的变量

Dimbi24BitInfoAsBITMAPINFO

定义BMP图片的格式

WithStage.Pict

.Picture=LoadPicture(Filename)

PictureBox控件加载BMP图

.Refresh

tw=.ScaleWidth

得到加载的BMP图片的宽度信息

th=.ScaleHeight

得到加载的BMP图片的高度信息

ReDimTextureImg(2,tw-1,th-1)

重新定义数组

EndWith

刷新PictureBox

pfd.dwFlags=PFD_DRAW_TO_WINDOW

OrPFD_SUPPORT_OPENGLOrPFD_DOUBLEBUFFER

OrPFD_GENERIC_FORMAT

绘图到Window,支持OpenGL,支持双缓

冲,通用模式

pfd.iPixelType=PFD_TYPE_RGBA

像素格式类型为RGBA

pfd.cColorBits=24

pfd.cDepthBits=16

pfd.cStencilBits=1

pfd.iLayerType=PFD_MAIN_PLANE

主层类型

PixFormat=ChoosePixelFormat(ghDC,pfd)

为设备描述表得到最匹配的像素格式,确定

Pdf结构是否存在

SetPixelFormatghDC,PixFormat,pfd如果

存在设备描述像素格式,把指定的像素格式赋

给指定的设备

hRC=wglCreateContext(ghDC)创建绘图描

述表

颜色索引位

深度缓冲区位数

2010年海南省机械工程学会

Ⅱ-47

Withbi24BitInfo.bmiHeader

头赋值

.biBitCount=24

位元存储

.biCompression=BI_RGB

.biPlanes=1

位图信息

TextureImage())Then

Status=True

glTexEnviGL_TEXTURE_ENV,

GL_TEXTURE_ENV_MODE,GL_MODULATE

纹理的贴图方式,与物体相溶合

glTexParameteriGL_TEXTURE_2D,

GL_TEXTURE_MAG_FILTER,GL_LINEAR

图像被放大时的采用线性滤波

glTexParameteriGL_TEXTURE_2D,

GL_TEXTURE_MIN_FILTER,GL_LINEAR

图像被缩小时的采用线性滤波

glTexImage2DGL_TEXTURE_2D,0,3,tw,th,

0,GL_RGB,GL_UNSIGNED_BYTE,TextureImage

(0,0,0)

将图像信息TextureImage(0,0,0)形成纹理

EndIf

EraseTextureImage

EndFunction

2.3.绘制图形

由于在VB编程环境下只有窗体和PictureBox

控件具有绘制、显示图形的功能,并且他们的缺

省的像素格式都是Windows的GDI设置的,为了

使OpenGL命令绘制的图形能够在其上显示,必须

进行重新初始化它们的像素格式,并利用Opnegl

命令将窗口进行必要的渲染,这样才能绘制出高

质量的图形。

PrivateSubForm_Resize()

EnableOpenGLPic1.hDC

素格式

glClearColor0,0.5,0,0

glClearDepth1#

glEnableGL_DEPTH_TEST

glDepthFuncGL_LESS

glHintGL_PERSPECTIVE_CORRECTION_HINT,

GL_NICEST

打开光照,放置光源

glEnableglcLighting

glEnableglcLight0

允许深度测试

设置背景色为绿色

glShadeModelGL_SMOOTH

初始化PIC1控件的像

擦除纹理矩阵的内容

LoadGLTextures=Status

每个像素以几个

是否压缩

.biSize=Len(bi24BitInfo.bmiHeader)

‘BitmapInfoHeader结构大小

.biWidth=tw

需要处理位图宽度(单位:像素)

.biHeight=th

需要处理位图高度(单位:像素)

EndWith

GetDIBitsStage.Pict.hDC,Stage.Pict.Image,

0,th,TextureImg(0,0,0),bi24BitInfo,0

将来自一幅位图的二进制位复制到一幅与

设备无关的位图里。这里他将二进制位复制到

已经定义好的三维数组,它将某像素点的BLUE

分量存储到了(0,x,y)将GREEN分量存储到

(1,x,y),将RED分量存储到了(2,x,y)中,

这样就使得在调用纹理数组时,产生的图像的

颜色值的BLUE分量与RED分量互换的情况,所

以用下面的一段代码将纹理颜色分量进行调整。

Forx=0Totw-1

Fory=0Toth-1

temp=TextureImg(0,x,y)

TextureImg(0,x,y)=TextureImg(2,x,y)

TextureImg(2,x,y)=temp

Nexty

Nextx

loadBMP=True

EndFunction

下面是通过调用LaodBMP函数来加载图像

信息,并将位图转化为纹理。

FunctionLoadGLTextures()AsBoolean

DimStatusAsBoolean

DimTextureImage()AsGlbyte

Status=False'StatusIndicator

IfloadBMP(App.Path&"\tim.BMP",

Ⅱ-48

2010年海南省机械工程学会

DimPos(0To3)AsGlfloat

Pos(0)=0:Pos(1)=0:Pos(2)=5:Pos(3)=3

glLightfvltLight0,lpmPosition,Pos(0)

设置材质属性

Dimambient(0To3)AsGlfloat

DimDiffuse(0To3)AsGlfloat

DimSpecilar(0To3)AsGlfloat

DimShininess(0)AsGlfloat

ambient(0)=0.8:ambient(1)=0.8:ambient(2)=0.8:

ambient(3)=1

Diffuse(0)=0.8:Diffuse(1)=0.8:Diffuse(2)=0.8:

Diffuse(3)=1

Specilar(0)=0:Specilar(1)=1:Specilar(2)=1:S

pecilar(3)=3

Shininess(0)=25

glMaterialfvfaceFront,mprAmbient,ambient(0)

glMaterialfvfaceFront,mprDiffuse,Diffuse(0)

glMaterialfvfaceFront,mprSpecular,Specilar(0)

glMaterialfvfaceFront,mprShininess,

Shininess(0)

glEnableglcColorMaterial

DimwAsLong,hAsLong

w=Me.ScaleWidth:h=Me.ScaleHeight

Ifh=0Thenh=1

glViewport0,0,w,h

定义投影矩阵

glLoadIdentity重置模型观察矩阵

gluPerspective40#,w/h,1,100#定义视角

glMatrixModeGL_MODELVIEW

定义模型变换矩阵

glLoadIdentity

重置模型观察矩阵

glClearGL_COLOR_BUFFER_BITOrGL_DEPTH

_BUFFER_BIT

清除屏幕及深度缓

glLoadIdentity

glTranslatef0,0,-15

LoadGLTextures

glPolygonModefaceBack,pgmLine形背面以线填充

重置模型观察矩阵

移入屏幕15个单位

定义视见区

glMatrixModeGL_PROJECTION

glPolygonModefaceFront,pgmFILL

图形前面以全填充

glEnableglcTexture2D

Timer1.Enabled=True

EndSub

Timer事件能准确每隔一定的时间触发一次,

使程序运行在不同速度的计算机上的变化效果几

乎没有差别,使动画连续稳定。

PrivateSubTimer1_Timer

DimxAsInteger,yAsInteger,rAsInteger

StaticTAsInteger定义T为静态整型变量,

存储变化的角度值。

Dimpx1AsGLfloat,py1AsGLfloat,pz1As

Double,px2AsGLfloat,py2AsGLfloat,pz2AsDouble

glRotatef3,0,0,1使图像没Z轴旋转

以Px1、Px2、Py1、Py2、Pz1、Pz2六点来

组合成一个四边形,通过使用整数循环来产生

99×99的方格集合,为了使产生的方格居中,

将x.,y变量除以10再减去5。

glBeginbmQuads画矩形的开始语句,必须

以glEnd结束

Fory=1To100

Forx=1To100

px1=(x-1)/10-5

py1=(y-1)/10-5

pz1=Cos((y-1)/10*40/360*3.141592654

*2+t/180*3.141592654)

px2=(x)/10-5

py2=(y)/10-5

pz2=Cos(y/10*40/360*3.141592654*

2+t/180*3.141592654)

glTexCoord2f(x-1)/100,(y)/100

glVertex3fpx1,py2,pz2

利用x,y值可以直接计算纹理坐标,每个多

边形分别映射了纹理的1/99×1/99部分,纹理坐

标不同于网格坐标,纹理坐标以纹理图像的高

宽为单位1,网格以实际值为坐标每个网格的绘

制都是以逆时针绘制的。

glTexCoord2f(x-1)/100,(y-1)/100

glVertex3fpx1,py1,pz1

启用纹理映射

触发时钟事件

2010年海南省机械工程学会

Ⅱ-49

glTexCoord2f(x)/100,(y-1)/100

glVertex3fpx2,py1,pz1

glTexCoord2f(x)/100,(y)/100

glVertex3fpx2,py2,pz2

Nexty

Nextx

glEnd

SwapBuffersPic1.hDC交换缓冲区数据

glClearclrColorBufferBitOrclrDepthBufferBit清除

颜色缓存和深度缓冲,否则会使多幅图像

重叠在一起

EndSub

PrivateSubForm_Unload(CancelAsInteger)

wglMakeCurrent0,0清空当前绘图描述表

wglDeleteContexthRC

EndSub

EndSub

3结束语

本文对VB中应用OpenGL进行三维动画开

发过程作了一个详细的介绍,意在阐明VB中运

用OpenGL的基本原理和具体实现方法,对VB

程序员利用OpenGL起一抛砖引玉的作用。VB

与OpenGL结合可使VB方便的调用OpenGL的API

函数进行图形的绘制和场景的渲染,同时由于

Vb语言简单、实用、提高了开发的速度和软件

的质量,而且成本低。我们相信在不久的将来,

它们一定会发挥出巨大的作用。未来是光明的,

前景是诱人的。

致谢:

海南大学校基金(Kyjj0604)、

海南大学材料与化工学院课程群教学团队资助

项目。

删除绘图描述表

参考文献:

[1]潇湘工作室译.计算机技术译林精选系

列:OpenGL超级宝典[M].北京:人民邮电

出版社,2001-01-01:10-13

[2]史正中,郭继坤等。基于VB+OpenGL三

维地形实现[J],后勤工程学院学报,

2003年第1期:92-96

[3]欧训勇.OpenGL程序移植技术浅析

[J],计算机应用研究,2002:158-161

[4].王峰.用VisualBasic实现OpenGL三维

地形显示[J].测绘信息与工程,2000No.

3:13-17

[5]张晓宇,曲家文等.在VB6.0中利用

OpenGL进行图形编程[J].电脑学习,

2001(2):23-24

[6]荷塘月色创作组编著.如何使用

OpenGL开发程序[M].北京:北京理工大

学出版社,1999-01-01:208

作者简介:

杨亮:男,1979年5月生,实验师,海南大

学材料与化工学院,海南海口:570228

E-mail:YL5923@sina.com.cn