VB编写DirectX简明教程_第1页
VB编写DirectX简明教程_第2页
VB编写DirectX简明教程_第3页
VB编写DirectX简明教程_第4页
VB编写DirectX简明教程_第5页
已阅读5页,还剩152页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

VB编写DirectX简明教程随这计算机软硬件的发展,计算机不在只是一个简单的计算工具而成为了一个可以玩游戏、进行多媒体操作的多功能平台。为了编写高性能的游戏和应用程序,我们需要绕过操作系统提供的API直接操作硬件以充分利用硬件的加速效果,但是由于现在的计算机配件数以万计,那么我们在编写程序时需要为每一类编写代码。这样就大大的浪费了资源。现在有了DirectX,这个问题就解决了,硬件厂家只要根据DirectX要求编写驱动程序,而程序员只要同单一的DirectX库打交道而基本不用顾及具体的硬件,这样不但大大的简化了编程而且也提高了程序性能。

由于微软的影响力,DirectX库已经成为了游戏开发的标准之一。过去要进行DirectX开发只能使用复杂的C++,不过自从DirectX7发布以来,微软同时也发布了DirectX的VB开发库,这样我们业可以使用VB来开发基于DirectX的游戏和应用程序了。

完整的DirectX7SDK库有139M大,其中包括了VB、VC开发库,在线开发文档,范例程序以及一些实用程序。只有至少安装了开发库中的VB部分以后,才可以来开发DirectX程序。

安装好DirectX开发库之后,打开VB,点击菜单的Project|References项打开References对话框,可以发现在列表中多了一项:DirectX7ForVisualBasicTypelibrary,点击该项,就可以把DirectX库加入到VB工程中。下面文章中编写每一个范例前都要首先进行上面的操作将DirectX7ForVisualBasicTypelibrary加入到VB工程中。

DirectX7开发库是基于对象的,其中最基本的对象是DirectX7对象,只有在程序中首先建立了DirectX7对象之后才可以在该对象的基础上建立其它对象。DirectX基本对象包含以下几类:

DirectDraw类独立于设备的平面绘图对象,支持以全屏方式或者窗口方式绘图。DirectDraw支持对显存的直接操作。一旦定义DirectDraw对象并锁定,就可以象操作一个数组一样的操作显存中的内容了。

Direct3D类DirectX三维绘图接口,包括立即模式(ImmediateMode)和保留模式,是绝大部分的三维DirectX游戏的基础。Direct3D类对象独立于设备。

DirectSound类DirectX中的Wave音频对象,独立于设备,支持混音、硬件加速、直接设备访问、声音捕捉和回放。

DirectMusic类音乐数据文件操作对象,支持DLS(downloadablesounds)标准,支持运行时编辑。

DirectInput类独立于设备的游戏控制器对象,支持鼠标、键盘、游戏杆,并且支持力反馈游戏杆。

DirectPlay类为支持多任游戏而设计的对象,支持不同的计算机通过网络、Internet或者Modem进行互连。支持建立游戏服务器,用户可以登陆到服务器上并纪录用户信息。可以协调速度不同的计算机之间的信息传递(例如一个使用专线和一个使用低速Modem的计算机之间)。

一、DirectDrawDirectDraw类是DirectX中绘图的基础,它包含以下的对象:· DirectDraw7· DirectDrawClipper· DirectDrawEnumModes· DirectDrawPalette· DirectDrawSurface7DirectDraw7是基本的DirectDraw类对象,它是建立其它对象的基础,DirectDraw7对象要通过DirectX7对象的DirectDrawCreate方法来建立。例如下面的语句就可以建立一个DirectDraw对象:

DimobjDxAsNewDirectX7

DimobjDrawAsDirectDraw7

SetobjDx=NewDirectX7

DirectDrawClipper对象可以建立一个屏幕的剪裁区域的列表。该对象的一个通常的应用是设置屏幕或者窗口区域,例如在你的游戏中有一个人物移动到了屏幕的边缘,你不希望他一下消失掉而是要平滑的移出,如果没有DirectDrawClipper对象的话这将后台的图像复制到前台会出现错误,因为人物图像的一部分已经移动到了绘图平面的外面,而有了DirectDrawClipper对象,DirectDraw就知道人物图像区域的那些部分是可见的而那些部分应该被剪裁掉。利用DirectDraw7的CreateClipper方法可以建立一个DirectDraw7下的DirectDrawClipper对象

通过DirectDrawEnumModes对象可以获得当前系统支持的显示模式。DirectDraw7的GetDisplayModesEnum方法可以建立一个DirectDrawEnumModes对象。

DirectDrawPalette对象是DirectDraw下的绘图调色板对象,它很类似于Windows下的调色板。DirectDraw7的CreatePalette方法可以建立一个DirectDrawPalette对象。

DirectDrawSurface7是DirectDraw下的最重要的对象,它有点类似Windows下窗口的hDC,我们所进行的所有图形、文本操作都是在这个对象上进行的。这个对象描述了一块线型的显存区域,你可以通过DirectDrawSurface7对象直接操作这片区域。如果你还记得在Dos下的QB4.5编写图形程序的话,DirectDrawSurface7对象就同它有一些类似。通过DirectDraw7的CreateSurface方法,你可以建立一个单一绘图平面、复合绘图平面或者三维绘图平面对象。而利用DirectDraw7的CreateSurfaceFromFile方法、CreateSurfaceFromResource方法可以建立一个包含位图的DirectDrawSurface7对象。DirectDrawSurface7对象是DirectDraw类对象中最难掌握的对象。

下面我们将通过建立一个简单的DirectDraw程序并通过充实程序来学习DirectDraw的基本原理和应用。首先来建立一个简单的DirectDraw程序,建立一个新的工程,将Direct7说明库加入到工程中,然后在Form1中加入两个CommandButton和一个ListBox控件,在Form1中加入以下代码:

OptionExplicitDimobjDxAsNewDirectX7DimobjDrawAsDirectDraw7DimobjEnumModesAsDirectDrawEnumModesSubCleanup()'Cleanup函数回复屏幕并且清除DirectX对象CallobjDraw.RestoreDisplayModeCallobjDraw.SetCooperativeLevel(Me.hWnd,DDSCL_NORMAL)SetobjDraw=NothingSetobjDx=NothingEndEndSubPrivateSubCommand1_Click()CleanUpEndSubPrivateSubForm_Load()Command1.Caption="结束"Command2.Caption="设置显示模式"OnErrorGoToErrHandler:DimddsdAsDDSURFACEDESC2DimIAsLong,lgCountAsLongSetobjDx=NewDirectX7'建立DirectDraw对象SetobjDraw=objDx.DirectDrawCreate("")'将DirectDraw对象支持的显示模式设置到DirectDrawEnumModes对象中SetobjEnumModes=objDraw.GetDisplayModesEnum(DDEDM_DEFAULT,ddsd)'将数据设置到ListBox中lgCount=objEnumModes.GetCount()ForI=1TolgCountobjEnumModes.GetItemI,ddsdList1.AddItemCStr(ddsd.lWidth)&"x"&CStr(ddsd.lHeight)&"x"_&CStr(ddsd.ddpfPixelFormat.lRGBBitCount)NextIErrHandler: SelectCaseErr.NumberCase0'没有错误 CaseElse Err.RaiseErr.Number,Err.Source,Err.Description,Err.HelpContext,_ Err.HelpContextCallCleanup EndSelectEndSubPrivateSubForm_Unload(CancelAsInteger)CleanupEndSub

程序的运行结果如下图:

上面的范例首先演示了如何建立一个简单的DirectDraw对象并获得该对象支持的显示模式。下面我们要将在原来程序的基础上添加一些模块以实现更多的功能。

首先在上面的程序中加入一个函数SetNewDisplayMode,函数代码如下:

PrivateFunctionSetNewDisplayMode()OnErrorGoToErrHandlerDimddsdAsDDSURFACEDESC2DimiAsLongi=List1.ListIndexIfi=-1ThenMsgBox"请在列表中选择一种显示模式",vbOKOnly,"错误" ExitFunctionEndIfobjEnumModes.GetItem(i+1),ddsd'设置协作模式objDraw.SetCooperativeLevelMe.hWnd,DDSCL_FULLSCREENOr_DDSCL_ALLOWMODEXOrDDSCL_EXCLUSIVE'设置显示模式objDraw.SetDisplayModeddsd.lWidth,ddsd.lHeight,_ddsd.ddpfPixelFormat.lRGBBitCount,_0,DDSDM_DEFAULTMe.RefreshErrHandler:SelectCaseErr.NumberCase0'NoErrorsCaseElseErr.RaiseErr.Number,Err.Source,Err.Description,Err.HelpContext,_Err.HelpContextCallCleanupEndSelectEndFunction在Command2的Click事件中加入以下代码:Dimi Fori=0ToForm1.Controls.Count-1 Form1.Controls(i).Visible=False NextiSetNewDisplayMode再次运行程序,点击列表中的任意一个显示模式,然后点击"设置显示模式"按钮,可以看到屏幕的显示模式被设置成了你在列表中选择的模式。

上面介绍的是如何设置显示模式,下面介绍如何利用DirectSurface对象来进行图形绘制以及如何利用前台绘图平面同后台绘图平面相配合工作。这个程序要实现的目的是:在屏幕上显示一幅背景位图,然后有一个角色在屏幕上移动。为了实现上面的目的,我们需要建立四个绘图平面,一个主平面,就是程序运行时可以看到的平面;一个后台缓冲平面,用于进行图像操作;一个位图平面,用于显示背景位图;一个角色位图平面,用于显示角色位图。在程序运行时首先将背景位图贴到后台缓冲平面,然后将角色位图平面贴到后台缓冲平面,在后台缓冲平面输出一些提示文字,最后将后台缓冲平面的内容贴到主平面上。

为完成下面的程序,首先要在你的工程文件的目录下建立一个名字为Demo.bmp的位图文件最为背景和一个名字为Sprite.bmp的位图作为角色位图。在Form1中加入一个ListBox控件和两个CommandButton控件。加入Directx7说明库,然后在Form1的代码窗口中添加以下的代码:

OptionExplicitDimobjDxAsNewDirectX7DimobjDrawAsDirectDraw7DimobjEnumModesAsDirectDrawEnumModesDimMainSurfAsDirectDrawSurface7DimBackSurfAsDirectDrawSurface7DimBmpSurfAsDirectDrawSurface7DimSpriteSurfAsDirectDrawSurface7DimddsdAsDDSURFACEDESC2Dimddsd1AsDDSURFACEDESC2Dimddsd2AsDDSURFACEDESC2Dimddsd3AsDDSURFACEDESC2Dimddsd4AsDDSURFACEDESC2Dimddsd5AsDDSURFACEDESC2DimbRunAsBooleanDimlastTimeAsLongDimfpsAsLongDimlfpsAsLongDimFrameCountAsLongDimClipperAsDirectDrawClipperDimxAsDDPIXELFORMATDimsx,syAsIntegerDimPict()AsByteSubInitSurf()OnErrorGoToErrHandler'设置主绘图平面的属性ddsd1.lFlags=DDSD_CAPSOrDDSD_BACKBUFFERCOUNTddsd1.lBackBufferCount=1ddsd1.ddsCaps.lCaps=DDSCAPS_COMPLEXOrDDSCAPS_FLIPOrDDSCAPS_PRIMARYSURFACE'设置缓冲绘图平面的属性ddsd2.ddsCaps.lCaps=DDSCAPS_BACKBUFFER'根据ddsd1建立主绘图平面SetMainSurf=objDraw.CreateSurface(ddsd1)'将BackSurf设置为MainSurf的附加平面SetBackSurf=MainSurf.GetAttachedSurface(ddsd2.ddsCaps)'设置背景绘图平面的字体和颜色BackSurf.SetForeColorRGB(255,255,255)Form1.Font.Name="宋体"BackSurf.SetFontForm1.Font'获得缓冲绘图平面的属性并设置到ddsd4中BackSurf.GetSurfaceDescddsd4'设置图形绘图平面的属性ddsd3.lFlags=DDSD_CAPSOrDDSD_HEIGHTOrDDSD_WIDTHddsd3.ddsCaps.lCaps=DDSCAPS_OFFSCREENPLAINddsd3.lWidth=ddsd4.lWidthddsd3.lHeight=ddsd4.lHeight'建立图形绘图平面SetBmpSurf=objDraw.CreateSurfaceFromFile(App.Path+"\demo.bmp",ddsd3)'设定角色位图平面的属性ddsd5.lFlags=DDSD_CAPSddsd5.ddsCaps.lCaps=DDSCAPS_OFFSCREENPLAIN'建立角色位图平面SetSpriteSurf=objDraw.CreateSurfaceFromFile(App.Path+"\sprite.bmp",ddsd5)DimkeyAsDDCOLORKEY'设定透明色(在这里设定为0,黑色)key.low=0key.high=0SpriteSurf.SetColorKeyDDCKEY_SRCBLT,keysx=20:sy=20lastTime=objDx.TickCountWhileTrueDoEventsBltWendErrHandler:SelectCaseErr.NumberCase0'NoErrorsCaseElse'错误退出CallCleanupEndSelectEndSubSubBlt()DimmrectScreenAsRECTDimsTimePassAsSingleDimsFramePerSAsSingle'以黑色清除并填充后台绘图平面BackSurf.BltColorFillmrectScreen,0'获得背景位图平面的矩形区域的尺寸mrectScreen.Right=ddsd2.lWidthmrectScreen.Bottom=ddsd2.lHeight'将图形绘图平面中的内容复制到后台绘图平面上CallBackSurf.BltFast(0,0,BmpSurf,mrectScreen,DDBLTFAST_WAIT)'获得前景角色位图平面的矩形区域mrectScreen.Right=ddsd5.lWidthmrectScreen.Bottom=ddsd5.lHeight'将前景角色位图复制到后台绘图平面上。CallBackSurf.BltFast(sx,sy,SpriteSurf,mrectScreen,DDBLTFAST_SRCCOLORKEY)sx=sx+2:sy=sy+2Ifsx>400Thensx=20Ifsy>400Thensy=20'在后台绘图平面上输出文本BackSurf.DrawText30,30,"ThisismyfirstDirectXprogram",FalseBackSurf.DrawText30,60,"点击屏幕退出程序",False'获得每秒的播放帧数。FrameCount=FrameCount+1sTimePass=(objDx.TickCount-lastTime)/1000IfsTimePass>0.5ThensFramePerS=FrameCount/sTimePassEndIfBackSurf.DrawText30,90,"每秒帧数:"+Format$(sFramePerS,"##00.0"),False'将后台绘图平面上的内容翻转到前台来MainSurf.FlipNothing,DDFLIP_WAITEndSubPrivateFunctionSetNewDisplayMode()OnErrorGoToErrHandlerDimiAsLongi=List1.ListIndexIfi=-1ThenMsgBox"请在列表中选择一种显示模式",vbOKOnly,"错误"ExitFunctionEndIf'获得用户选择的显示模式objEnumModes.GetItem(i+1),ddsd'设置协作模式objDraw.SetCooperativeLevelMe.hWnd,DDSCL_FULLSCREENOrDDSCL_ALLOWMODEX_OrDDSCL_EXCLUSIVE'设置显示模式objDraw.SetDisplayModeddsd.lWidth,ddsd.lHeight,ddsd.ddpfPixelFormat.lRGBBitCount,_0,DDSDM_DEFAULTMe.RefreshErrHandler:SelectCaseErr.NumberCase0'NoErrorsCaseElseErr.RaiseErr.Number,Err.Source,Err.Description,Err.HelpContext,_Err.HelpContextCallCleanupEndSelectEndFunctionSubCleanup()'Cleanup函数回复屏幕并且清除DirectX对象CallobjDraw.RestoreDisplayModeCallobjDraw.SetCooperativeLevel(Me.hWnd,DDSCL_NORMAL)SetobjDraw=NothingSetobjDx=NothingEndEndSubPrivateSubCommand1_Click()EndEndSubPrivateSubCommand2_Click()DimiFori=0ToForm1.Controls.Count-1Form1.Controls(i).Visible=FalseNextiSetNewDisplayModeInitSurfEndSubPrivateSubForm_Click()CleanupEndSubPrivateSubForm_Load()Command1.Caption="结束"Command2.Caption="设置显示模式"OnErrorGoToErrHandler:DimddsdAsDDSURFACEDESC2DimiAsLong,lgCountAsLongSetobjDx=NewDirectX7'建立DirectDraw对象SetobjDraw=objDx.DirectDrawCreate("")'将DirectDraw对象支持的显示模式设置到DirectDrawEnumModes对象中SetobjEnumModes=objDraw.GetDisplayModesEnum(DDEDM_DEFAULT,ddsd)'将数据设置到ListBox中lgCount=objEnumModes.GetCount()Fori=1TolgCountobjEnumModes.GetItemi,ddsdList1.AddItemCStr(ddsd.lWidth)&"x"&CStr(ddsd.lHeight)&"x"_&CStr(ddsd.ddpfPixelFormat.lRGBBitCount)NextiErrHandler:SelectCaseErr.NumberCase0'没有错误CaseElseErr.RaiseErr.Number,Err.Source,Err.Description,Err.HelpContext,_Err.HelpContextCallCleanupEndSelectEndSub现在程序全部完成了,运行程序,点击列表中的任意显示模式,然后点击"设置显示模式"按钮,可以看到位图被显示在屏幕上并且在屏幕上显示出程序中的文本。

上面的程序比较简单,但是包含了基本的DirectDraw的应用,下面来分析一下:

首先通过DirectX7的DirectDrawCreate方法建立一个DirectDraw对象,然后通过GetDisplayModesEnum方法获得DirectDraw对象支持的显示模式,当选择某一种显示模式之后,调用DirectDraw对象的SetDisplayMode方法设置所选择的显示模式。

接下来是设置绘图平面,如果对于游戏编程有一些了解的朋友都会知道,为了不使在游戏的图像切换时发生闪烁,我们一般需要设置一个后台绘图平面,对所有的画面首先在后台缓冲平面上做所需要的处理,然后再将它翻转到前台来。从上面的程序可以看到,在程序中一共设置了三个不同的绘图平面:MainSurf、BackSurf、BmpSurf、SpriteSurf。MainSurf是主绘图平面,是程序运行时可以看到的部分;而BackSurf是后台绘图平面;BmpSurf是背景位图平面;SpriteSurf是角色位图平面。我们使用MainSurf的GetAttachedSurface方法将BackSurf设置为MainSurf的附加平面,所有的图形操作首先在在BackSurf上进行,然后在翻转到主平面上来。BmpSurf在程序中利用DirectDraw的CreateSurfaceFromFile函数被设置为一个包含位图的绘图平面。SpriteSurf也做同样的设定,但是为了使只有角色显示出来而无关的部分不显示,我们需要设置SpriteSurf的ColorKey,在上面设置为0黑色,即在粘贴图像时Sprite.bmp中的黑色部分不会显示出来。然后建立一个无限循环,在每个循环内首先将BmpSurf上的位图转贴到BackSurf上,然后在BackSurf上输出文字,等在BackSurf上的操作全部完成之后,再利用MainSurf的Flip方法将后台绘图平面的内容翻转到前台平面上来。读者需要注意的是这四个绘图平面的不同属性(从ddsd1到ddsd5)。

二、Direct3D

Direct3D类对象可以说是DirectX下最重要的同时也是最复杂的对象集合。基本说来,Direct3D可以分为立即模式(ImmediateMode)和保留模式(RetainedMode)。其中保留模式是一种高级3DAPI编程接口,它是为需要快速开发Direct3D应用的程序员所准备的。而立即模式是一种低级3DAPI编程接口,它为需要开发高性能游戏或者多媒体应用的程序员提供了在较低级别上同图形加速硬件打交道的与设备无关的接口。Direct3D的保留模式是建立在立即模式基础之上的,如下图所示:

由上面的图可以看到。Direct3D的立即模式同图形加速硬件之间的结合比较紧密,性能比较高,适合于开发三维游戏。而Direct3D的保留模式具有层次性,可移植性比较的好,可以用于开发商业的三维应用程序(例如设备展示等)。

要建立一个Direct3D应用,首先要建立Direct3D7对象,利用DirectDraw7对象的GetDirect3D方法可以获得一个Direct3D7对象。利用Direct3D7对象可以建立Direct3D对象以及设置三维环境。

利用Direct3D7对象的CreateDevice方法可以建立一个Direct3DDevive7对象,你可以将一个Direct3DDevice7对象想象为一个电影场景,你可以向场景中布置演员(3D对象)、给每个演员安排服装(纹理设置)、设置灯光(光照效果)、设置摄影机(设置视角)。

下面通过一个具体的程序来说明Direct3D立即模式的基本原理

首先建立一个新的工程并保存,为了给三维对象加上纹理,我们需要在工程目录下建立三个位图文件,文件名分别是t1.bmp、t2.bmp、t3.bmp,位图的尺寸要设置为128*128或者256*256像素,将DirectX7说明库加入到工程文件中。然后在Form1中加入以下代码:

OptionExplicitConstpiAsSingle=3.141592ConstNUM_CUBE_VERTICESAsInteger=4*6Dimg_vCube(NUM_CUBE_VERTICES)AsD3DVERTEX'定义三个材质表面DimTextureSurface1AsDirectDrawSurface7DimTextureSurface2AsDirectDrawSurface7DimTextureSurface3AsDirectDrawSurface7Dimg_dxAsNewDirectX7Dimg_ddAsDirectDraw7Dimg_ddsdAsDDSURFACEDESC2DimMainBufferAsDirectDrawSurface7DimBackBufferAsDirectDrawSurface7DimDirect3DDeviceAsDirect3DDevice7Dimg_rcDestAsRECT,g_rcSrcAsRECTDimViewPortRect(0)AsD3DRECTDimbIsRunningAsBooleanDimbRoAnAsBooleanDimCNTAsSingleDimiViewSizeAsIntegerPrivateSubForm_KeyDown(KeyCodeAsInteger,ShiftAsInteger)'根据不同的击键值来决定角度的变化SelectCaseKeyCodeCasevbKeyUpCNT=CNT+6bRoAn=TrueCasevbKeyDownCNT=CNT-6bRoAn=TrueCasevbKeyLeftCNT=CNT+6bRoAn=FalseCasevbKeyRightCNT=CNT-6bRoAn=FalseCasevbKeySubtractIfiViewSize<12TheniViewSize=iViewSize+1EndIfCasevbKeyAddIfiViewSize>4TheniViewSize=iViewSize-1EndIfEndSelectEndSubPrivateSubForm_Load()DimjAsLongInitDDrawInitD3DInitDeviceObjectsMe.ShowbIsRunning=TrueDoWhilebIsRunning=TrueRenderSceneFrameMove(CNT/360),bRoAng_dx.GetWindowRectMe.hWnd,g_rcDest'将后台绘图平面的内容复制到前台j=MainBuffer.Blt(g_rcDest,BackBuffer,g_rcSrc,DDBLT_WAIT)Ifj<>DD_OKThenMsgBox"无法将后台绘图平面的内容拷贝到前台,错误代码:"&Hex(j)EndEndIfDoEventsLoopEndSubPrivateSubFrameMove(stepValAsSingle,bTypeAsBoolean)DimmatViewAsD3DMATRIXDimmatTempAsD3DMATRIX'建立线形矩阵g_dx.IdentityMatrixmatView'matView.rc11=Cos(0.5)'matView.rc12=Sin(0.5)'matView.rc21=Sin(-0.5)'matView.rc22=Cos(0.5)'matView.rc33=1'matView.rc43=iviewsize'你可以尝试将下面5句注释掉而使用上面5句进行视矩阵变换,看有什么效果matView.rc11=1matView.rc22=Cos(-0.5)matView.rc23=Sin(-0.5)matView.rc32=-Sin(-0.5)matView.rc33=Cos(-0.5)matView.rc43=iViewSize'对视矩阵进行角度变换Direct3DDevice.SetTransformD3DTRANSFORMSTATE_VIEW,matViewDimmatWorldAsD3DMATRIXg_dx.IdentityMatrixmatWorldIfbTypeTheng_dx.RotateXMatrixmatWorld,stepValElseg_dx.RotateYMatrixmatWorld,stepValEndIfDirect3DDevice.SetTransformD3DTRANSFORMSTATE_WORLD,matWorldEndSub'RenderScene函数执行场景重绘和渲染PrivateSubRenderScene()DimiAsInteger'将整个视界背景设置为蓝色,并清除Z缓冲Direct3DDevice.Clear1,ViewPortRect(),D3DCLEAR_TARGET,&HFF,1,0'开始绘制场景Direct3DDevice.BeginScene'将TextureSurface1设置为Direct3DDevice的纹理平面Direct3DDevice.SetTexture0,TextureSurface1'使用TextureSurface1作为纹理绘制g_vCube(0)到g_vCube(3)顶点之间的平面,CallDirect3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_VERTEX,g_vCube(0),_4,D3DDP_DEFAULT)'使用TextureSurface1作为纹理绘制g_vCube(4)到g_vCube(7)顶点之间的平面,CallDirect3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_VERTEX,g_vCube(4),_4,D3DDP_DEFAULT)'将TextureSurface2设置为Direct3DDevice的纹理平面Direct3DDevice.SetTexture0,TextureSurface2'使用TextureSurface2作为纹理绘制g_vCube(8)到g_vCube(11)顶点之间的平面,CallDirect3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_VERTEX,g_vCube(8),_4,D3DDP_DEFAULT)'使用TextureSurface2作为纹理绘制g_vCube(12)到g_vCube(15)顶点之间的平面,CallDirect3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_VERTEX,g_vCube(12),_4,D3DDP_DEFAULT)'将TextureSurface3设置为Direct3DDevice的纹理平面Direct3DDevice.SetTexture0,TextureSurface3'使用TextureSurface3作为纹理绘制g_vCube(16)到g_vCube(19)顶点之间的平面,CallDirect3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_VERTEX,g_vCube(16),_4,D3DDP_DEFAULT)'使用TextureSurface3作为纹理绘制g_vCube(20)到g_vCube(23)顶点之间的平面,CallDirect3DDevice.DrawPrimitive(D3DPT_TRIANGLESTRIP,D3DFVF_VERTEX,g_vCube(20),_4,D3DDP_DEFAULT)'结束绘制场景Direct3DDevice.EndSceneEndSubPrivateSubForm_Unload(CancelAsInteger)bIsRunning=FalseEndSub'InitDDraw函数初始化DirectDraw对象,包括建立主绘图平面以及后台绘图平面PrivateSubInitDDraw()'建立DirectDraw对象Setg_dd=g_dx.DirectDrawCreate("")'设定DirectDraw对象的协作模式g_dd.SetCooperativeLevelMe.hWnd,DDSCL_NORMAL'预先定义主绘图平面的属性g_ddsd.lFlags=DDSD_CAPSg_ddsd.ddsCaps.lCaps=DDSCAPS_PRIMARYSURFACE'建立主绘图平面SetMainBuffer=g_dd.CreateSurface(g_ddsd)g_ddsd.lFlags=DDSD_HEIGHTOrDDSD_WIDTHOrDDSD_CAPSg_ddsd.ddsCaps.lCaps=DDSCAPS_OFFSCREENPLAINOrDDSCAPS_3DDEVICEg_dx.GetWindowRectMe.hWnd,g_rcDestg_ddsd.lWidth=g_rcDest.Right-g_rcDest.Leftg_ddsd.lHeight=g_rcDest.Bottom-g_rcDest.Top'建立后台绘图平面SetBackBuffer=g_dd.CreateSurface(g_ddsd)'将后台绘图平面的尺寸保存到g_rcSrc中Withg_rcSrc.Left=0:.Top=0.Bottom=g_ddsd.lHeight.Right=g_ddsd.lWidthEndWithDimpcClipperAsDirectDrawClipperSetpcClipper=g_dd.CreateClipper(0)pcClipper.SetHWndMe.hWndMainBuffer.SetClipperpcClipperEndSub'InitD3D函数初始化Direct3D对象,包括3D设备、光源、视角以及材质SubInitD3D()Dimd3dAsDirect3D7DimddsdAsDDSURFACEDESC2'从DirectDraw对象中获得Direct3D对象Setd3d=g_dd.GetDirect3D'获得DirectDraw对象的显示颜色深度,如果小于16位色,则程序出错退出g_dd.GetDisplayModeddsdIfddsd.ddpfPixelFormat.lRGBBitCount<=8ThenMsgBox"本程序不支持颜色位数小于16bit的显示模式,程序将退出"EndEndIfOnErrorResumeNext'首先尝试建立硬件3维设备对象(HAL)SetDirect3DDevice=d3d.CreateDevice("IID_IDirect3DHALDevice",BackBuffer)'如果Direct3DDevice为Nothing说明显示卡不支持硬件Direct3D设备'尝试建立RGB3维设备。IfDirect3DDeviceIsNothingThenSetDirect3DDevice=d3d.CreateDevice("IID_IDirect3DRGBDevice",BackBuffer)EndIf'定义视角区域DimVPDescAsD3DVIEWPORT7VPDesc.lWidth=g_rcDest.Right-g_rcDest.LeftVPDesc.lHeight=g_rcDest.Bottom-g_rcDest.TopVPDesc.minz=0#VPDesc.maxz=1#'设置Direct3DDevice对象的视角Direct3DDevice.SetViewportVPDesc'保存对视角的设置WithViewPortRect(0).X1=0:.Y1=0.X2=VPDesc.lWidth.Y2=VPDesc.lHeightEndWithiViewSize=4EndSub'InitDeviceObjects函数建立三维物体PrivateSubInitDeviceObjects()'建立立方体的顶点数据CreateCubeg_vCube'通过位图文件建立三个纹理表面SetTextureSurface1=CreateTextureSurface("t1.bmp")SetTextureSurface2=CreateTextureSurface("t2.bmp")SetTextureSurface3=CreateTextureSurface("t3.bmp")'使用泛光源以及白色的普通材质DimmtrlAsD3DMATERIAL7'定义材质对光源的的反射属性,你可以尝试改变它们的值看一下材质'的反射效果mtrl.diffuse.r=1#:mtrl.diffuse.g=0#:mtrl.diffuse.b=1#mtrl.Ambient.r=1#:mtrl.Ambient.g=1#:mtrl.Ambient.b=1#:mtrl.Ambient.a=1mtrl.emissive.r=1#:mtrl.emissive.g=0#:mtrl.emissive.b=1#mtrl.emissive.r=1#:mtrl.specular.g=1#:mtrl.specular.b=1#'将材质的清晰度设置为10mtrl.power=10Direct3DDevice.SetMaterialmtrl'设置Direct3DDevice的光源为泛光源,你可以尝试对SetRenderState函数的'第一个参数使用不同的值,看看光源的效果。Direct3DDevice.SetRenderStateD3DRENDERSTATE_AMBIENT,_g_dx.CreateColorRGBA(1#,1#,0#,1#)DimmatProjAsD3DMATRIXg_dx.IdentityMatrixmatProjCallg_dx.ProjectionMatrix(matProj,1,1000,pi/4#)Direct3DDevice.SetTransformD3DTRANSFORMSTATE_PROJECTION,matProjEndSub'CreateCube函数建立立方体的顶点数据PrivateSubCreateCube(vertices()AsD3DVERTEX)'一个立方体有6个面,每面有是一个正方形,有4个顶点,下面共定义了'这6个面的24个顶点g_dx.CreateD3DVertex-1,1,-1,0,0,-1,0,0,vertices(0)g_dx.CreateD3DVertex1,1,-1,0,0,-1,1,0,vertices(1)g_dx.CreateD3DVertex-1,-1,-1,0,0,-1,0,1,vertices(2)g_dx.CreateD3DVertex1,-1,-1,0,0,-1,1,1,vertices(3)g_dx.CreateD3DVertex-1,1,1,0,0,1,1,0,vertices(4)g_dx.CreateD3DVertex-1,-1,1,0,0,1,1,1,vertices(5)g_dx.CreateD3DVertex1,1,1,0,0,1,0,0,vertices(6)g_dx.CreateD3DVertex1,-1,1,0,0,1,0,1,vertices(7)g_dx.CreateD3DVertex-1,1,1,0,1,0,0,0,vertices(8)g_dx.CreateD3DVertex1,1,1,0,1,0,1,0,vertices(9)g_dx.CreateD3DVertex-1,1,-1,0,1,0,0,1,vertices(10)g_dx.CreateD3DVertex1,1,-1,0,1,0,1,1,vertices(11)g_dx.CreateD3DVertex-1,-1,1,0,-1,0,0,0,vertices(12)g_dx.CreateD3DVertex-1,-1,-1,0,-1,0,0,1,vertices(13)g_dx.CreateD3DVertex1,-1,1,0,-1,0,1,0,vertices(14)g_dx.CreateD3DVertex1,-1,-1,0,-1,0,1,1,vertices(15)g_dx.CreateD3DVertex1,1,-1,1,0,0,0,0,vertices(16)g_dx.CreateD3DVertex1,1,1,1,0,0,1,0,vertices(17)g_dx.CreateD3DVertex1,-1,-1,1,0,0,0,1,vertices(18)g_dx.CreateD3DVertex1,-1,1,1,0,0,1,1,vertices(19)g_dx.CreateD3DVertex-1,1,-1,-1,0,0,1,0,vertices(20)g_dx.CreateD3DVertex-1,-1,-1,-1,0,0,1,1,vertices(21)g_dx.CreateD3DVertex-1,1,1,-1,0,0,0,0,vertices(22)g_dx.CreateD3DVertex-1,-1,1,-1,0,0,0,1,vertices(23)EndSubPublicFunctionCreateTextureSurface(sFileAsString)AsDirectDrawSurface7DimddsTextureAsDirectDrawSurface7DimiAsLongDimbIsFoundAsBooleanDimddsdAsDDSURFACEDESC2'定义纹理平面的属性ddsd.lFlags=DDSD_CAPSOrDDSD_HEIGHTOrDDSD_WIDTHOrDDSD_PIXELFORMAT_OrDDSD_TEXTURESTAGEDimTextureEnumAsDirect3DEnumPixelFormats'获得当前Direct3DDevice支持的所有纹理类型SetTextureEnum=Direct3DDevice.GetTextureFormatsEnum()'便历所有纹理类型,找到符合需要的类型Fori=1ToTextureEnum.GetCount()bIsFound=TrueCallTextureEnum.GetItem(i,ddsd.ddpfPixelFormat)Withddsd.ddpfPixelFormat'跳过不常使用的格式If.lFlagsAnd(DDPF_LUMINANCEOrDDPF_BUMPLUMINANCEOrDDPF_BUMPDUDV)ThenbIsFound=FalseEndIf'跳过FourCC格式If.lFourCC<>0ThenbIsFound=False'跳过Alpha模式纹理If.lFlagsAndDDPF_ALPHAPIXELSThenbIsFound=False'只使用16位颜色三维纹理,跳过其它的颜色设定If.lRGBBitCount<>16ThenbIsFound=FalseEndWithIfbIsFoundThenExitForNextiIfNotbIsFoundThenMsgBox"你的图形卡不支持16位颜色绘图平面"EndEndIfddsd.ddsCaps.lCaps=DDSCAPS_TEXTUREddsd.ddsCaps.lCaps2=DDSCAPS2_TEXTUREMANAGEddsd.lTextureStage=0sFile=App.Path+"\"+sFile'建立一个新的纹理绘图平面SetddsTexture=g_dd.CreateSurfaceFromFile(sFile,ddsd)'返回建立的纹理绘图平面SetCreateTextureSurface=ddsTextureEndFunction

运行程序,在窗口中会出现一个带贴图的立方体,按动上下左右方向键就可以向不同的方向滚动立方体,按动+、-键可以缩放立方体。

分析上面的程序,基本的实现过程大家可能已经有一些基本的了解,首先建立DirectX7对象,然后建立并初始化DirectDraw、再建立Direct3D对象。接下来利用CreateCube函数建立立方体框架,利用InitDeviceObjects函数为Direct3DDevice对象建立纹理、光照效果以及材质,利用RenderScene函数可以将不同的纹理赋予立方体不同的表面并将其绘制在DirectDrawSurface7对象。对于FrameMove函数中的内容可能大家不太了解。在Direct3D场景中有两个不同的坐标系,一个是以Direct3D场景的中心为坐标原点的坐标系,另外一个是以虚拟的观察者为中心的坐标系。在Direct3D世界中的对象的旋转、平移是通过改变对象的坐标系来实现的,D3DMATRIX对象定义了一个4*4的矩阵,Direct3D场景中的某一点到另外一点的变换是使用如下公式来进行的:

展开如下:

其中x'、y'、z'为新坐标。FrameMove函数中的SetTransform方法就是根据D3DMATRIX对象定义的4*4的矩阵进行坐标系变换的函数。另外作者还编写了一个平移对象的FrameMove函数,函数如下:

PrivateSubFrameMove(stepValAsSingle,bTypeAsBoolean)DimmatViewAsD3DMATRIXDimmatWorldAsD3DMATRIX'建立线形矩阵g_dx.IdentityMatrixmatViewmatView.rc11=1matView.rc22=Cos(-0.5)matView.rc23=Sin(-0.5)matView.rc32=-Sin(-0.5)matView.rc33=Cos(-0.5)matView.rc43=iViewSizeIfbTypeTheng_dx.RotateXMatrixmatView,stepValElseg_dx.RotateYMatrixmatView,stepValEndIfDirect3DDevice.SetTransformD3DTRANSFORMSTATE_VIEW,matViewg_dx.IdentityMatrixmatWorldmatWorld.rc11=1matWorld.rc22=Cos(-0.5)matWorld.rc23=Sin(-0.5)matWorld.rc32=-Sin(-0.5)matWorld.rc33=Cos(-0.5)matWorld.rc43=iViewSizeDirect3DDevice.SetTransformD3DTRANSFORMSTATE_WORLD,matWorldEndSub

你可以将这个函数代入上面的程序运行,程序运行时首先按-键将立方体缩小,然后按动上下左右键看立方体是如何平移的。

接下来介绍Direct3D保留模式对象编程,由于Direct3D保留模式对象比较多而且相对立即模式使用起来比较简单,我们就来直接切入程序。

建立一个新的工程文件,保存文件,为了添加纹理,你需要在工程文件所在目录下建立一个名字为glass.bmp的位图文件。加入DirectX7说明库,然后在Form1的代码窗口中假如以下代码:

OptionExplicitDimg_dxAsNewDirectX7Dimg_ddAsDirectDraw4DimpcClipperAsDirectDrawClipperDimg_ddsdAsDDSURFACEDESC2DimMainBufferAsDirectDrawSurface4DimBackBufferAsDirectDrawSurface4'Direct3DRM对象DimD3DRMAsDirect3DRM3'三维设备对象DimRMDeviceAsDirect3DRMDevice3'三维视区对象DimRMViewPortAsDirect3DRMViewport2'三维场景对象DimRMFrameSceneAsDirect3DRMFrame3DimRMFrameCameraAsDirect3DRMFrame3DimRMFrameDirLightAsDirect3DRMFrame3DimRMFrameAmbientLightAsDirect3DRMFrame3'光源对象DimRMDirLightAsDirect3DRMLightDimRMAmbientLightAsDirect3DRMLight'Direct3DRMMeshBuilder3对象是提供与mesh对象象交互作用的对象'一个mesh对象是一个由多个多边形组成德多面体DimmeshboxAsDirect3DRMMeshBuilder3DimframeboxAsDirect3DRMFrame3Dimg_rcDestAsRECT,g_rcSrcAsRECTSubCleanUp()Err.ClearOnLocalErrorResumeNextSetRMFrameCamera=NothingSetRMFrameScene=NothingSetRMFrameDirLight=NothingSetRMFrameAmbientLight=NothingSetRMDirLight=NothingSetRMAmbientLight=Nothingg_dd.RestoreDisplayModeg_dd.SetCooperativeLevelMe.hWnd,DDSCL_NORMALSetBackBuffer=NothingSetMainBuffer=NothingSetg_dd=NothingSetRMViewPort=NothingSetRMDevice=NothingEndSubPrivateSubInitDDraw()SetRMViewPort=NothingSetRMDevice=Nothing'建立DirectDraw对象Setg_dd=g_dx.DirectDraw4Create("")'设定DirectDraw对象的协作模式g_dd.SetCooperativeLevelMe.hWnd,DDSCL_NORMAL'预先定义主绘图平面的属性g_ddsd.lFlags=DDSD_CAPSg_ddsd.ddsCaps.lCaps=DDSCAPS_PRIMARYSURFACE'建立主绘图平面SetMainBuffer=g_dd.CreateSurface(g_ddsd)SetpcClipper=g_dd.CreateClipper(0)pcClipper.SetHWndMe.hWndMainBuffer.SetClipperpcClipperg_dx.GetWindowRectMe.hWnd,g_rcDestg_ddsd.lFlags=DDSD_HEIGHTOrDDSD_WIDTHOrDDSD_CAPSg_ddsd.ddsCaps.lCaps=DDSCAPS_OFFSCREENPLAINOrDDSCAPS_3DDEVICEg_dx.GetWindowRectMe.hWnd,g_rcDestg_ddsd.lWidth=g_rcDest.Right-g_rcDest.Leftg_ddsd.lHeight=g_rcDest.Bottom-g_rcDest.Top'建立后台绘图平面SetBackBuffer=g_dd.CreateSurface(g_ddsd)EndSub'InitS函数设定三维场景SubInitS()SetD3DRM=g_dx.Direct3DRMCreate'建立三维场景SetRMFrameScene=D3DRM.CreateFrame(Nothing)'建立相机SetRMFrameCamera=D3DRM.CreateFrame(RMFrameScene)'设置相

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论