<DirectX 图形接口指南>这篇文章在我的博客的左边图形方面的连接里有.在这里重贴是因为我对文章进行了整合.原作者允许转贴,我按照原作者的要求贴了声明.
我给这篇文章定的级别是:入门级
这是SDK里翻译过来的,读者也可以看原版(英文).
指南一:创建设备
为了使用
Microsoft Direct3D
,你首先需要创建一个应用程序窗口,并紧接着创建和初始化
Direct3D
对象。你应该使用这些对象提供的
COM
接口来操纵它们,以及创建描绘一个场景所必需的其它对象。本指南包含的
CreateDevice 示
例将例示并说明以下几个工作:创建
Direct3D
设备并且绘制一个简单的蓝色屏幕。
这个指南使用以下步骤:初始化
Direct3D
,绘制场景,以及最后清理与关闭。
·步骤一:创建一个窗口
·步骤二:初始化
Direct3D
·步骤三:处理系统消息
·步骤四:绘制与显示场景
·步骤五:关闭与清除
注意:
CreateDevice
示例程序的路径在:
(SDK root)/Samples/Multimedia/Direct3D/Tutorials/Tut01_CreateDevice.
步骤一:创建一个窗口
任何
Microsoft Windows
程序执行中必须要作的第一件事就是创建一个应用程序窗口并将其显示给用户。为做到这点,
CreateDevice
例程将首先实现它的
WinMain
函数。以下示例代码完成了窗口的初始化。
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
// Register the window class.
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"D3D Tutorial", NULL };
RegisterClassEx( &wc );
// Create the application's window.
HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 01: CreateDevice",
WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
GetDesktopWindow(), NULL, wc.hInstance, NULL );
前述示例代码是标准的
Windows
编程。例子开始时定义和注册了一个窗口类名为
"D3D Tutorial"
。类注册以后,示例代码使用已注册的类创建了一个基本的顶层(
top-level
)窗口,客户区域为
300
像素宽,
300
像数高。这个窗口没有菜单或子窗口。示例使用了
WS_OVERLAPPEDWINDOW
属性创建一个包括最大化,最小化,以及关闭按钮的普通窗口。(如果该例程将运行在全屏模式下,首选的窗口属性应该是
WS_EX_TOPMOST
,它指定创建的窗口置于并且保持在所有非最高(
non-topmost
)窗口之前,甚至在窗口失活的情况下。)一旦窗口创建完成,例代码调用标准的
Microsoft Win32
函数显示和更新窗口。
在应用程序窗口准备好以后,你就能开始设置具体的
Microsoft Direct3D
对象了,
请见:步骤二:初始化
Direct3D
步骤二:初始化 Direct3D
CreateDevice
示例在
WinMain
中创建窗口之后,调用该程序定义的函数
InitD3D
完成
Microsoft Direct3D
初始化过程。在创建窗口之后,程序已经准备好初始化你将用来绘制场景的
Direct3D
对象了。这个过程包括创建一个
Direct3D
对象,设置
Present Parameters
,以及最后创建
Direct3D
设备。
创建完
Direct3D
对象之后,你可以立即使用
IDirect3D8::CreateDevice
方法创建
Direct3D
设备。你也能够使用
Direct3D
对象枚举设备,类型,模式以及其他东西。这些工作的代码段应位于使用
Direct3DCreate8
函数创建
Direct3D
对象之后。
if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
return E_FAIL;
传递给
Direct3DCreate8
的唯一参数应该始终是
D3D_SDK_VERSION
,它告诉
Direct3D
当前使用的头文件信息。无论如何,头文件或者其他的变化将导致这个值增加并强制使用该值的应用程序重新编译。如果此版本不匹配,调用
Direct3DCreate8
将失败。
下一个步骤是使用
IDirect3D8::GetAdapterDisplayMode
接口找到当前的显示模式,代码如下:
D3DDISPLAYMODE d3ddm;
if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
return E_FAIL;
D3DDISPLAYMODE
结构中的
Format
变量将被用于创建
Direct3D
设备。如果是运行于窗口模式下的话,
Format
参数通常用来创建一个与适配器当前模式相匹配的后背缓冲
(Back buffer)
。
在给
D3DPRESENT_PARAMETERS
各参数赋值时,你必须指定你的应用程序在
3D
下工作的方式。本
CreateDevice
例程设置
D3DPRESENT_PARAMETERS
结构中
Windowed
为
TRUE
,
SwapEffect
为
D3DSWAPEFFECT_DISCARD
,
BackBufferFormat
为
d3ddm.Format
。
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
最后一步,是利用
IDirect3D8::CreateDevice
函数创建
Direct3D
设备,代码如下:
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
前述代码使用
D3DADAPTER_DEFAULT
标志创建了一个使用省缺适配器的设备。在非常多数的情况下,系统只有一个适配器,除非它安装了多个图形加速卡。通过把
DeviceType
参数设成
D3DDEVTYPE_HAL
,表示你希望获得一个实际硬件设备
(hardware device)
而不是软件虚拟设备
(software device)
。示例代码还使用
D3DCREATE_SOFTWARE_VERTEXPROCESSING
标志通知系统使用软件顶点处理
(software vertex processing)
。注意,如果你指定
D3DCREATE_HARDWARE_VERTEXPROCESSING
标志通知系统使用硬件顶点处理
(hardware vertex processing),
你可以在支持硬件顶点处理的图形加速卡上得到大幅度的性能提升。
现在
Direct3D
已经初始化完毕,下一步是确保你的程序具有一个机制用来来处理系统消息,
见下文:步骤三:处理系统消息
步骤三:处理系统消息
完成创建程序窗口以及初始化
Direct3D
以后,你已经准备好绘制场景
(Render scene)
。大多数情况下,
Microsoft Windows
程序在它们的消息循环里监视系统消息,并且在队列里没有消息时绘制画面帧。然而,
CreateDevice
例程仅仅在等到一个
WM_PAINT
出现在队列里时,才通知应用程序重绘窗口的所有部分。
// The message loop.
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
当每循环一次,
DispatchMessage
调用
MsgProc
,后者负责处理队列里的消息,当
WM_PAINT
消息进队时,调用该程序自身定义的函数
Render()
,它将负责重绘窗口。然后
Microsoft Win32
函数
ValidateRect
执行并将整个客户区域设为有效。
消息处理函数的例代码如下:
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
Render();
ValidateRect( hWnd, NULL );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
现在,应用程序处理了系统消息,接着的一步是绘制显示,见:步骤四:绘制与显示场景
步骤四:绘制与显示场景
为了描绘和显示需要的场景,本例程在这一步把后背缓冲
(back buffer)
填充为蓝色,然后将此后背缓冲的内容传给前景缓冲
(front buffer),
并且将前景缓冲提交至屏幕。
清除表面,应调用
IDirect3DDevice8::Clear
函数:
// Clear the back buffer to a blue color
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
Clear()
接受的前两个参数通知
Microsoft Direct3D
被清除的矩形区域数组的基址和大小,该矩形区域数组描述了绘制目标表面
(render target surface)
里需要清除的区域。
在大多数情况下,只使用单个矩形覆盖整个绘制目标表面。这样你只需设置第一个参数为
0
及第二个参数为
NULL
。第三个参数将决定方法的行为,你可以通过设置特定的标志用来清除绘制目标表面
(render target surface)
,关联的
Z
缓冲
(associated depth buffer)
,模版缓冲
(stencil buffer)
,以及任意这三者的混合。本指南不使用
Z
缓冲,所以仅仅使用了
D3DCLEAR_TARGET
标志。最后三个参数分别用于设置对应绘制目标表面、
Z
缓冲和模版缓冲的清除填充值
(reflect clearing values)
。该
CreateDevice
例程将绘制目的表面的清除填充色设置为蓝色
(D3DCOLOR_XRGB(0,0,255)
。由于相应的标志没有设置,最后两个参数被
Clear()
忽略。
在清除了视口
(viewport)
之后,
CreateDevice
例程告知
Direct3D
绘图将要开始,然后立即通知这次绘制完成,见以下代码段:
// Begin the scene.
g_pd3dDevice->BeginScene();
// Rendering of scene objects happens here.
// End the scene.
g_pd3dDevice->EndScene();
当绘制开始或完成时,
IDirect3DDevice8::BeginScene
和
IDirect3DDevice8::EndScene
函数将用信号通知系统。你只能在这两函数之间调用其它的绘图函数。即使调用绘图函数失败,你也应该在重新调用
BeginScene
之前调用
EndScene
。
绘制完之后,调用
IDirect3DDevice8::Present
显示该场景:
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
Present()
接受的前两个参数是原始矩形和目标矩形。在这一步,例程设置这两个参数为
NULL
并把整个后备缓冲提交到前景缓冲。第三个参数用于设置该次提交的目标窗口。因为这个参数被设为
NULL
,实际使用的窗口是
D3DPRESENT_PARAMETERS
的
hWndDeviceWindow
成员。第四个是
DirtyRegion
参数,在绝大多数情况下应该设为
NULL
。
本指南的最终步骤是关闭应用程序,见:步骤五:关闭与清除
步骤五:关闭与清除
在执行的若干时刻,你的应用程序必须立即关闭。关闭一个
Direct3D
应用程序中不只是意味着你必须销毁程序窗口,并且你还要释放程序中使用过的的任何
Direct3D
对象并且无效化它们的指针。当收到一个
WM_DESTROY
消息时,
CreateDevice
例程通过调用一个本地定义的函数
Cleanup()
来处理这些工作。
VOID Cleanup()
{
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if( g_pD3D != NULL)
g_pD3D->Release();
}
上述函数对每个对象调用
IUnknown::Release
方法来释放它们自身。由于
DirectX
遵循
COM
规则,大多数对象当其引用计数降为
0
时,
DirectX
会自动的从内存中释放这个对象。
对于其他关闭程序情况,可能发生在程序的平常执行中——比如用户改变了桌面的参数或色深——此时你可能需要撤销和重建使用中的
Microsoft Direct3D
对象。因此一个好的主意就是将你的释放代码放到一起,以便能在需要时随时调用它。
本指南已经说明了如何创建一个设备,指南二:演示顶点(Render Vertex) ,将告诉你如何用顶点(Vertex)创建几何形体。
(指南二:演示顶点 见本文第三部分...)
指南二:演示顶点
(Render Vertex)
Microsoft Direct3D
写的应用程序使用顶点
(Vertex)
构造几何物体。每一个三维空间
(3D)
场景包括一个或几个这样的几何物体。
Vertices
例程构造简单的物体,一个三角形,并且将它绘制到显示屏上。
本指南说明如何采用以下步骤从顶点构造一个三角形:
·第一步:定义一个自定义顶点类型
·第二步:设置顶点缓冲
·第三步:绘制至显示屏
注意:
Vertices
示例程序的路径为:
(SDK root)/Samples/Multimedia/Direct3D/Tutorials/Tut02_Vertices.
Vertices
程序的示例代码与
CreateDevice
的代码大部分相同。本“演示顶点(
Render Vertex
)”指南仅仅关注于那些独特的,关于顶点的代码而不包括初始化
Direct3D
,处理
Microsoft Windows
消息,绘图,与清理等工作。如要得到有关这些任务的信息,请参考
指南一:创建设备
。
第一步:定义一个自定义顶点类型
Vertices
例程使用三个顶点构造一个
2D
的三角形。这里提及了顶点缓冲的概念,这是用于保存和演示大量顶点的
Microsoft Direct3D
对象。通过指定一个自定义的顶点结构和相应的可变向量格式
(FVF)
,顶点能够采用很多方法定义。本
Vertices
例程使用的顶点格式定义于以下代码片断中。
struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw; // The transformed position for the vertex.
DWORD color; // The vertex color.
};
上面的结构体说明了自定义顶点类型的格式。下一步是定义
FVF
以描述顶点缓冲区中的顶点内容。以下代码片段定义了一个
FVF
并符合此上建立的自定义顶点类型。
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
可变顶点格式标记描述了使用中的自定义顶点类型。前述示例代码使用了
D3DFVF_XYZRHW
和
D3DFVF_DIFFUSE
标志,这将告诉顶点缓冲,自定义顶点类型包含一组转换过的点坐标并紧跟着一个颜色参数。
现在自定义向量格式和
FVF
已经被指定好了,下一步将使用顶点填充顶点缓冲区,请参看:第二步:设置顶点缓冲
。
注意:
Vertices
例程中的顶点是转换过的。用另一句话说,它们已经在
2D
窗口坐标系下。这意味着座标点
(0,0)
位于左上角,且正的
x
半轴向右,正的
y
半轴向下。这些顶点同样也是光照过的,这说明它们的着色不通过
Direct3D
照明而由它们自己的颜色代替。
第二步:设置顶点缓冲
现在自定义顶点格式已经完成,初始化顶点的时候到了。
Vertices
例程创建了必需的
Microsoft Direct3D
对象之后调用本程序内部定义的函数
InitVB()
进行这个工作。以下代码段将初始化三个自定义顶点的值。
CUSTOMVERTEX g_Vertices[] =
{
{ 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
{ 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
{ 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
};
前述代码片段采用三角形的三个顶点填充三个
Vertex
并指定了每个顶点的散射光的颜色。第一个顶点位于
(150,50)
,散射红色
(0xffff0000)
。第二个顶点位于
(250,250)
,为绿色
(0xff00ff00)
。第三点位于
(50,250)
并散射蓝绿色
(0xff00ffff)
。每一点都具有相同的
0.5 Z
值及
1.0
的
RHW
参数。关于这些矢量格式的其它信息见
SDK:
Transformed and Lit Vertices
。
下一步将调用
IDirect3DDevice8::CreateVertexBuffer
创建顶点缓冲区,如以下代码段所示:
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0 /* Usage */, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB ) ) )
return E_FAIL;
CreateVertexBuffer
的头两个参数告诉
Direct3D
新顶点缓冲区预计的大小和用法。紧跟的两个参数指定新缓冲区的矢量格式及存储位置。这里的向量格式是
D3DFVF_CUSTOMVERTEX
,就是例程先前定义的
FVF
值。
D3DPOOL_DEFAULT
标记告诉
Direct3D
在最合适的位置创建此顶点缓冲区。最后一个参数返回创建完成的顶点缓冲区对象地址。
创建了顶点缓冲区之后,如以下代码段所示,开始采用自定义格式的顶点填充缓冲区中的数据。
VOID* pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );
g_pVB->Unlock();
首先调用
IDirect3DVertexBuffer8::Lock
锁定顶点缓冲区。函数第一个参数是锁定顶点数据的偏移量,按字节计算。第二个参数是需锁定的顶点数据长度,同样按字节计算。第三个参数是一个
BYTE
类型指针的地址,用于返回指向顶点数据的地址。第四个参数告知顶点缓冲区如何锁定数据。
通过使用
memcpy
,顶点被复制到顶点缓冲区里。将顶点放入缓冲区之后,调用一次
IDirect3DVertexBuffer8::Unlock
以解锁顶点缓冲区。这个锁定——解锁机制是必需的,因为正在使用的顶点缓冲区可能位于设备内存中。
现在顶点缓冲区已经填入顶点,绘制到显示的时候到了,见描述:第三步:绘制至显示屏
。
第三步:绘制至显示屏
现在缓冲区已经填入顶点,现在需要把它绘制到显示屏上。在绘制到屏幕之前,先将背景清除为蓝色并调用
BeginScene
。
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0L );
g_pd3dDevice->BeginScene();
从顶点缓冲区绘制顶点数据需要一些步骤。首先,你需要设置流数据源;在当前情况下,使用第
0
个流
。流的数据源是通过调用
IDirect3DDevice8::SetStreamSource
设置的。
g_pd3dDevice->SetStreamSource( 0, g_pVB, sizeof(CUSTOMVERTEX) );
SetStreamSource
的第一个参数告诉
Microsoft Direct3D
设备设置数据流的索引。第二个参数是绑定在该数据流上的顶点缓冲区。第三个参数是数据单元的大小,用字节数表示。在上面的示例代码中,将使用
CUSTOMVERTEX
的大小作为数据单元的大小。
下一步通过调用
IDirect3DDevice8::SetVertexShader
使
Direct3D
了解使用中的顶点处理器(
Vertex Shader
)。就整体而言,自定义顶点处理器是一种高级的话题,但是在绝大多数情况下顶点处理器仅仅等于
FVF
代码。这能够让
Direct3D
知道处理中的顶点类型。以下代码片段将
FVF
设置为当前顶点处理器:
g_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
SetVertexShader()
唯一的参数是当前设置的顶点处理器的句柄。这个参数的值可以是从
IDirect3DDevice8::CreateVertexShader
返回的句柄,或者是
FVF
代码。在这儿,使用的参数是定义为
D3DFVF_CUSTOMVERTEX
的
FVF
代码。
关于顶点处理器的更多信息,请见
SDK: Vertex Shader
一章。
下一步使用
IDirect3DDevice8::DrawPrimitive
绘制顶点缓冲区中的顶点,见以下代码片段:
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
DrawPrimitive
接受的第一个参数是一个标记,它通知
Direct3D
绘制哪种类型的物件
(Primitive)
。本例程使用
D3DPT_TRIANGLELIST
标记指定为三角形序列。第二个参数是第一个顶点的索引。第三个参数通知绘制的物件的数目。本例子只画一个三角形,这个值为
1
。
关于不同种类物件的更多信息,可见
SDK: 3-D Primitive
最后的一步是结束场景并立即将后背缓冲提交为前景缓冲。这些写在以下代码片段中:
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
当后背缓冲被提交为前景缓冲后,客户窗口将显示出一个三个点颜色各异的三角形。
本指南已经指导你如何使用顶点构造几何外形了。指南三:使用矩阵
将介绍矩阵的概念以及如何使用它们。
(指南三:使用矩阵 见本文第四部分)
指南三:使用矩阵
本指南介绍矩阵的概念及演示如何使用它们。
Vertices
例程通过呈递
2D
的顶点画出了一个三角形。然而,在这个指南中,你将通过顶点变换在
3-D
环境下工作。矩阵和变换也同样用于设置摄影头与视口(
Viewport
)。
在
Matrices
例程呈递几何物体之前,它调用程序自定义函数
SetupMatrices
创建并设置用于演示
3-D
三角形的矩阵变换。作为代表,三种类型的变换同时被设置到一个
3-D
场景。创建这些典型变换的步骤如下表:
·第一步:定义世界变换矩阵
·第二步:定义观察变换矩阵
·第三步:定义映射变换矩阵
注意:
Matrices
示例程序的路径为:
(SDK root)/Samples/Multimedia/Direct3D/Tutorials/Tut03_Matrices.
创建这三种变换的顺序并不影响场景元素的输出。无论如何,
Direct3D
都使用以下顺序依次将矩阵作用于场景:
(1)
世界,
(2)
观察,
(3)
映射。
Matrices
工程的示例代码几乎与
Vertices
工程的代码相同。该“使用矩阵”指南仅仅关注那些有关矩阵的独特代码,而不重复初始化
Direct3D
,处理
Microsoft Windows
消息,演示,以及清除。关于这些工作的信息,请见
指南一:创建设备
。
本指南使用自定义顶点格式和单个顶点缓冲区呈递几何模型,关于更多的有关选择自定义顶点类型以及执行顶点缓冲区的信息,见
指南二:演示顶点
。
第一步:定义世界变换矩阵(World Transformation Matrix)
世界变换矩阵定义了怎样转换、缩放、以及旋转
3-D
模拟空间中的几何物体。
以下代码片段为
Microsoft Direct3D
设备设置当前的世界变换并且使三角形绕
y-
轴
旋转。
D3DXMATRIX matWorld;
D3DXMatrixRotationY( &matWorld, timeGetTime()/150.0f );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
第一步是通过调用
D3DXMatrixRotationY
函数使三角形绕
y-
轴
旋转。函数第一个参数是指向
D3DMATRIX
结构的指针用于返回操作结果。第二个参数是以弧度表示的旋转角度。
下一步是调用
IDirect3DDevice8::SetTransform
给
Direct3D
设备设置世界变换。
SetTransform
接受的第一个参数通知
Direct3D
被设置的是哪个转换。这个例子用
D3DTS_WORLD
宏指定被设置的是世界变换。第二个参数是一个指向被设为当前变换之矩阵的指针。
关于世界变换的更多信息,见:
SDK: World Transformation
定义完场景的世界变换后,你可以准备观察变换矩阵了。再一次请注意:定义任一变换的顺序不是关键。无论如何,
Direct3D
采用以下顺序将这些矩阵作用于场景:
(1)
世界,
(2)
观察,
(3)
映射。
定义观察变换矩阵请参看
第二步:定义观察变换矩阵
第二步:定义观察变换矩阵(View Transformation Matrix)
观察变换矩阵定义了观察的位置和旋转角度。此观察矩阵就相当于场景的摄影机。
以下代码片段创建了一个观察变换矩阵并将其设置为
Microsoft Direct3D
设备的当前观察矩阵。
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 3.0f,-5.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
第一步是通过调用
D3DXMatrixLookAtLH
定义观察矩阵。第一个参数是一个指向
D3DXMATRIX
结构的指针,用来接受操作结果。第二、三、四个参数定义了观察点、注视点、以及方向“上”。这儿设置观察点为沿
Z-
轴
反方向
5
单位再往上
3
单位,注视点为原点,以及作为“上”的方向为
Y-
轴。
下一步是调用
IDirect3DDevice8::SetTransform
给
Direct3D
设备设置观察矩阵。
SetTransform
接受的第一个参数通知
Direct3D
哪一个变换将要被设置。该例程使用
D3DTS_VIEW
标记指定为观察矩阵。第二个参数是一个指向矩阵的指针,它被设为当前的变换。
关于观察矩阵的更多信息,见:
SDK: View Transformation
定义了场景的世界变换后,你可以开始准备映射变换矩阵了。再一次提醒,定义每一变换的顺序不是关键性的。无论如何,
Direct3D
总是采用以下顺序将矩阵应用于场景:
(1)
世界,
(2)
观察,
(3)
映射。
定义映射变换矩阵的工作被描述在
第三步:定义映射变换矩阵
第三步:定义映射变换矩阵(Projection Transformation Matrix)
映射变换矩阵定义了将
3-D
观察空间转换为
2-D
视口空间的几何学方法。
以下代码片段创建映射变换矩阵并将其设为
Microsoft Direct3D
设备的当前映射变换。
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
第一步是调用
D3DXMatrixPerspectiveFovLH
设置映射矩阵。函数第一个参数是一个指向
D3DXMATRIX
的结构,用于接受操作的结果。第二个参数定义视场,它说明物体如何随着距离而缩小。一个典型的视场是
1/4
π,就像这个例子使用的一样。第三个参数定义了屏幕纵横比。本示例采用典型的纵横比
1
。第四和第五个参数定义最近和最远剪切平面。这是用于确定位于何种距离之外的几何物体无需再绘制。本
Matrices
示例设置它的最近剪切平面为
1
,最远剪切平面为
100
。
下一步是调用
IDirect3DDevice8::SetTransfrom
对
Direct3D
应用变换。
SetTransfrom
接受的第一个参数通知
Direct3D
何种变换被设置。本例程使用
D3DTS_PROJECTION
标志指定映射变换将被设置。第二个参数是一个指向矩阵的指针,它将被设置为当前的变换。
关于映射变换的更多信息,参见:“映射变换”
本指南已经提示你如何使用矩阵。指南四:创建和使用光源
将揭示如何在你的场景中添加光源以增加真实性。
(指南四:创建和使用光源
见本文第五部分)
指南四:创建和使用光源
Microsoft Direc3D
光照系统给
3-D
物体提供更多的真实性。当使用它时,每个场景中的几何对象将被照亮,基于它们的位置和使用的光源类型。这个指南的例程将介绍关于光照和材质的主题。
本指南包含以下步骤用于创建材质与光照:
·第一步:创始化场景几何
·第二步:设置材置与光照
注意:
Lights
示例程序的路径为:
(SDK root)/Samples/Multimedia/Direct3D/Tutorials/Tut04_Lights.
注意:
Lights
例程中的代码和
Matrices
例程的代码几乎完全一样。“创建和使用光源”指南仅仅关注于有关创建和使用光照的独特代码,而并不重复有关设置
Direct3D
,处理
Microsoft Windows
消息,绘制,或者清理的内容。关于这些任务的其他信息,见:指南一:创建设备。
本指南使用自定义顶点和顶点缓冲区呈递几何形体。关于选择一个自定义顶点格式并执行顶点缓冲的更多信息,见:指南二:演示顶点。
本指南采用矩阵变换几何对象。关于矩阵和变换的更多信息,参见:指南三:使用矩阵。
第一步:创始化场景几何
使用光照的一个前提是每个表面都应该有法向量。为此,
Lights
例程使用一个稍微不同的自定义顶点格式,新的自定义顶点格式具有一个
3-D
位置坐标和一个表面法向量。这个表面法向量被用于
Microsoft Direct3D
光照计算的核心。
struct CUSTOMVERTEX
{
D3DXVECTOR3 position; // The 3-D position for the vertex.
D3DXVECTOR3 normal; // The surface normal for the vertex.
};
// Custom FVF.
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
现在适当的矢量格式定义好了,
Lights
例程调用
InitGeometry()
,一个程序自定义的函数以创建一个圆柱体。最初的步骤是创建一个顶点缓冲区并用它保存这个圆柱体的各点,如以下例代码所示:
// Create the vertex buffer.
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),
0 /* Usage */, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &g_pVB ) ) )
return E_FAIL;
下一步是使用圆柱体的顶点填充顶点缓冲区。注意下面的示例代码,每个点都被定义了一个位置和一个法向量。
for( DWORD i=0; i<50; i++ )
{
FLOAT theta = (2*D3DX_PI*i)/(50-1);
pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );
pVertices[2*i+0].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );
pVertices[2*i+1].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
}
在前述例程使用圆柱体顶点填充了顶点缓冲区之后,这个顶点缓冲区已经准备好用于呈递了。但是首先,这个场景的材质与光照必须在绘制圆柱体之前被设置。这些描述在
第二步:设置材质与光照
。
第二步:设置材质与光照
为了在
Microsoft Direct3D
中使用光照,你必须创建一个或多个光源。为了确定一个几何物体放射何种颜色的光线,材质必须被创建于绘制几何对象。在绘制这个场景之前,
Lights
例程调用
SetupLights
,一个程序自定义函数来设置材质和一个方向性光源。
创建一种材质
材质被定义为当一束光照到几何物体表面后,反射出的颜色。以下代码片段使用
D3DMATERIAL8
结构来创建一个黄色的材质。
D3DMATERIAL8 mtrl;
ZeroMemory( &mtrl, sizeof(D3DMATERIAL8) );
mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
g_pd3dDevice->SetMaterial( &mtrl );
这个材质的漫射光颜色与环境光颜色都被设为黄色。对
IDirect3DDevice8::SetMaterial
函数的调用将应用此材质到用于绘制场景的
Microsoft Direct3D
设备。
SetMaterial()
接受的唯一参数是设置材质的指针。在这个调用完成以后,每个物件都将使用这个材质绘制直到另一次对
SetMaterial
的调用指定了一个不同的材质为止。
现在材质已经被应用到场景,下一个步骤是创建光源。
创建一个光源
Microsoft Direct3D
里有三种可用的光源:点光源,方向形光源,与聚光灯光源。本示例代码创建一个方向形光源,它向一个方向发光,并且不停的变换发光的方向。
下列代码片段使用
D3DLIGHT8
结构创建一个方向性光源。
D3DXVECTOR3 vecDir;
D3DLIGHT8 light;
ZeroMemory( &light, sizeof(D3DLIGHT8) );
light.Type = D3DLIGHT_DIRECTIONAL;
下列代码片设置光源的漫射光为白色。
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
以下代码片在一个环内旋转光源的方向。
vecDir = D3DXVECTOR3(cosf(timeGetTime()/360.0f),
0.0f,
sinf(timeGetTime()/360.0f) );
D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );
对
D3DXVec3Normalize
函数的调用将归一化方向矢量并初始化光源的方向。
可以设置一个范围告诉
Direct3D
此光源能影响多远的距离。这个成员参数对方向性光源无效。以下代码片指定此光源的范围为
1000
单位。
light.Range = 1000.0f;
下面的代码片将这个光源分配到当前的
Direct3D
设备,通过调用
IDirect3DDevice8::SetLight
。
g_pd3dDevice->SetLight( 0, &light );
SetLight
接受的第一个参数是此光源被分配的索引号。注意如果在此索引已存在一个光源,它将被新光源覆盖。第二个参数是一个指向新定义光源数据结构的指针。本
Lights
例程设置这个光源位于
0
号索引。
下列代码片激活这个光源,通过调用
IDirect3DDevice8::LightEnable
。
g_pd3dDevice->LightEnable( 0, TRUE);
LightEnable
接受的第一个参数是激活光源的索引。第二个参数是一个布尔量通知此光源是开
(TRUE)
还是闭
(FALSE)
。在上面的例程中,索引
0
上的光源被打开。
以下代码片通知
Direct3D
呈递此光源,通过调用
IDirect3DDevice8::SetRenderState
。
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
SetRenderState
接受的头两个参数是哪一个设备状态变量被改写以及写入何种值。本例程设置
D3DRS_LIGHTING
设备变量为
TRUE
,这将使设备能够演示光照效果。
本例程的最后一步是通过再一次调用
SetRenderState
打开环境照明光。
g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );
当前代码段设置
D3DRS_AMBIENT
设备变量为一种浅灰色
(0x00202020)
。环境照明将使用所给的颜色照亮所有的物体。
关于照明及材质的更多信息,参见
SDK:
Lights and Materials。
本例程向你说明了如何使用照明与材质。指南五:使用纹理映射
将向你说明如何将纹理添加到物体表面上。
(指南五:使用纹理映射
见本文第六部分)
指南五:使用纹理映射
尽管光照和材质大大增加了场景的真实感,但没有比在表面上添加纹理更能增加真实感的了。纹理能够被想象为一层紧紧包装在表面的贴纸。你能在一个立方体上放置一层木质纹理使它看起来就象用木头制成的一样。本
Texture
例程将在
指南四:创建和使用光照
中构造的圆柱上添加一幅类似香蕉的纹理。此指南介绍的内容包括如何载入纹理,设置纹理,与呈递带有纹理的物体。
本指南采用以下步骤实现纹理:
·第一步:定义一个定制顶点格式
·第二步:初始化屏幕几何
·第三步:演示场景
注意:
Texture
示例程序的路径为:
(SDK root)/Samples/Multimedia/Direct3D/Tutorials/Tut05_Textures.
注意:除了
Texture
示例不创建材质和光照以外,
Texture
工程中的示例代码与
Lights
工程的几乎完全一样。本“使用纹理映射”指南仅仅关注于有关于纹理的独特代码,而并不重复有关初始化
Microsoft Direct3D
,处理
Microsoft Windows
消息,演示,或清理的内容。关于这些工作的信息,见:指南一:创建设备。
本指南使用自定义顶点和顶点缓冲区显示几何物体。关于选择一个自定义顶点格式并执行顶点缓冲的更多信息,见:指南二:演示顶点。
本指南采用矩阵进行几何变换。关于矩阵和变换的更多信息,参见:指南三:使用矩阵。
第一步:定义一个定制顶点格式
在使用纹理以前,必须使用包含纹理坐标的自定义顶点格式。纹理坐标告诉
Microsoft Direct3D
在物件上如何将纹理定位于每个顶点上。纹理坐标范围从
0.0
到
1.0
,
(0.0, 0.0)
的位置代表纹理贴图的左上角而
(1.0, 1.0)
代表纹理贴图的右下角。
以下示例代码说明了
Texture
例程是如何通过设置它的自定义顶点格式来包含纹理坐标的。
struct CUSTOMVERTEX
{
D3DXVECTOR3 position; // The position.
D3DCOLOR color; // The color.
FLOAT tu, tv; // The texture coordinates.
};
// The custom FVF, which describes the custom vertex structure.
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
关于纹理坐标的进一步信息,参见
SDK:
Texture Coordinates
一章。
现在自定义顶点格式已经准备好了,下一步将是载入一幅纹理并创建一个圆柱体,见
第二步:初始化屏幕几何
。
第二步:初始化屏幕几何
在绘制之前,
Texture
例程调用
InitGeometry
,一个程序自定义的函数用于创建一幅纹理并初始化圆柱体的几何参数。
纹理是由基于文件的图像构造的。以下示例代码使用
D3DXCreateTextureFromFile
从
Banana.bmp
文件创建一幅纹理并用它覆盖圆柱的表面。
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "Banana.bmp",
&g_pTexture ) ) )
return E_FAIL;
D3DXCreateTextureFromFile
接受的第一个参数是一个指向
Microsoft Direct3D
设备的指针,这个设备将用于绘制纹理。第二个参数是一个指向
ANSI
字符串的指针,它指定用于创建纹理的文件名。本例程指定从此文件:“
Banana.bmp
”
来装载图像。第三个参数是一个指向纹理对象指针的地址。
当这个类似香蕉的纹理被装载并准备好之后,下一个步骤是创建圆柱体。以下示例代码用一个圆柱体填充顶点缓冲区。注意每一点都具备了纹理坐标
(tu, tv)
。
for( DWORD i=0; i<50; i++ )
{
FLOAT theta = (2*D3DX_PI*i)/(50-1);
pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0, cosf(theta) );
pVertices[2*i+0].color = 0xffffffff;
pVertices[2*i+0].tu = ((FLOAT)i)/(50-1);
pVertices[2*i+0].tv = 1.0f;
pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0, cosf(theta) );
pVertices[2*i+1].color = 0xff808080;
pVertices[2*i+1].tu = ((FLOAT)i)/(50-1);
pVertices[2*i+1].tv = 0.0f;
}
每一个顶点包括位置,颜色,以及纹理坐标。上面的例程给每一点设置了纹理坐标并使此纹理能够平滑的包裹在圆柱体周围。
现在纹理和顶点缓冲区已经准备好用于演示了,现在能够呈递和着色图形了,参见
第三步:演示场景
。
第三步:演示场景
在场景几何被初始化之后,应该是绘制场景的时候了。为了绘制一个带有纹理的物体,使用的纹理必须要设置成当前纹理中的一个。下一步将是设置纹存储器的状态。纹理存储器状态使你能够定义一个或者多个纹理被呈递的方式。比如说,你能将多个纹理混合在一起。
现在
Texture
示例开始设置需要使用的纹理。以下代码段使用
IDirect3DDevice8::SetTexture
设置
Microsoft Direct3D
设备用于绘制的纹理。
g_pd3dDevice->SetTexture( 0, g_pTexture );
SetTexture
接受的第一个参数是设置纹理存储器的标示符。一个设备能够支持八个已初始化的纹理,所以这儿的最大值是
7
。本
Texture
示例仅仅使用一个纹理并且把它设置在存储器
0
。第二个参数是一个指向纹理对象的指针。在这儿,
Texture
示例使用由它的程序自定义函数
InitGeometry
创建的纹理。
以下代码片设置纹理存储器状态的值,通过调用
IDirect3DDevice8::SetTextureStageState
方法。
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
SetTextureState
的第一个参数是需要改变状态的存储器的索引。本示例代码改变位于存储器
0
的纹理,所以这儿置为
0
。下一个参数是要设置的纹理状态。关于所有有效的纹理状态以及它们的意义,见
"SDK: D3DTEXTURESTAGESTATETYPE"
。再下一个参数是设置为此纹理状态的参数。你放置这儿的值应取决于你要改变的纹理存储器状态。
在设置完每个纹理存储器状态的合适值之后,这个圆柱体可以被呈递了,现在纹理将被添加在它的表面上。
使用纹理坐标的其他方法是使它们自动的生成。这是用一种纹理坐标索引
(TCI)
实现的。
TCI
使用一个纹理矩阵来变换
(x,y,z) TCI
坐标为
(tu, tv)
纹理坐标。在
Texture
例程中,位于摄像机空间中的顶点位置被用来产生纹理坐标。
第一步是创建用于转换的矩阵,示范在以下代码片段中:
D3DXMATRIX mat;
mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f;
mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f;
mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f;
mat._41 = 0.50f; mat._42 = 0.50f; mat._43 = 0.00f; mat._44 = 1.00f;
在矩阵创建好之后,它必须通过调用
IDirect3DDevice8::SetTransform
来设置它,如以下代码段所示:
g_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat );
D3DTS_TEXTURE0
标志告诉
Direct3D
应用此变换到位于纹理存储器
0
的纹理。本示例的下一步是设置其他的存储器状态值,以得到所需的效果。这些处理在以下代码段中。
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION );
纹理坐标被设置后,现在此场景已准备好被呈递了。注意到现在的坐标是自动设置到圆柱上的。这样精确的设置使几何物体被演示时纹理好象是覆盖在绘制的屏幕上。
关于纹理的更多信息,见
SDK: Texture
一章。
本指南已经向你说明了如何给表面添加纹理。指南六:使用
Mesh
模型
将告诉你如何应用
Mesh
模型呈递复杂的几何形体。
(指南六:使用
Mesh
模型
见本文第七部分)
指南六:使用
Mesh
模型
复杂的几何形状常常使用
3-D
建模软件构造模型并保存为文件。一个例子就是
.x
文件格式。
Microsoft Direct3D
使用
Mesh
对象从文件装载这些物体。
Mesh
对象稍微有点复杂,但是
Microsoft Direct3DX
包含的函数使应用
Mesh
对象变的简单。
Meshed
例程介绍关于
Mesh
的话题并展示如何装载,演示,以及卸载一个
Mesh
对象。
本指南使用以下步骤说明如何装载,演示,以及卸载一个
Mesh
对象:
·第一步:装载一个
Mesh
对象
·第二步:演示一个
Mesh
对象
·第三步:卸载一个
Mesh
对象
注意:
Methes
示例程序的路径为:
(SDK root)/Samples/Multimedia/Direct3D/Tutorials/Tut06_Meshes.
注意:除了
Meshes
工程中的示例代码不创建材值与光照以外,此工程的示例代码与
Lights
工程几乎完全一样。“使用
Mesh
模型”指南仅仅关注于有关于
Mesh
对象的独特代码,而并不重复有关设置
Microsoft Direct3D
,处理
Microsoft Windows
消息,演示,或清理的工作。关于这些工作的信息,见:指南一:创建设备。
本指南使用自定义顶点和顶点缓冲区显示几何物体。关于选择一个自定义顶点格式并执行顶点缓冲的更多信息,见:指南二:演示顶点。
本指南采用矩阵进行几何变换。关于矩阵和变换的更多信息,参见:指南三:使用矩阵。
本指南使用纹理覆盖
Mesh
模型的表面。关于装载和使用纹理的更多信息,参见:指南五:使用纹理映射。
第一步:装载一个Mesh对象
在使用之前,
Microsoft Direct3D
应用程序必须先装载一个
Mesh
对象。
Meshes
例程通过调用
InitGeometry
,一个该程序自定义的函数,装载一只虎的
Mesh
模型,当然这是在已经装载了必需的
Direct3D
对象以后。
一个
Mesh
对象需要用一个材质缓冲保存所有将要用到的材质与纹理。所以该函数最初定义了一个材质缓冲,如以下代码段所示:
LPD3DXBUFFER pD3DXMtrlBuffer;
以下代码段使用
D3DXLoadMethFromX
函数装载
Mesh
对象。
// Load the mesh from the specified file.
if( FAILED( D3DXLoadMeshFromX( "tiger.x", D3DXMESH_SYSTEMMEM,
g_pd3dDevice, NULL,
&pD3DXMtrlBuffer, &g_dwNumMaterials,
&g_pMesh ) ) )
return E_FAIL;
D3DXLoadMeshFromX
接受的第一个参数是一个指向字符串的指针告诉
Microsoft Direct3D
要装载的文件。本例程从
Tiger.x
读取一只虎的
Mesh
模型。
第二个参数通知
Direct3D
如何创建
Mesh
对象。本示例采用
D3DXMESH_SYSTEMMEM
标记,它等于同时指定
D3DXMESH_VB_SYSTEMMEM
与
D3DXMESH_IB_SYSTEMMEM
,这两个参数告诉
Direct3D
把
Mesh
对象的索引缓冲区和顶点缓冲区都放到系统内存中。
第三个参数是指向将被用于绘制
Mesh
对象的
Direct3D
设备的指针。
第四个参数是一个指向
ID3DXBuffer
对象的指针。这个对象装入关于各个面相邻与否的信息。在本例程中此信息是不需要的,所以这个参数被设为
NULL
。
第五个参数同样取得一个指向
ID3DXBuffer
的指针。在函数执行完以后,此对象将被填入该
Mesh
对象使用的
D3DXMATERIAL
结构。
第六个参数是一个指针,指向函数执行结束后,返回的置入
ppMaterials
队列中的
D3DXMATERIAL
结构数目。
第七个参数是一个
Mesh
对象指针的地址,返回装载的
Mesh
对象。
在装载了这个
Mesh
对象和相关材质信息之后,你需要从材质缓冲区中分解出材质属性及纹理名称。
本
Mesh
例程先需要得到材质缓冲区指针才能处理这些事情。以下代码段使用
ID3DXBuffer::GetBufferPointer
函数得到这个指针。
D3DXMATERIAL* d3dxMaterials =
(D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
以下代码段创建了一个新的
Mesh
和纹理对象基于
Mesh
对象中材质的最大数目。
g_pMeshMaterials = new D3DMATERIAL8[g_dwNumMaterials];
g_pMeshTextures = new LPDIRECT3DTEXTURE8[g_dwNumMaterials];
对于每个
Mesh
对象里的材质都必须进行以下步骤。
第一步是拷贝材质,如以下代码段所示
.
g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
第二步是设置材值的环境色,见以下代码段。
g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;
最后一步是为该材质创建纹理,如以下代码段。
// Create the texture.
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
d3dxMaterials[i].pTextureFilename,
&g_pMeshTextures[i] ) ) )
g_pMeshTextures[i] = NULL;
}
装载了每个材质以后,你使用完毕了这个材质缓冲区,必须调用
IUnknown::Release
来释放它。
pD3DXMtrlBuffer->Release();
现在,
Mesh
对象,连同其相应的材质与纹理都已经装载好了。这个
Mesh
物体已准备好呈递到屏幕上,参看
第二步:演示一个
Mesh
对象
。
第二步:演示一个Mesh对象
在第一步中,
Mesh
对象已经准备号被呈递了。该对象被
Mesh
对象装载的每个材质分成若干个子集。为了绘制每个子集,应该在一个循环中绘制此
Mesh
对象。循环的第一步是为每个子集设置材质,如以下代码段所示:
g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] );
循环的第二步是给每个子集设置纹理,如以下代码段所示。
g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );
在给每个子集设置完材质与纹理之后,子集被
ID3DXBaseMesh::DrawSubset
函数所绘制,如以下代码段所示。
g_pMesh->DrawSubset( i );
DrawSubset
函数带有一个
DWORD
参数用于指定
Mesh
对象的哪个子集被绘制。本例程使这个参数的值每循环一次就被加一。
在使用完
Mesh
对象之后,重要的事是要将此
Mesh
对象完全移出内存,参见
第三步:卸载一个
Mesh
对象
。
第三步:卸载一个Mesh对象
在任何
Microsoft Direct3D
程序结束前,它有必要解构它使用的所有
DirectX
对象并且使指向它们的指针无效。本例程使用的
Mesh
对象同样需要被解构。当它接收到一个
WM_DESTROY
消息时,
Meshes
例程调用
Cleanup
,一个该程序自定义的函数,来处理此事。
以下代码段删除材质队列。
if( g_pMeshMaterials )
delete[] g_pMeshMaterials;
以下代码解构每个装载过的单独纹理并删除纹理队列。
if( g_pMeshTextures )
{
for( DWORD i = 0; i < g_dwNumMaterials; i++ )
{
if( g_pMeshTextures[i] )
g_pMeshTextures[i]->Release();
}
delete[] g_pMeshTextures;
以下代码段解构
Mesh
对象。
Delete the mesh object
if( g_pMesh )
g_pMesh->Release();
本指南已经向你说明了如何装载和绘制
Mesh
对象。这是此区域最后一个指南。如果需要了解一个典型的
Direc3D
应用程序是如何写成的,见:
"SDK: DirectX Graphics C/C++ Samples"
。
(
DirectX
图形接口指南(
1
)
~
(
7
)
全文粘贴完毕,Data 2002. 8. 1
)
-----------------------------------------------------------------------
DirectX图形接口指南 译者:In355Hz 电子邮箱: In355Hz@hotmail.com
-----------------------------------------------------------------------
DirectX 图形接口指南:
(应用于 DirectX 8.1 版 C/C++ 编程)
本区域的指南将说明如何在
C/C++
程序中使用
Microsoft Direct3D
和
Direct3DX
完成一些普通的工作。这些工作总是被分解成若干个必要的步骤。在某些情况下,为了使表达更清楚,一些步骤还被细分成几个子步骤。
本区域提供的指南有:
·指南一:创建设备
·指南二:演示顶点
·指南三:使用矩阵
·指南四:创建和使用光源
·指南五:使用纹理映射
·指南六:使用Mesh模型
提示:指南中出现的示例代码来自于每个指南具体提供的路径里的源文件。
这些指南中的源代码是用
C++
写成的。如果使用
C
编译器,你必须适当的改变这些文件使它们能够编译通过。最少的,你需要加入
vtable
然后用它引用接口函数。
包含在示例代码中的一些注解可能与来自
Microsoft Platform Software Development Kit (SDK)
中的源代码不同。这些改变仅仅为了简化表述并且只限于注解中,这样能够防止示例程序的行为被改变。
(见本文第二部分 指南一:创建设备 )