DirectX 9 Graphics the Definitive Guide to Direct3D第二章

龙儿对于这个CSDN无话可说,翻译了一下午就这么没了,还好我还保存了部分底稿。现在只能把那一部分提供给大家了,希望大家不要见怪啊。本来我是把书上的代码截屏放在这译文里,但图片又挂了,所以龙儿还是用帖我自己的代码吧。


IDirect3D9 *Direct3DCreate9(          UINT SDKVersion
);


其中SDKVersion 的值必须为D3D_SDK_VERSION
这个函数用起来实在简单,我们只需要把D3D_SDK_VERSION传给函数来确定我们要用的DirectX的版本。一旦成功,这个函数就会返回一个Direct3D物体的指针。这个指针我们将会贯穿整个应用。创建Direct3D物体的代码如下:
            IDirect3D9* g_pD3D = NULL;
            if(NULL == (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
            return E_FAIL;


现在我们有了一个Direct3D应用,这个物体能被借来帮助我们完成这个应用,准备画一些东西。首先就要创建一个Direct3D设备。
 
第三步——创建Direct3D设备
在上一步我们说Direct3D物体(IDirect3D9)Direct3D应用的生命线,它基本上是从程序开始的时候创建,结束的时候销毁,还用来创建别的东西。在这一步我们用IDirect3D9来创建最重要的一个东西:Direct3D设备,这是一个IDirect3DDevice类型的COM接口。如果你想在屏幕上画什么东西,它是最基本的。它代表了电脑的显卡或者其他绘图的硬件。但值得注意的是一个Direct3D设备只能代表一张显卡,如果你要对两张卡编程,你就要创建两个设备。每一个设备有一个独特的ID来与其他设备区分。本书只集中在只用一个设备。主图形设备连接到系统。
 
Direct3D中,设备有以下两种类型:
HAL设备
主要的设备类型,本书用到的也是这个。它代表了硬件抽象层。这个设备类型包括了主要的3D加速卡来玩游戏。
Reference 设备
这是一个独有的软件设备,它支持所有的Direct3D特性。但是这个设备很慢,经常被开发人员用来测试那些将要在硬件上实现的特点。本书不使用这种类型。
创建设备
Direct3D设备被IDirect3D9CreateDevice函数创建,这个函数要求几个参数,包括将要被告创建的设备所特有的ID,设备类型,句柄,一些行为标志来确定创建的设备如何操作。一旦成功,这个函数将返回一个可用的IDirect3DDevice指针。CreateDevice函数语法如下:
HRESULT CreateDevice(          UINT Adapter,
    D3DDEVTYPE DeviceType,
    HWND hFocusWindow,
    DWORD BehaviorFlags,
    D3DPRESENT_PARAMETERS *pPresentationParameters,
    IDirect3DDevice9** ppReturnedDeviceInterface
);


UINT Adapter
序数词指示显卡,这个参数代表要用的设备。本书用D3DADAPTER_DEFAULT来使用主显卡。
D3DDEVTYPE DeviceType
D3DDEVTYPE枚举的成员,指示想要用的设备类型,如果想用的设备类型不可用,那么函数会失败。本书这个值设为D3DDEVTYPE_HAL
HWND hFocusWindow
窗口的句柄来与所创建的设备进行关联。IDirect3DDevice将把这个窗口当作画纸来画东西。这个值将是你在第一步中创建窗口的句柄。
DWORD BehaviorFlags
一个或者多个标志来指明设备如何行动。本书使用D3DCREATE_SOFTWARE_VERTEX-PROCESSING。目前不用太关心这个参数的重要性。
D3DPRESENT_PARAMETERS *pPresentationParameters
这是一个指向D3DPRESENT_PARAMETERS结构体的指针。它将确定你所创建的设备如何操作。使用这个结构体你能指定其他事项,屏幕分辨率,应用是以全屏模式还是窗口模式。结构体如下:
typedef struct _D3DPRESENT_PARAMETERS_ {
    UINT BackBufferWidth, BackBufferHeight;
    D3DFORMAT BackBufferFormat;
    UINT BackBufferCount;
    D3DMULTISAMPLE_TYPE MultiSampleType;
    DWORD MultiSampleQuality;
    D3DSWAPEFFECT SwapEffect;
    HWND hDeviceWindow;
    BOOL Windowed;
    BOOL EnableAutoDepthStencil;
    D3DFORMAT AutoDepthStencilFormat;
    DWORD Flags;
    UINT FullScreen_RefreshRateInHz;
    UINT PresentationInterval;
} D3DPRESENT_PARAMETERS;


同样别担心对某些参数不理解。很多可以被留白,大部分在本书以程序的形式解释。为了参考,对这个结构体做了下简单的描述。
UINT BackBufferWidth, BackBufferHeight
指定后台缓冲的宽度和高度。如果你的程序是以全屏模式运行,那这两个值必须与你的屏幕分辨率匹配。如果你的程序是以窗口模式运行,那这两个参数可以是任意值。0表示后台缓冲的尺寸与窗口尺寸相同。
D3DFORMAT BackBufferFormat
这是一个D3DFORMAT的枚举类型。它指明了后台缓冲的颜色格式,像256色,或者16位、24位、32位颜色。它也定义了RGBAlpha如何分配。有很多可能的值。你也能设为D3DFMT_UNKNOWN来表明不知道格式。
UINT BackBufferCount
你想要的后台缓冲的数量。可以是0或者更大。大多数情况下设为1
D3DMULTISAMPLE_TYPE MultiSampleType
多重采样可以达到生动的效果。像抗锯尺,动态模糊等等。通常情况下你不需要它,所以你可以传它一个D3DMULTISAMPLE_NONE
DWORD MultiSampleQuality
指定质量,这个参数可以被留白当MultiSampleType被设为D3DMULTISAMPLE_NONE时。
D3DSWAPEFFECT SwapEffect
描述后台缓冲如何行动。基本上总是设为D3DSWAPEFFECT_DISCARD
HWND hDeviceWindow
想要渲染的窗口的句柄
BOOL Windowed
程序以哪种模式运行,TRUE表示以窗口模式运行,FALSE表示以全屏模式运行。
BOOL EnableAutoDepthStencil
通常设为FALSE,设为TRUE的话将允许DirectX来管理你的浓度缓存。
D3DFORMAT AutoDepthStencilFormat
如果EnableAutoDepthStencil设为TRUE的话,你就要为你的浓度缓存指定一个格式,像BackBufferFormat一样。
DWORD Flags
通常你可以把它设为D3DPRESENTFLAG_LOCKABLE_BACKBUFFER或者留白。
UINT FullScreen_RefreshRateInHz
定义屏幕每秒刷新次数。像75就意味着每秒刷新75次。但在窗口模式下这个值必须为0
UINT PresentationInterval
指定后如缓存呈现的速度。在窗口模式下,这个值必须为D3DPRESENT_INTERVAL_DEFAULT,你也可以在任一应用中使用这个值。
IDirect3DDevice9** ppReturnedDeviceInterface
返回的指向IDirect3DDevice接口指针的地址。一旦函数调用成功,一个可用的指针将会被放在这里。
一个创建IDirect3DDevice的例子:
	D3DPRESENT_PARAMETERS d3dp;
	d3dp.AutoDepthStencilFormat = D3DFMT_D24S8;
	d3dp.BackBufferFormat = D3DFMT_A8R8G8B8;
	d3dp.BackBufferCount = 1;
	d3dp.BackBufferHeight = CY;
	d3dp.BackBufferWidth = CX;
	d3dp.EnableAutoDepthStencil = TRUE;
	d3dp.Flags = 0;
	d3dp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	d3dp.hDeviceWindow = m_hwnd;
	d3dp.MultiSampleQuality = 0;
	d3dp.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
	d3dp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dp.Windowed = TRUE;

	hr = pid->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dp, &m_device);

	if (FAILED(hr))
	{
		return FALSE;
	}


 
或者来创建一个全屏的Direct3D设备。记住,创建一个全屏设备,Direct3D会自动进入一个全屏模式并将电脑分辨率改为你所设置的。
代码跟上面差不多,只有一点不同。
	D3DPRESENT_PARAMETERS d3dp;
	d3dp.AutoDepthStencilFormat = D3DFMT_D24S8;
	d3dp.BackBufferFormat = D3DFMT_A8R8G8B8;
	d3dp.BackBufferCount = 1;
	d3dp.BackBufferHeight = CY;
	d3dp.BackBufferWidth = CX;
	d3dp.EnableAutoDepthStencil = TRUE;
	d3dp.Flags = 0;
	d3dp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	d3dp.hDeviceWindow = m_hwnd;
	d3dp.MultiSampleQuality = 0;
	d3dp.MultiSampleType = D3DMULTISAMPLE_NONE;
	d3dp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
	d3dp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dp.Windowed = FALSE;

	hr = pid->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hwnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dp, &m_device);

	if (FAILED(hr))
	{
		return FALSE;
	}


更多关于Direct3D设备
你已经看到Direct3D设备如何代表绘图硬件,也明白了它对Direct3D应用的重要性。这一部分就IDirect3DDevice能做什么提供一个简单的概述。这些将会在后面进行详细的解释。
    Direct3D设备能做以下事甚至更多:
将一个场景渲染到窗口
    一个Direct3D设备将被用来在与它相关联的窗口上一帧一帧的画图。在这一章的后面,Direct3D设备将从文件中加载一幅画并在窗口中画出来。我们将组合它的函数来实现,这个将会在后面解释。
询问设备能力
    IDirect3DDevice告诉我们很多硬件的表现。使用它的GetDeviceCaps函数来填充D3DCAPS9结构体。我们通过检查它的属性来知道我们的硬件能做什么,不能做什么。函数原型如下
HRESULT GetDeviceCaps(          D3DCAPS9 *pCaps
);


设置光标图像
    IDirect3DDevice能被用来显示光标图像并设置它在屏幕中的位置。这将在后面出现。当我们用SetCursorPositionSetCursorProperties函数时。
创建和管理图形资源
    Direct3D设备能在内存中创建图形资源。像从文件中加载图形或者3D模型。
模仿3D环境
    IDirect3DDevice提供函数来使3D模型在3D空间中并正确的将它们在窗口中画出来。所有的物体都会被画出来根据它们离摄像机的距离。它也会保证那些离摄像机近的将会遮住远的。
第四步——配置消息循环
窗口在第一步中已经创建,第二步有了Direct3D物体,第三步有了Direct3D设备。现在如果你编译并运行你的程序,你会发现一个问题。它根本不运行。但它确实运行过,只是很快你没看到。这是因为没有消息泵。通常一个应用程序都会进入一个消息循环。这个循环会一直继续直到用户退出。在这期间,应用程序接收和发送因事件发生而产生的消息。当用户退出时,WM_QUIT消息就产生了。消息循环退出,程序结束。代码如下:
	while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
	{
		
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		
	}


这种循环可能是你现在所用的标准循环。它对windows应用非常有用因为它意味着它消耗较少的处理器的时间,毕竟它只需坐在这附近,当有事件发生时传递下消息。这也意味着windows应用程序之间彼此互不干涉。它们只有在收到指示时消耗CPU资源,也不妨碍太多。但游戏不同。
 
游戏是贪婪的。它们需要各种不同的消息循环,它不像标准的循环。相反,它需要大量的资源,原因如下:
图形
游戏需要确保他们的图形每秒被更新多少次来保证动画的流畅。每秒重画的次数就是所谓的FPS
输入
游戏需要有一个精确的认识,用户在什么时候按下了哪个键来保证游戏做出正确的反应。
定时
游戏需要一个很精确的定时器,这是因为很多事件,像对口型,需要被同步。
windows的标准消息循环可以通过修改来适应游戏所需。代码如下:
	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		} 
		else
		{
			m_direct.Display();
		}
	}


这个游戏循环不断的调用我应用程序中为处理游戏数据所预留的Render()函数,也将要画的图在屏幕上显示出来。你也可以在这里调用你自己的函数。接下来我们检查一下Direct3D设备是如何在循环中呈现一幅场景。

龙儿唯一能再为大家做的就是提供这一章的源码了,这是龙儿自己写的。可能有些地方没涉及到,还请大家多多包涵啊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值