下沙论坛

标题: 一个最简单的DirectX9(D3D) 的例子 [打印本页]

作者: 游侠无极限    时间: 2005-4-7 16:13
标题: 一个最简单的DirectX9(D3D) 的例子
Andy Pike 的DirectX 8 教程第一章,具体的程序不一样点% a4 s5 m! d" J; j/ g. G" o/ L
我总觉得用多线程更容易理解……
, M) Y+ e- z+ Q1 h k9u5gRfj.rar (87.25 KB, 下载次数: 403)
作者: 游侠无极限    时间: 2005-4-7 16:23

DirectX 8 教程

著 Andy Pike

www.andypike.com

译 Aman JIANG

www.AmanPage.com

第一章: 准备就绪

What you will need (你需要什么)

Introduction ()

(原著的话)

欢迎阅读本DX教程。本教程至少能帮你入门、使你了解怎样用DX8 来开发Windows游戏。我写这个教程的原由有二:首先,当出现DX时,我还是一个初学者。所以,我想边学习边写一个教程来锻炼自己。其次,对初学者来说,DX SDK 并不是很有帮助。而且,网上也没有什么像样的Dx8教程。另外,就像上面我提到的,我也是个初学者,所以,如果你发现教程中有什么地方不对,请给我写信:webmaster@andypike.com

译者言

我也是一名初学者,所以,有言在先:如果你读英文能如履平地,建议你还是去读原著。此教程很适合入门,等你入门以后,你会发现,其实一切并没有想象的那样复杂。这是个不错的Dx8教程,我会尽最大努力把它翻译好。注:我并没有完全按照原著来译,不适之处,请多包涵。嗯,你应该弄到教程附带的源代码,没有那个可不行!可以到www.andypike.com去下载。欢迎指出我的错误,或与我联系,我的Email:Chaoyu_JIANG@hotmail.com or Aman_JIANG@163.com , QQ:15852673。

COM

What is COM? COM 是什么呢?COM 就是 Component Object Model, 组件对象模型。COM 接口和C++的抽象类相似(但不一样),就像抽象类没有与之相关的实际代码一样,COM描述了一套符号和语法而非实现过程。你也可以把 COM 对象就想象成一套为某个主题而设计的一整套库函数。DX 就提供了一套完整的设计3D游戏的库。最棒的就是,使用DX时,你不必去直接接触硬件,而由DX帮你代理了。这使得一些事情变得简单了。

使用 COM 时应该注意,必须在程序结束前释放所有的 COM 对象(或接口)。而且,释放它们的顺序应该和创建它们的顺序相反。就像这样:

1. Create interface A.

2. Create interface B.

3. Release interface B.

4. Release interface A.

调用它们的 Release 模块来释放它们。

Page Flipping (页翻动)

页翻动又是什么呢?嗯,你知道电影的原理吗?电影通过以每秒钟24幅的速度连续的闪动图像,每幅图像之间的差别又很小,由于人眼的滞留作用,我们看到的画面就是连续的了。这不难理解。其实,DirectX 也是这样工作的。我们把要显示的物体通通绘制到一个不可见的页上,我们称这个页为“后缓冲区”。绘制完后,快速的把它翻动到可见的“前缓冲区”上,并重复这个过程。当用户正在观看新绘制的可见页(前缓冲区)时,程序要降下一幅要显示的东西绘制到“后缓冲区”上。快速而连续的重复次过程,用户就会看到像电影一样连续的图像了。不过一般情况下,我们每秒钟能绘制的页数要比电影多很多。

如果我们不是用页翻动技术,那用户看到的屏幕中的物体,将会一个个的被绘制出来,虽然速度可能很快,但效果会很差,那并不是我们想要的。

所以,我们的游戏需要一个循环,称之为“Game Loop”。每次循环,我们都要清除“后缓冲区”,把该绘制的物体按照一定的逻辑都绘制到那上面,然后把它翻动到“前缓冲区”上,然后进入下一次循环。这个循环得直到游戏退出了才能结束。有时我们可能需要好几个这样的“后缓冲区”(多缓冲)来组成一个“交换链”(Swap Chain),以求更好的效果。

Devices (设备)

What is a device? 设备是什么?简单的说,就是你的3D卡。 你得创建一个接口来代表设备,然后使用那个接口来绘制东西。

Game Loop (游戏循环)

什么是游戏循环呢?游戏循环是一段代码,在游戏退出之前循环执行的代码。这段代码在每次循环中都要:在屏幕上绘制物体(或场景人物随便什么)、处理游戏的逻辑过程(如:物体的移动、人工智能等等)、处理Windows的消息等等。基本上就是这样了。

Creating Your First Project (创建你的第一个项目)

译者:嗯,这部分我就不用译了吧,这可是基础的东西。不过还是说说初学者容易忽略的一点:一定要把你的DX SDK的Include目录和Lib目录的路径添加到VC的目录设置列表中去,而且不要把Include和Lib的地方放错了,而且还要放在第一位。还要把d3d8.lib添加到项目设置的Lib列表中,否则编译不了。

Okay, that’s enough theory lets get started. Follow the step-by-step guide below to create your first DirectX Graphics project.

  1. In Visual C++ create a new Win32 Application.

    1. File > New

    2. From the Projects tab select Win32 Application

    3. Enter a name for your project such as “DX Project 1”

    4. Select a folder for the location of your source code files

    5. Click Next

    6. Select the empty project option.

    7. Click Finish

  2. Make sure that your project settings are correct.

    1. Project > Settings...

    2. On the Link tab, make sure that "d3d8.lib" is in the list of Object/Library Modules. If it isn’t simply type it in.

  3. Make sure that your search paths are correct.

    1. Tools > Options > Directories Tab

    2. In the "Show directories for" drop-down, select "include files".

    3. If it does not exist already, add the following path: <SDK INSTALL PATH>\include.

    4. Make sure that this path is at the top of the list by clicking on the up arrow button (if needed).

    5. In the "Show directories for" drop-down, select "library files".

    6. If it does not exist already, add the following path: <SDK INSTALL PATH>\lib.

    7. Make sure that this path is at the top of the list by clicking on the up arrow button (if needed).

  4. Add the source code.

    1. File > New

    2. From the Files tab, select C++ Source File

    3. Enter a filename such as “Main.cpp”

    4. Copy the code segment below, and then paste it into your new file.

  5. Build and Run the program.

    1. Press F7 to build your project

    2. Press F5 to run


作者: 游侠无极限    时间: 2005-4-7 16:25

下面就是本章的例子了,好好研究吧,不难。

#include <d3d8.h>

LPDIRECT3D8 g_pD3D = NULL;

LPDIRECT3DDEVICE8 g_pD3DDevice = NULL;

HRESULT InitialiseD3D(HWND hWnd)

{

//First of all, create the main D3D object. If it is created successfully we

//should get a pointer to an IDirect3D8 interface.

g_pD3D = Direct3DCreate8(D3D_SDK_VERSION);

if(g_pD3D == NULL)

{

return E_FAIL;

}

//Get the current display mode

D3DDISPLAYMODE d3ddm;

if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))

{

return E_FAIL;

}

//Create a structure to hold the settings for our device

D3DPRESENT_PARAMETERS d3dpp;

ZeroMemory(&d3dpp, sizeof(d3dpp));

//Fill the structure.

//We want our program to be windowed, and set the back buffer to a format

//that matches our current display mode

d3dpp.Windowed = TRUE;

d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC;

d3dpp.BackBufferFormat = d3ddm.Format;

//Create a Direct3D device.

if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,

D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,

&g_pD3DDevice)))

{

return E_FAIL;

}

return S_OK;

}


作者: 游侠无极限    时间: 2005-4-7 16:25

void Render()

{

if(g_pD3DDevice == NULL)

{

return;

}

//Clear the back buffer to a green colour

g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);

//Begin the scene

g_pD3DDevice->BeginScene();

//Rendering of our game objects will go here

//End the scene

g_pD3DDevice->EndScene();

//Filp the back and front buffers so that whatever has been rendered on the

//back buffer will now be visible on screen (front buffer).

g_pD3DDevice->resent(NULL, NULL, NULL, NULL);

}

void CleanUp()

{

if(g_pD3DDevice != NULL)

{

g_pD3DDevice->Release();

g_pD3DDevice = NULL;

}

if(g_pD3D != NULL)

{

g_pD3D->Release();

g_pD3D = NULL;

}

}


作者: 游侠无极限    时间: 2005-4-7 16:26

void GameLoop()

{

//Enter the game loop

MSG msg;

BOOL fMessage;

PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);

while(msg.message != WM_QUIT)

{

fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE);

if(fMessage)

{

//Process message

TranslateMessage(&msg);

DispatchMessage(&msg);

}

else

{

//No message to process, so render the current scene

Render();

}

}

}


作者: 游侠无极限    时间: 2005-4-7 16:26

//The windows message handler

LRESULT WINAPI WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

case WM_DESTROY:

PostQuitMessage(0);

return 0;

break;

case WM_KEYUP:

switch (wParam)

{

case VK_ESCAPE:

//User has pressed the escape key, so quit

DestroyWindow(hWnd);

return 0;

break;

}

break;

}

return DefWindowProc(hWnd, msg, wParam, lParam);

}


作者: 游侠无极限    时间: 2005-4-7 16:27

//Application entry point

INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)

{

//Register the window class

WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WinProc, 0L, 0L,

GetModuleHandle(NULL), NULL, NULL, NULL, NULL,

"DX Project 1", NULL};

RegisterClassEx(&wc);

//Create the application's window

HWND hWnd = CreateWindow("DX Project 1", "www.andypike.com: Tutorial 1",

WS_OVERLAPPEDWINDOW, 50, 50, 500, 500,

GetDesktopWindow(), NULL, wc.hInstance, NULL);

//Initialize Direct3D

if(SUCCEEDED(InitialiseD3D(hWnd)))

{

//Show our window

ShowWindow(hWnd, SW_SHOWDEFAULT);

UpdateWindow(hWnd);

//Start game running: Enter the game loop

GameLoop();

}

CleanUp();

UnregisterClass("DX Project 1", wc.hInstance);

return 0;

}


作者: 游侠无极限    时间: 2005-4-7 16:27

你会得到一个绿色背景的窗户(读者:是窗口,白痴),虽然看起来不怎么样,但至少是一个好的开始,不是吗?好地开头,就是成功地半拉!(读者:… …)

(译者:嗯,那个老外用WinXP?我看还是Win2K好… …)

(读者:切~~别在那废话。)


作者: 游侠无极限    时间: 2005-4-7 16:27

WinMain

此乃Win32程序的入口点,代码会从这里开始执行。这是我们注册、创建、显示窗口的地方。然后,我们要初始化Direct3D并进入游戏循环(Game Loop)。

WinProc

这是应用程序的消息处理过程。Windows发给我们的程序的消息,都要有它处理。注意我们上面的例子,我们处理了两种消息:WM_DESTROY(结束程序) 和 WM_KEYUP(有按键被按下)。其他的消息我们都交给默认消息处理过程DefWindowProc处理了。

g_pD3D

这是指向IDirect3D8接口的指针,我们得通过它来创建Direct3D设备接口。

g_pD3DDevice

这是 IDirect3DDevice8(D3D 设备) 的接口的指针,它实际上代表了你的硬件3D卡。

InitialiseD3D

我们的这个函数是用来初始化Direct3D的。首先,创建IDirect3D8对象,通过这个对象我们得到了当前屏幕的显示模式。然后,根据刚刚我们获取的信息(显示模式),创建了兼容的设备。

译者:因为一些显示卡的显示模式并不相同,所以,我们的程序要在每块显卡上都能执行,就要了解这块显卡的显示模式等等一些信息。然后,根据这些信息,创建我们的D3D设备。

GameLoop

这就是上面提到的“游戏循环”的具体实现了。当初始化结束后,它就开始了。

他会检测有没有Windows的消息,没有的话,就调用Render来绘制屏幕。

Render

首先,我们清除了后缓冲区准备作画。然后,调用了BeginScene函数来告知DX我们要作画了。这时,我们就可以作画了(教程2)。结束了绘制,我们调用EndScene来告知DX我们画完了。最后,我们调用了Present来完成关键的一步:翻动后缓冲区到前缓冲区(屏幕)。这时,用户就能看到我们画的东西了。

CleanUp

我们在此做清洁工作:释放所有的被创建的对象。因为程序要推出了。

Summary (摘要)

译者:嗯,好了,这就是我们教程的第一章了。并不难,不是吗?看起来虽然字不多,翻译起来,蛮累呢!

研究明白了的话,看下一章吧!下一章我们就会真正的画一些东西了!呵呵,真是令人期待呢… …

也让老外说几句吧:

Ok, that’s it for the first tutorial. I know that the finished program wasn’t the most spectacular thing in the world, but just wait for the next tutorial when we will be drawing some shapes!


作者: Eagle    时间: 2005-4-12 12:47
直接飘过,
作者: yzhlinux    时间: 2005-4-14 10:04
看的好辛苦




欢迎光临 下沙论坛 (http://bbs.xiasha.cn/) Powered by Discuz! X3.3