创建D3D设备
创建一个简单的D3D设备并进行图形渲染
第一步 创建窗体和picture控件
Caption = "Create Device" Height = 3600 Left = 0 Top = 0 Width = 4800 LinkTopic = "Form1" MaxButton = True MinButton = True ScaleHeight = 3195 ScaleMode = 1 - Twip ScaleWidth = 254 StartUpPosition = 3 - Windows Default
第二步 开始D3D设备
首先要用DirectX8.Direct3DCreate方法创建一个Direct3d8对象
代码: |
get g_D3D = g_DX.Direct3DCreate() g_D3D Is Nothing Then Exit Function |
方法格式: |
Direct3d8object.direct3dcreate(); |
备注: |
他将返回一个Direct3d8对象只有在创建了DirectX8对象后才可以创建Direct3DDevice8对象 | 其次要用Direct3D8.GetAdapterDisplayMode方法接受到当前的显示模式
代码: |
Dim Mode As D3DDISPLAYMODE g_D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, mode |
方法格式: |
Direct3d8object.GetAdapterDisplayMode Adapter As Long,Mode As D3DDISPLAYMODE |
备注: |
用Direct3d8对象来接收,Adapter参数是要查询的显卡序号,一般是D3DADAPTER_DEFAULT值来指定主显卡,Mode参数为当前显示模式的接收变量,D3DDISPLAYMODE对象有Format,Height,RefreshRate,Width成员.format成员的值为23(&H17)时表示16位RGB像素格式为22时是32位. RefreshRate值表示刷新率,为0时表示为默认的刷新率. | 在取得显示模式后,以后就可以用此结构在创建一个运行在窗口模式下的Direct3Ddevice设备时,建立一个与当前显卡相匹配的后缓冲区接下来用D3DPRESENT_PARAMETERS对象来指定3D应用程序的表现
代码: |
Dim d3dpp As D3DPRESENT_PARAMETERS d3dpp.Windowed = 1 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC d3dpp.BackBufferFormat = mode.Format |
对象说明: |
D3DPRESENT_PARAMETERSobject.成员 |
备注: |
成员Windowed用来说明3D应用程序运行的环境为1表示在窗口模式下.成员SwapEffect是个枚举类型,D3DSWAPEFFECT_COPY_VSYNC时值为4用来说明只有一个后缓冲区,并执行COPY操作.成员BackBufferFormat用来指定后缓冲区的格式,在Windowed在被说明成TURE(1)时,必须为GetAdapterDisplayMode方法取到的值. | 下面就要用CreateDevice方法利用上面对象的值设置应用程序
代码: |
Set g_D3DDevice =g_D3D.CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,d3dpp) If g_D3DDevice Is Nothing Then Exit Function |
方法格式: |
Direct3D8object.CreateDevice Adapter,DeviceType,hFocusWindow, BehaviorFlags,PresentationParameters |
备注: |
返回一个Direct3DDevice8对象,Adapter参数为查询的显卡序号,一般为D3DADAPTER_DEFAULT,DeviceType参数为D3DDEVTYPE常量,表示设备类型D3DDEVTYPE_HAL意义为硬件驱动软件补充,hFocusWindow参数是设备的窗口句柄.BehaviorFlags控制D3D设备的全局性能,为D3DCREATE_SOFTWARE_VERTEXPROCESSING规定为软件顶进程. |
第三步 渲染和显示场景
本例使用一个(Interval=40)timer控件触发场景的后缓冲区进行颜色填充.再把后缓冲与前缓冲交换实现渲染
首先用Direct3DDevice8.Clear方法进行填充颜色
代码: |
g_D3DDevice.Clear 0,ByVal 0,D3DCLEAR_TARGET,&HFFFF0,1#,0 |
方法格式: |
Direct3DDevice8object.Clear Count,ClearD3DRect,Flags,Color,Z,Stencil |
备注: |
ClearD3DRect参数为D3DRECT类型是指明清除的区域可以被说明为ByVal 0表明所有点都被清除.Count参数是指区域的数量,当ByVal 0为ClearD3DRect的值时这里要设为0.flags为D3DCLEARFLAGS常量,为D3DCLEAR_TARGET时表示清除渲染目标,color为填充颜色值.参数Z为深度缓冲的大小取值为0.0到1.0.参数Stencil在有模板缓冲时使用可以是0到2. | 在是开始场景和结束场景
代码: |
g_D3DDevice.BeginScene g_D3DDevice.EndScene | 在渲染完场景后再用Direct3DDevice8.Present方法显示出来
代码: |
g_D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 |
方法格式: |
Direct3DDevice8object.Present SourceRect,DestRect,DestWindowOverride,DirtyRegion |
备注: |
参数SourceRect为包含源矩形的类型,一般为ByVal 0则全部源表面被呈现.参数DestRect为包含目标矩形的类型,一般为ByVal 0则全部用户区域被填充.DestWindowOverride参数说明用户区域作为这个图象的目标窗口被取得,当为0时则D3DPRESENT_PARAMETERS成员hWndDeviceWindow被取.在窗口模式下此成员为Present方法设定缺省的目标窗口如果没有取值表示焦点窗口被取得.DirtyRegion参数总是被设置成ByVal 0 |
第四步 关闭应用程序
在DX应用程序结束后必须把所有的DX对象设置成Nothing
代码: |
Set g_D3D = Nothing Set g_D3DDevice = Nothing |
所有代码如下:
Dim g_DX As New DirectX8 Dim g_D3D As Direct3D8 Dim g_D3DDevice As Direct3DDevice8 Private Sub Form_Load() Me.Show DoEvents b = InitD3D(Picture1.hWnd) '初始化设备 If Not b Then MsgBox "Unable to CreateDevice (see InitD3D()source for comments)" End End If Timer1.Enabled = True End Sub Private Sub Timer1_Timer() Render '渲染 End Sub Private Sub Form_Unload(Cancel As Integer) Cleanup '清除设备 End End Sub Function InitD3D(hWnd As Long) As Boolean'初始化 On Local Error Resume Next Set g_D3D = g_DX.Direct3DCreate() If g_D3D Is Nothing Then Exit Function Dim mode As D3DDISPLAYMODE g_D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, mode Dim d3dpp As D3DPRESENT_PARAMETERS d3dpp.Windowed = 1 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC d3dpp.BackBufferFormat = mode.Format Set g_D3DDevice =g_D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp) If g_D3DDevice Is Nothing Then Exit Function InitD3D = True End Function Sub Cleanup() '清除设备 Set g_D3DDevice = Nothing Set g_D3D = Nothing End Sub Sub Render() '渲染 If g_D3DDevice Is Nothing Then Exit Sub g_D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 g_D3DDevice.BeginScene g_D3DDevice.EndScene g_D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 End Sub
要使用D3D进行渲染就必须创建Direct3DDevice8对象 在DirectX8.Direct3DCreate方法先要创建一个Direct3d8对象 再用Direct3d8.CreateDevice方法创建Direct3DDevice8对象 其中还要Direct3D8.GetAdapterDisplayMode方法接受到当前的显示模式 并要设置D3DPRESENT_PARAMETERS成员来指定3D应用程序的表现 创建完后用Direct3DDevice8.Clear方法进行填充颜色 并开始场景用Direct3DDevice8.Present方法显示出来 最后还要把所有的DX对象设置成Nothing 来结束DX程序
顶点的渲染
使用顶点画几何图形,本例使用3个顶点,并使用了顶点缓冲区的概念
第一步:定义一个顶点类型 首先定义顶点格式,并指定在顶点缓冲区里描述画面顶点的FVF
代码: |
Private Type CUSTOMVERTEX x As Single y As Single z As Single rhw As Single color As Long End Type Const D3DFVF_CUSTOMVERTEX=(D3DFVF_XYZRHW Or D3DFVF_DIFFUSE) |
说明: |
FVF(Flexible Vertex Format)用来描述在单个数据流里交错存储的顶点内容,FVF代码通常用来指定:数据用固定的顶点函数来处理;D3DFVF_DIFFUSE说明包含了扩散的颜色部分;D3DFVF_XYZRHW说明包含了已转化了的顶点位置,已转化了的标志着D3D不能对此点进行世界或视图坐标的转化. |
第二步:设置顶点缓冲区 本例子用自定义的InitVB过程在创建了D3D所需的对象后来实现初始化顶点缓冲区, 接下来的代码初始了三个特定的顶点类型来填充顶点缓冲区
代码: |
With Vertices(0) .x=150 .y=50 .z=0.5 .rhw=1 .color=&HFFFF0000 End With |
With Vertices(1) .x=250 .y=250 .z=0.5 .rhw=1 .color=&HFF00FF00 End With |
With Vertices(2) .x= 50 .y=250 .z=0.5 .rhw = 1 .color =&HFF00FFFF End With |
说明: |
3个点的颜色值,用于进行颜色渐变,red(&HFFFF0000) green(&HFF00FF00) blue-green(&HFF00FFFF)Z和RHW成员说明点的深度和RHW值为0.5,1 | 下面用CreateVertexBuffer方法建立顶点缓冲区
代码: |
Set g_VB = g_D3DDevice.CreateVertexBuffer(VertexSizeInBytes* 3,0,D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT) If g_VB Is Nothing Then Exit Function |
方法格式: |
Direct3DDevice8对象.CreateVertexBuffer LengthInBytes,Usage,FVF,Pool |
备注: |
参数LengthInBytes用来容纳顶点缓冲区的大小;参数Usage是个D3DUSAGEFLAGS常量,为0时表示新顶点的使用;参数Pool值为D3DPOOL常量,D3DPOOL_DEFAULT指明程序资源要放在显存的首选地址;方法返回值是个Direct3DVertexBuffer8类型 | 接下来使用D3DVertexBuffer8SetData来添加数据
代码: |
D3DVertexBuffer8SetData g_VB,0,VertexSizeInBytes*3,0,Vertices(0) |
格式: |
D3DVertexBuffer8SetData VBuffer,Offset,Size,Flags,Data |
备注: |
参数VBuffer是Direct3DVertexBuffer8类型.参数offset是表示缓冲区的起始位置.参数Size代表缓冲区的大小.参数Flags代表了如何锁定缓冲,这里用0表示使用默认的值,参数Data代表缓冲区要包含的数据 |
第三步 渲染显示表面 现在仍使用clear方法来清除表面并开始场景
代码: |
g_D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 g_D3DDevice.BeginScene | 接下来要用SetStreamSource方法,来设置顶点缓冲区对应的流
代码: |
Dim v As CUSTOMVERTEX sizeOfVertex = Len(v) g_D3DDevice.SetStreamSource 0, g_VB, sizeOfVertex |
格式: |
Direct3DDevice8对象.SetStreamSource(StreamNumber,StreamData,Stride) |
备注: |
这个方法使顶点缓冲区绑定一个设备数据流.参数StreamNumber表示使用流0;参数StreamData代表要绑定的顶点缓冲区;参数Stride为表示流组件的大小,当使用FVF顶点时,流组件大小必须和顶点大小匹配. | 下一步是使用CreateVertexShader方法来创建顶点遮盖
代码: |
g_D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX |
格式: |
Direct3DDevice8对象.SetVertexShader(VertexShaderHandle) |
备注: |
顶点遮盖运用于顶点处理.参数VertexShaderHandle为顶点遮盖的句柄或者FVF代码.这里使用D3DFVF_CUSTOMVERTEX表示使用FVF代码.说明绑定在设备上的流0被引用 | 使用DrawPrimitive在顶点缓冲区里渲染顶点
代码: |
g_D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, 1 |
格式: |
Direct3DDevice8对象.DrawPrimitive(PrimitiveType,StartVertex,PrimitiveCount) |
备注: |
绘制主平面,参数PrimitiveType是个CONST_D3DPRIMITIVETYPE枚举类型,这里使用D3DPT_TRIANGLELIST表示告诉D3D设备要绘制的主平面为三角形.参数StartVertex为第一个点的索引,参数PrimitiveCount为要绘制的主平面数,这里为1 | 最后的步骤就是交换前后缓冲,这个例子只是简单说明如何用顶点来绘制几何图形
代码: |
g_D3DDevice.EndScene g_D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 |
所有代码如下:
Dim g_DX As New DirectX8 Dim g_D3D As Direct3D8 Dim g_D3DDevice As Direct3DDevice8 Dim g_VB As Direct3DVertexBuffer8 Private Type CUSTOMVERTEX x As Single y As Single z As Single rhw As Single color As Long End Type Const D3DFVF_CUSTOMVERTEX = (D3DFVF_XYZRHW Or D3DFVF_DIFFUSE) Private Sub Form_Load() Dim b As Boolean Me.Show DoEvents b = InitD3D(Picture1.hWnd) If Not b Then MsgBox "Unable to CreateDevice (see InitD3D() source for comments)" End End If b = InitVB() If Not b Then MsgBox "Unable to Create VertexBuffer" End End If Timer1.Enabled = True End Sub Private Sub Timer1_Timer() Render End Sub Private Sub Form_Unload(Cancel As Integer) Cleanup End End Sub Function InitD3D(hWnd As Long) As Boolean Set g_D3D = g_DX.Direct3DCreate() If g_D3D Is Nothing Then Exit Function Dim mode As D3DDISPLAYMODE g_D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, mode Dim d3dpp As D3DPRESENT_PARAMETERS d3dpp.Windowed = 1 d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC d3dpp.BackBufferFormat = mode.Format Set g_D3DDevice = g_D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, d3dpp) If g_D3DDevice Is Nothing Then Exit Function InitD3D = True End Function Function InitVB() As Boolean Dim Vertices(3) As CUSTOMVERTEX Dim VertexSizeInBytes As Long VertexSizeInBytes = Len(Vertices(0)) With Vertices(0): .x = 150: .y = 50: .z = 0.5: .rhw = 1: .color = &HFFFF0000: End With With Vertices(1): .x = 250: .y = 250: .z = 0.5: .rhw = 1: .color = &HFF00FF00: End With With Vertices(2): .x = 50: .y = 250: .z = 0.5: .rhw = 1: .color = &HFF00FFFF: End With Set g_VB = g_D3DDevice.CreateVertexBuffer(VertexSizeInBytes * 3, 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT) If g_VB Is Nothing Then Exit Function D3DVertexBuffer8SetData g_VB, 0, VertexSizeInBytes * 3, 0, Vertices(0) InitVB = True End Function Sub Cleanup() Set g_VB = Nothing Set g_D3DDevice = Nothing Set g_D3D = Nothing End Sub Sub Render() Dim v As CUSTOMVERTEX Dim sizeOfVertex As Long If g_D3DDevice Is Nothing Then Exit Sub g_D3DDevice.Clear 0, ByVal 0, D3DCLEAR_TARGET, &HFF&, 1#, 0 g_D3DDevice.BeginScene sizeOfVertex = Len(v) g_D3DDevice.SetStreamSource 0, g_VB, sizeOfVertex g_D3DDevice.SetVertexShader D3DFVF_CUSTOMVERTEX g_D3DDevice.DrawPrimitive D3DPT_TRIANGLELIST, 0, 1 g_D3DDevice.EndScene g_D3DDevice.Present ByVal 0, ByVal 0, 0, ByVal 0 End Sub
总结:
首先你要定义CUSTOMVERTEX结构和FVF 象大多数D3D程序一样要初始化3D设备(教程1内容) 再设定3个CUSTOMVERTEX类型的顶点 建立顶点缓冲区是必须的,并为其填充要包含的数据 清除场景,把顶点缓冲区绑定在流上,是渲染的开始 接着创建顶点遮盖,把顶点在顶点缓冲区里进行渲染 后面就是交换前后缓冲,把渲染结果呈现出来 结束所有D3D设备
使用矩阵
本教程介绍了如何使用矩阵,我们在顶点的例子里,渲染了一个2D的三角形,而本例子将把它转化为3D
第一步:定义世界变化矩阵 介绍在3-D空间里矩阵的世界矩阵如何转化,度量,和旋转几何图形 首先使用D3DXMatrixRotationY方法把三角形围绕Y轴旋转
代码: |
Dim matWorld As D3DMATRIX D3DXMatrixRotationY matWorld, Timer * 4 |
格式: |
D3DXMatrixRotationY(MOut,angle) |
备注: |
建立一个围Y轴旋转的矩阵, 参数MOut是个D3DMATRIX类型t包含着返回的矩阵; 参数angle是表示旋转的弧度 | 接下来就是用SetTransform来设置当前的D3D设备的转变
代码: |
g_D3DDevice.SetTransform D3DTS_WORLD, matWorld |
格式: |
Direct3DDevice8对象.SetTransform(TransformType,Matrix) |
备注: |
参数TransformType是D3DTRANSFORMSTATETYPE枚举类型D3DTS_WORLD指出一个世界矩阵将被设置,参数Matrix是一个指向单前转化矩阵的指针 |
第二步:定义视图变化矩阵 视图矩阵定义了视图的位置和转动,相当于一个场景摄象机. 首先使用D3DXMatrixLookAtLH方法
代码: |
Dim matView As D3DMATRIX D3DXMatrixLookAtLH matView,vec3(0#,3#,-5#),vec3(0#,0#,0#),vec3(0#,1#,0#) |
格式: |
D3DXMatrixLookAtLH(MOut,VEye,VAt,VUp) |
备注: |
参数MOut是D3DMATRIX类型,参数VEye为D3DVECTOR类型定义观察点(Y+3,Z-5),参数VAt为D3DVECTOR类型定义摄影机焦距(原点),参数VUp是D3DVECTOR定义向上的方向(0,1,0) |
代码: |
g_D3DDevice.SetTransform D3DTS_VIEW, matView |
备注: |
参数TransformType是D3DTRANSFORMSTATETYPE枚举类型D3DTS_VIEW指出一个视图矩阵将被设置 |
第三步:定义投影变化矩阵 投影矩阵定义了几何图形被从2D转化为3D首先使用D3DXMatrixPerspectiveFovLH方法,在观察视野创建一个左手透视投影矩阵(相当于人的视野)
代码: |
Dim matProj As D3DMATRIX D3DXMatrixPerspectiveFovLH matProj, g_pi / 4, 1, 1, 100 g_D3DDevice.SetTransform D3DTS_PROJECTION, matProj |
格式: |
D3DXMatrixPerspectiveFovLH(MOut,fovy,aspect,zn,zf) |
备注: |
参数MOut是D3DMATRIX类型;参数fovy弧度表示的观察视野,让远处的物体看起来更小,一个标准的观察视野是PI/4;参数aspect长宽高度比,标准为1;参数zn和zf设定几何物体在Z上的可视范围最近和最远的两个点 |
代码: |
g_D3DDevice.SetTransform D3DTS_VIEW, matView |
备注: |
参数TransformType是D3DTRANSFORMSTATETYPE枚举类型D3DTS_PROJECTION指出一个投影矩阵将被设置 | 所有代码
Option Explicit Dim g_DX As New DirectX8 Dim g_D3D As Direct3D8 Dim g_D3DDevice As Direct3DDevice8 Dim g_VB As Direct3DVertexBuffer8 Private Type CUSTOMVERTEX x As Single y As Single z As Single color As Long End Type Const D3DFVF_CUSTOMVERTEX=(D3DFVF_XYZ Or D3DFVF_DIFFUSE) Const g_pi = 3.1415 Private Sub Form_Load() '省略 End Sub Private Sub Timer1_Timer() Render End Sub Private Sub Form_Unload(Cancel As Integer) End End Sub Function InitD3D(hWnd As Long) As Boolean '省略 End Function Sub SetupMatrices() Dim matWorld As D3DMATRIX D3DXMatrixRotationY matWorld, Timer * 4 g_D3DDevice.SetTransform D3DTS_WORLD, matWorld Dim matView As D3DMATRIX D3DXMatrixLookAtLH matView, vec3(0#, 3#, -5#), vec3(0#, 0#, 0#), vec3(0#, 1#, 0#) g_D3DDevice.SetTransform D3DTS_VIEW, matView Dim matProj As D3DMATRIX D3DXMatrixPerspectiveFovLH matProj, g_pi / 4, 1, 1, 1000 g_D3DDevice.SetTransform D3DTS_PROJECTION, matProj End Sub Function Initvb() As Boolean '省略 End Function Sub Cleanup() '省略 End Sub Sub Render() '省略 End Sub Function vec3(x As Single, y As Single, z As Single) As D3DVECTOR vec3.x = x vec3.y = y vec3.z = z End Function

|

| |