×

vb.net对 directx 的管理办法

Kalet Kalet 发表于2009-03-20 12:00:14 浏览351 评论0

抢沙发发表评论

vb.net对 directx 的管理办法(一)


译:newmoon


不发翻译的原文了,是因为个人水平的关系.现在把我理解的部分写出来,请高手指教正确与否!

vb.net对 directx 的管理办法

direct3d 9.0 有两种使用方法,一是传统的api调用(适用于c++),二是提供管理代码的接口(所有的.net语言),以下用的都是第二种方法.代码用vb.net实现.


至于这两种办法的优劣,不做过多的解释,我们重点要说明的是如何使用d3d9,它没有必要,也不可能是最好的.


管理代码是微软一个新的做法,它是基础于使用CLR,它比c/c++更高级。CLR实现有效的存储分配和垃圾回收,所以我们不必担心内存的管理,类或者模块的生命周期。


我们需要准备的工具:


1、编程工具


编程需要一个好的IDE,我们需要Visual Studio.Net 2002软件,确保下载并安装在你的系统上,当然你可以仅仅下载你需要的工具,如C#或者vb.net。


2、directx 9.0 sdk


directx有两个版本,用户版和工具包(sdk),可以从micrsoft.com下载,大约有200-250mb硬盘空间。安装之前,你必须要注意的是,要保证首先安装了.net框架,只有这样direct才安装管理代码部件,如果你安装顺序错了,你


只能开发c/c++ 应用程序。


vb.net对 directx 的管理办法(二)


原文很罗嗦,我简单介绍一下:directx 和3d基础


directx是微软开发的游戏和多媒体的基础的一个库!我们需要知道是:


一、它提供一个抽象的方法去使用任何一个pc的图形硬件。(简单说,就是我们不必为每个不同显卡改编程序,也不需要知道究竟你机子和你用户机子的显卡有什么不同)


二、快速绘制一个复杂的3d图象。(简单说,就是利用现代高性能的显卡来完成我们需要复杂图形的绘制和渲染)


三、渲染交互的、动画的3d场景犯法。(简单说,3d场景不是孤立的,是可以使用directx来帮助我们交互控制和产生动画效果。)


以上部分原文写了满满两页,我总结如上,高手请指教。


3d基础


这是个复杂的课题,需要熟悉几何学、面、矢量、矩阵、线形方程等等,我们仅仅来解释我们变成需要的部分。


3d世界空间


最重要的概念,我们的2d 屏幕有宽和高:x和y,3d增加深度z,我们在内存中创造一个点(x,y,z),并使用d3d和图形硬件使用各种算法把它表示为屏幕上的一个点(x,y).


简单的几何学


任何一个顶点的位置数据很简单(x,y,z),我们需要把灯光、材质和颜色等扩充的信息放在这个特殊的位置上,


三个顶点组成一个三角形,所有的物体和网格都是由这样的三角形组成。


材质:有了这些三角形,物体就有了形状,我们利用材质提供它材料、材质、模式等等信息,材质是2d的图象(位图存储),然后我们象贴墙纸一样把它贴在有了形状的物体上。


转换:


是个比较复杂的话题,我们现在知道的仅仅是3d图形被放在2d的屏幕上是一种转换,物体的移动、缩放、旋转也是转换的结果。等等吧,后面在详细说。


模型和网格


术语的网格和模型经常通用。比如游戏一个角色就是一个组织好的网格。它可能是有很多简单的几何体(方体、球体)来组合的,可以用数学方程来表示,也可能是一个永远不可能被数学方程表示的的物体。


原文内容我提炼了一小部分。因为它真的太罗嗦了,以后写的也是这样。


vb.net 对directx 管理方法(三)


强烈建议你到www.directx4vb.com下载源代码!


我们开始工作,我们的目的是绘制两个在屏幕中旋转的立方体,并且有个文字的菜单在屏幕上显示.重点是我们设计了一个简单的图形引擎来完成它.后面的时间我们一行一行来解释它,所以你最好能先下载源代码.(个人认为,程序不是主要的,这个程序中涉及的3d管理方法是很不错的)


在我们开始输入代码前,必须要加入相关的基库,在.net的任何语言都需要相同的步骤,project>>add reference 选择(如果安装direct sdk后会有相关选项)


Microsoft.DirectX


Microsoft.Directx.direct3d


Microsoft.DirectX.direct3dx


最后在你的应用程序中,每个你使用 directx函数的窗口和模块中都加入相关的库


Imports Microsoft.DirectX


Imports Microsoft.DirectX.Direct3D


Imports System.Math


(在着本书里没有写下个步骤,但我在其它书里看到了这个步骤,我认为很重要,顺便说说,请高手指教,似乎这上面的步骤和下面的步骤作用相同,任选一个即可)


导入命名空间


在你的项目右键->属性,在导入栏中分别输入Microsoft.DirectX,Microsoft.DirectX.Direct3D,并增加它们.


下面先写出CSampleGraphicsEngine类的的代码,后面我会一步一步说明也先看看英文的注释,我会详细的说明的)


'[--------------------------------------------------------------]


'


' NAME: CSampleGraphicsEngine


' AUTHOR: Jack Hoxley


' CONTACT: mailto:Jack.Hoxley@DirectX4VB.com


' http://www.DirectX4VB.com


'


' DATE: 16th December 2002 (started)


' 21st December 2002 (finished)


'


' NOTES:


' This is a relatively simple graphics library designed


' for learning from - it'll work fine for small-medium


' projects, but it's far from a complete solution.


'


' You're free to use/disect this class for your own


' projects, although a little credit for the original


' work wouldn't hurt!


'


'[--------------------------------------------------------------]


'these two imports bring all of the classes, types and


'objects that we need to write our application.


Imports Microsoft.DirectX


Imports Microsoft.DirectX.Direct3D


'a useful import for any multimedia-based application


Imports System.Math


...


vb.net 对directx 管理方法(四)


我们开始讨论第一部分:初始化及构造函数


先理论,后实践了!


我们有两种方法建立一个direct3d设备,窗口模式和全屏模式,概念我就不说详细说了吧,一般的游戏都是全屏模式,一般的应用程序都是窗口模式.


看看这个函数吧!


Public Shared Function isDisplayModeOkay(ByVal iWidth As Integer, _


ByVal iHeight As Integer, _


ByVal iDepth As Integer _


) As Boolean


Try


'this covers the most commonly used display modes


'only. others exist and are used for more specific cases


Dim AdapterInfo As AdapterInformation


Dim DispMode As DisplayMode


Dim fmt As Format


Dim D3Dr As Manager


Select Case iDepth


Case 16


fmt = Format.R5G6B5


Case 32


fmt = Format.X8R8G8B8


End Select


For Each AdapterInfo In D3Dr.Adapters


For Each DispMode In AdapterInfo.SupportedDisplayModes(fmt)


If DispMode.Width = iWidth Then


If DispMode.Height = iHeight Then


Return True


End If


End If


Next


Next


Throw New Exception("No compatable resolution was found")


'errors are caught silently, no real need


'to inform the user as to whether the resolution


'is supported or not. The caller can do that.


Catch DXErr As DirectXException


Return False

vb.net对 directx 的管理办法

Catch Err As Exception


Return False


End Try


End Function


这个函数是检查我们的硬件是否支持我们需要的模式,如果需要更多的模式,我们就增加相应的case好了,这里只给出了两种常用的,


程序很简单,我们讲讲模式的定义.我们的计算机显示图形的时候必须给它指定分辨率(屏幕是宽和高分别是由多少点组成的),还有色深.


分辨率好理解,我们一般使用400*300,或者800*600等等,


看看我们关心的,也是不好理解的:


R5R6B5 -16 位


分开就是RRRRRGGGGGGBBBBB


X8R8G8B8


分开就是XXXXXXXXRRRRRRRRBBBBBBBB


好了,每个符号代表一bit,x是没有使用的内存,r是红色,b是兰色, G是绿色.就是我们通常所说的16位和32位颜色了.


在桌面空白处上右键,选属性->设置,看看你自己的计算机支持什么模式.毫无疑问,我们选择色深越大,分辨率越高,画面的质量越好,但越占用内存,一个1024*768*32 的模式,每屏幕就需要的内存是3mb.(想完成流畅的动画>>>夸张)


好了,看看构造函数吧,我们一共做了两个可覆盖的函数(区别于参数的数量,看仔细),一个窗口模式.


Public Sub New(ByVal Target As System.Windows.Forms.Form)


Try


Dim d3dPP As New PresentParameters()


d3dPP.Windowed = True : bWindowed = True


d3dPP.SwapEffect = SwapEffect.Discard


d3dPP.BackBufferCount = 1


d3dPP.BackBufferFormat = D3DRoot.Adapters(0).CurrentDisplayMode.Format


d3dPP.BackBufferWidth = Target.ClientSize.Width()


d3dPP.BackBufferHeight = Target.ClientSize.Height()


sDispInfo = "[WINDOWED] " + _


Target.ClientSize.Width.ToString + "x" + _


Target.ClientSize.Height.ToString + " " + d3dPP.BackBufferFormat.ToString()


rTarget = Target


initialiseDevice(CType(Target, System.Windows.Forms.Control), d3dPP)


Catch err As Exception


bInitOkay = False


'you can examine 'err' and/or output that error, but I don't want


'the calling application to get much info about the internal state of the engine.


'for now, we'll just throw an exception that'll fall back to the caller


Throw New Exception("Could not initialise graphics engine.")


End Try


End Sub


一个是全屏模式:


Public Sub New(ByVal Target As System.Windows.Forms.Form, _


ByVal iWidth As Integer, _


ByVal iHeight As Integer, _


ByVal iDepth As Integer _


)


Try


Dim d3dPP As New PresentParameters()


If Not isDisplayModeOkay(iWidth, iHeight, iDepth) Then


Throw New Exception("Could not verify that the selected " _


+ "resolution is compatable with the hardware")


End If


bWindowed = False


d3dPP.BackBufferWidth = iWidth


d3dPP.BackBufferHeight = iHeight


d3dPP.BackBufferCount = 1


d3dPP.SwapEffect = SwapEffect.Copy


d3dPP.PresentationInterval = PresentInterval.Immediate


Select Case iDepth


Case 16


d3dPP.BackBufferFormat = Format.R5G6B5


sDispInfo = "[Fullscreen] " + iWidth.ToString + "x" + iHeight.ToString + " 16bit R5G6B5"


Case 32


d3dPP.BackBufferFormat = Format.X8R8G8B8


sDispInfo = "[Fullscreen] " + iWidth.ToString + "x" + iHeight.ToString + " 32bit X8R8G8B8"


Case Else


Throw New Exception("iDepth does not contain a valid value, only 16 or 32 is acceptable")


End Select


rTarget = Target


initialiseDevice(CType(Target, System.Windows.Forms.Control), d3dPP)


Catch err As Exception


bInitOkay = False


'you can examine 'err' and/or output that error, but I don't want


'the calling application to get much info about the internal state of the engine.


'for now, we'll just throw an exception that'll fall back to the caller


Throw New Exception("Could not initialise graphics engine")


End Try


End Sub


调用的时候看你的参数,如果只给了窗口的句柄,就是窗口模式,如果指定详细的分辨率(宽和高)和色深,就是全屏了!


我们在看看下面这个过程,无论哪个构造函数被调用后,后面过程都是一样的我们放在初始化这个方法里.这里我们走了7个步骤:


1\确定显示模式和格式


2\设置深度缓冲


3\列举所有额外选项


4\实际上创建设备,并且检查


5\设置绘制的状态


6\设置初始转换矩阵.


看好源代码,我们下节慢慢来说,累了,我先吃饭去了!


vb.net 对directx 管理方法(五)


先小小的理论,不要晕,没有理论,是看不懂代码的,再次提醒大家,如果你英文水平好的话,建议你去全文在www.directx4vb.com 上有,我写的东西是大大精简的内容,不是全文的翻译,我在整理,全文的翻译,如果有人要的话,请联系我!qq:71022501!共同研究,共同理解了!


我们程序设计到的几种缓冲所谓缓冲,就是内存的一个段落,有自己的格式和大小)


一\u21518后台缓冲:后台缓冲是一种技术,为了不把我们绘制一个一个三角形的过程暴露给用户,如果你要这么做,会出现停顿和闪烁,所以我们在绘制的每个帧隐藏在一个后台的内存中,这个内存和前台缓冲(既我们看到的屏幕画面的内存)大小格式完全一样,当所有的绘制动作完成的时候,我们将后台变成前台!这样就象一个雕刻家用帆布盖做没有完成的雕像,直到所有工作完了,再取掉帆布!


深度缓冲和z缓冲


当我们去看一个正方形的盒子,一般只有面对我们的三个面,我们可以看见,其它的就看不见了,如何确定什么是我们看见的,什么是我们看不见的,方法就是建立深度缓冲,看看哪个三角形被盖住不能看见,这个三角形就不必绘制了,z缓冲是用的最多的一种深度缓冲,在屏幕绘制的过程中(一般是在后台缓冲中绘制),保留屏幕上每个点当前离我们观看的距离(就是离照相机的距离),如果新绘制的点大于我们保留的距离,不绘制,如果小于我们保留的距离,就绘制新点,并且保留新点的离我们的距离.从而保障了我们不会在屏幕上看见不该看到的点.当然为了更好的提高绘制的效率,我们还需要用到裁减!后话!


何储存几何体的缓冲!


我们已经知道了,网格和模型是由许多三角形组成的,我们有6中三角形顶点的缓冲<1\u32447线顺序,2\u32447线带,3\u39030顶点列表,4\u19977三角形列表,5\u19977三角形带,6\u19977三角形fan,(原文中有很详细的图表,大家可以去看看)directx 将可以知道用上面6种缓冲的代表的是什么几何体!


当然还有一个问题,一个三角形有三个点,假设是abc,我们可以储存成abc也可以储存成acb,区别就是你的三个点是顺时针存的,还是逆时针存的,这是一个很有用很聪明的设置!你可以使用deviec.renderstate.cullmode来进行三种设置,默认的是cull.counterclockwise, 意思是移除所有的逆时针的三角形,只要我们在给顶点的时候,注意按照顺时针去储存,那么我们可以提高40%的效率来判断这个面是否背对我们,(背对我们的时候是逆时针),直接去掉这个面不绘制,当然在特殊情况下,如透明效果,不能用这个功能,我们要取消它设置为no-culling.


vb.net 对directx 管理方法(六)


以后代码我直接写出,不说它的位置了,请你自己找:


我们在5讲了顶点的缓冲,现在我们将用程序来完成它!


我们建立的是一个正方体,但你不要认为正方体只有8个顶点,所有我们只需要告诉directx这个顶点就可以了,我可以告诉你,这样不行,我说过,网格\u27169模型\u25110或者一个几何体都是由三角形组成的, directx 也只认我们前面说过的六种顶点缓冲的一种!那么我们看看这个正方体,众所周知,一共有上下左右前后六个面,每个面我们可以划成两个三角形(两个相对的顶点相连),每个三角形有三个点,我们来算算,6*2*3=36个顶点,这个数字才是对的,而不是你想当然的8个!明白了么!我们用vCube(0)-vCube(35)来储存他们,0-2, 3-5 , 6-8 , 9-11 等等分别代表是一个三角形三个顶点,哦,这段代码现在看懂了吧!


我们看看这个


vbCube= new vertexbuffer(gettype(customvertex.positiontextured),36,d3ddev,0,customvertex.positiontextured.format,pool.managed)


有点眼花!


我们使用的是顶点缓冲类构造函数来建立我们的顶点缓冲!上面意思是告诉directx我们用gettype()命令来告诉这个过程用什么样的储存类型.第二参数是顶点的数量,pool.managged指出我们希望是把数据储存在显卡的内存上,还是系统的内存上,当然显卡内存提供我们更快的访问速度,但资源有限!!哈!customvertex类是所有普通类型的顶点格式类,我们不能自己定义它,从对象浏览器中可以看到它的结构,一般变化很小,当然它也控制光滑顶点格式(fvf)以后我们会用到


顶点数据在加入我们的顶点缓冲时,需要先锁定,然后解锁!这个原因我也不是很懂,请高手指教.


顶点被定义完了,我们就可以加入材质的信息了,关于材质,前面我有叙述,希望你仔细看看!还是老话,没有理论,就看不懂代码!


材质在内存中是以标准图形格式,如,bmp,tga,gif,jpg等等都可以,使用directx你不必担心材质的格式,这些格式有的没有压缩,有的是无损耗压缩,有的是损耗压缩!我需要说明的是这种格式dds(direct draw surface),这个格式特点是它在硬盘上的存储格式和内存中完全一样,是提高程序运行速度的最好办法.如果你希望建立dds文件,最好使用sdk"DXTEX"工具,photoshop或其他工具软件的插件也可以直接输出这种格式.


材质在内存中储存大约有超过40种的格式,由farmat枚举描述,我们这个例子没有涉及这么多复杂的内容,


我们看看格式它的表示方法x8r8g8b8,这样我们知道rgb代表红绿蓝,x是没有使用,我们应该已经熟悉了,如果有a代表透明通道,但 direct9提供了6中新的格式,就是后面加了数字 f, a16r16g16b16f 可以使用浮点数,这样允许我们使用更高的颜色保真度!我不需要这些,只有高级的图形引擎才可能使用f


如果我们有32m显卡,大约20到25m的空间会分配给材质,就这样也远远不够我们的需要,所以需要设计一个好的算法去在特定的时间让重要的材质放在显存,这样才能提高游戏的效率!

vb.net对 directx 的管理办法

下面的一节,我尽力说明材质是如何贴到物体上的!希望我有时间



群贤毕至

访客