让人很不爽的前两天装的directX9(decemeber)版和我看的这本《Direct3D游戏编程入门教程》有版本冲突。书里边使用了 direct3D自己带的框架,而这个框架和我装的这个directX9是不一样的,听说这个版本包含了许多directX10的东西,可能是这个原因吧。
我反复想是用新的框架还是装回较早的版本,看了directX自带的tutorail和文档是英文的,不利于我速成。要是用原来的版本呢,可能换回来还需要一些代价。想来想去最后还是把原来那个卸了,装回原来的版本。先速成再说。
好,下面进入第5章的第一个例子-Basic。
这个是d3d通用框架中的应用程序基类,在WinMain()里边声明一个CD3DApplication对象,然后调用其Run()方法程序就跑起来了。简单代码如下:
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
CMyD3DApplication d3dApp;
InitCommonControls();
if( FAILED( d3dApp.Create( hInst ) ) )
return 0;
return d3dApp.Run();
}
我们再来看一下CMyD3DApplication的声明:
class CMyD3DApplication : public CD3DApplication
{
LPDIRECT3DVERTEXBUFFER9 m_pVB; //vertice buffer的指针
DWORD m_dwSizeofVertices; //顶点数
protected:
HRESULT OneTimeSceneInit();
HRESULT InitDeviceObjects();
HRESULT RestoreDeviceObjects();
HRESULT InvalidateDeviceObjects();
HRESULT DeleteDeviceObjects();
HRESULT FinalCleanup();
HRESULT Render();
HRESULT FrameMove();
HRESULT ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat );
public:
CMyD3DApplication();
};
也很简单,两个成员变量的含义已经注释出来。需要说明一下的就是该程序使用vertex buffer来处理顶点,也就是直接把顶点复制到显卡可以直接访问到的驱动程序缓冲中,这样就不必每次复制顶点,提高了效率。下面介绍一下该类的方法的调用:
- 程序启动的执行顺序是:ConfirmDevice()->OneTimeSceneInit()->InitDeviceObject()->RestoreDeviceObjects().
- 程序运行期间会执行一个循环:FrameMove()->Render()
- 如果运行期间改变窗口大小,框架会调用:InvalidateDeviceObjects()->RestoreDeviceObjects();
- 如果通过F2或者菜单来更改设备(HAL或REF),调用:InvalidateDeviceObjects()-> DeleteDeviceObjects()->InitDeviceObjects()->RestoreDeviceObjects();
- 程序退出时执行:InvalidateDeviceObjects()->DeleteDeviceObjects()->FinalCleanUp().
下面说一下具体函数的含义:
- ConfirmDevice():最先被执行,用来检查显卡能力,如果显卡不支持,框架会切换到使用参考光栅器,或切换为顶点软件处理。具体参数见教材。
- OneTimeSceneInit():一次性永久初始化,初始化与设备无关的东西,与FinalCleanUp()搭配,初始化的数据可以在FinalCleanUp()中销毁。
- InitDeviceObjects():初始化与设备相关的对象,如果通过F2使设备发生改变,那么就需要重新执行该初始化。与DeleteDeviceObjects()搭配。
- InvalidateDeviceObjects():对于窗口的大小改变做出响应。
- RestoreDeviceObjects():和InvalidateDeviceObjects()搭配,可以在窗口大小改变时重新设置投影矩阵和渲染状态等等。除了在程序开始时以为,都会和InvalidateDeviceObjects()成对调用。
- DeleteDeviceObjects():在设备改变时对设备资源进行销毁。
- Render():作为3D渲染的入口点在每一帧时被调用,可以设置render state,clear buffer,渲染场景。
- FrameMove():容纳所有动画的代码。
- FinalCleanUp():销毁几何数据和文件对象等等非设备资源。
OK,了解了执行过程,下面看一下重要步骤。
在Basic例子程,程序较为简单,绘制了一个无须任何坐标变换和投影的四边形,并用 m_d3dEnumeration.AppUsesDepthBuffer = FALSE;设置了不使用深度缓存。这里边重要的方法就是RestoreDeviceObjects()中创建顶点缓冲区:
m_pd3dDevice->CreateVertexBuffer( m_dwSizeofVertices, D3DUSAGE_WRITEONLY, FVF,D3DPOOL_MANAGED,&m_pVB, NULL )
这里m_dwSizeofVertices是顶点数,m_pVB是缓冲区指针,比较好理解。FVF表示每个顶点的表示形式,定义成const DWORD FVF = (D3DFVF_XYZRHW | D3DFVF_DIFFUSE);表示每个顶点由(x,y,z,rhw,diffuse)构成,direct3D的顶点表示还有specular, normal,纹理等信息,分别对应不同的变量组合。
D3DPOOL_MANAGED是指定了D3D的资源管理器,负责对于纹理和几何数据实施统一管理。D3D的资源管理器分成五种:
- D3DPOOL_DEFAULT:资源存储在AGP或显存中,在顶点缓冲或索引缓冲经常更新的情况下使用,避免内存到显存的拷贝“过慢”。对于永远不变的纹理,用默认池就是一种好的选择。
- D3DPOOL_MANAGED:托管池,资源存储在AGP或者显存中,并在系统内存中有一份拷贝。只有内存发生变化才需要拷贝到显存,如果性能不是最重要的,托管池永远是一种最安全的选择。
- D3DPOOL_SYSTEMMEN:系统池,存储在系统内存中,设备丢失后(在全屏和窗口模式切换时或者改变分辨率)资源不需要重建。
- D3DPOOL_SCRATCH:临时池,资源存储在系统内存中,且设备丢失时无法重建,连同CreateOffScreenPlainSurface()一起使用,用于创建图像表面。
- D3DPOOL_FORCE_DWORD:
创建顶点缓冲器之后,是Lock()顶点缓冲器,然后执行memcpy()拷贝顶点,之后UnLock().这里Lock()包含四个参数, offsetToLock是锁定顶点缓冲区从哪个偏移开始,SizeToLock是锁定的大小,ppbData是返回指向内存缓冲区的指针,最后一个是指定如何使用顶点缓冲器.
最后看一下Render()方法:
HRESULT CMyD3DApplication::Render()
{
// Begin the scene
if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
{
// In DX8: m_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
// Passing an FVF to IDirect3DDevice9::SetFVF specifies a legacy FVF with stream 0.
m_pd3dDevice->SetFVF(FVF ); // new in DX9
// DX8: only three parameters. In DX9 the third parameter is new
m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(VERTEX) );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
// End the scene.
m_pd3dDevice->EndScene();
}
return S_OK;
}
Render()方法中首先使用m_pd3dDevice初始化一个场景 BeginScene(),使场景处于处理过程中,这样后边的绘制才会奏效,否则都会返回D3DERR_SCENE_NOT_IN_SCENE的错误。结束绘制以后再调用EndScene()清除标识场景处于处理过程的标志,刷新缓存数据以及确认渲染表面完好。
SetFVF()只有一个参数,就是顶点的结构,该方法仅用于固定流水线,对于使用shader的情况要调用SetVertexShader().
SetStreamSource()设置了数据流,DrawPrimitive()把数据渲染出来。
over!
原文地址:http://blog.sina.com.cn/u/40d00f170100012z