[翻译]Direct3D Tutrial-04 画个三角

[翻译]Direct3D Tutrial-04 画个三角
        首先向大家道歉自3出了以后隔这么久才出4,一方面过年期间我天天在外面走亲戚,另一方面我最近确实有些消沉,我不是个会太监的人,却总是有时会陷入一种消沉的状态,因为想从软件行业转型,碰了许多壁,关起门来看龙书和算法导论,基本保持不上网状态,偶尔手机上上人人网分享点日志。

        我也知道我的文章并不是多么的不可或缺,没了这个翻译大家照样过,目前为止基本都是些入门类的东西,有时候我会想到曾小贤的午夜节目,那个夜晚被胡一非痛骂才明白原来自己做的并不是没有意义,消沉的这段时间,看到陆续还有几个网友留言鼓励我,我真的非常感谢你们,我不是什么大神,也不是什么天才,我高数重修了两遍才过,非是不努力而是真的智力不足学起来比别人要多花几倍的时间,但我只是一直努力着,欠了38个学分的时候我没有选择提前留级(如果学年结束时欠了36分以上会退学),我苦行僧般地过了下半学年勉强保住不留级(24学分),刚来上海的时候我是C盲(之前一直搞WEB),没有数据结构的基础不懂STL但我还是撑过来了,四个月以后轻松地完成工作,八个月以后我觉得我们的代码到处是问题,不管遇到怎样的困境,我从来没有放弃过,就像我经常消沉但我总会走出来结束太监状态,希望在看这篇翻译的你,无论在技术还是生活上,永远不要轻言放弃,不管在怎样的困境,只要有1%的希望,就值得我们拼尽全力去争取,人之所以能战胜神,是因为我们相信着的奇迹。

课程概述

      有一个简单的方式来学习的DirectX。杯具的是,简单的方法往往有很多功能上的限制,即使没有,在一个比较大型的游戏使用它仍然会很麻烦。当然,更简单的 方法是,努力地学习,本教程会尽量写得更易于编程,以便不使理论的部分太艰深晦涩。
在本节中,您将学习如何在屏幕上画一个三角形。我们将通过创造一系列顶点来构建三角并通过Direct3D设备在屏幕上绘制之。
     首先,我们将涵盖如何工作的,那么我们将在代码本身和生成程序的理论。

灵活顶点格式(Flexible Vertex Formats)

        如果您完成了第3课中的学习,你会记得顶点的定义:一个确定在在三维空间中的点的精确位置和属性。位置只包含三个坐标数值以描述顶点在空间中的位置。顶点的属性也用数值定义。
        Direct3D使用一种称为灵活顶点格式(Flexible Vertex Format简称FVF)的技术。该技术中一个顶点格式包含一个顶点的位置和多个属性数据。一个FVF顶点会是一个格式化的数据,您可以根据您的需要修改和设置。让我们来看看究竟丫是如何工作的。
顶点可以用一个结构体来描述,它包含所有与创建该3D图像有关的数据。为了展示这个图像,我们要把所有的信息复制到视频RAM,然后让Direct3D来复制数据到后台缓冲区。然而,如果我们不得不把一个顶点所有可能需要的数据发送过去会怎样呢?如下图所示。

[翻译]Direct3D Tutrial-04 画个三角_第1张图片
Image 4.1 - 一个顶点格式包含了所有的信息

        当然,你可能不会马上看到这儿有什么问题,但让我们不得不说我们只需要这些信息中的两块。我们可以看到将其发送到视频RAM会快得多,就像这样:

[翻译]Direct3D Tutrial-04 画个三角_第2张图片
Image 4.2 – FVF格式会快得多

      这就是在我们使用FVF时发生的。我们选择我们要使用的信息,并发送之,这样就可以使我们在每帧之间发送更多的顶点。

 

FVF 代码

        在Direct3D中,每个顶点都是预先设定好的顶点格式。正如标题声称,这种格式是灵活的,是使用的Direct3D提供的某些元素。这些元素通过使用特殊标识来设置,比如何时逻辑或在一起,创建一个顶点的定义,或一个告诉Direct3D顶点格式代码的。
        让我们来看看它如何做到这一点。比方说,我们希望包括位置和我们的顶点漫反射颜色。我们将建立一个代码:

#define  CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

        稍后,我们将简单地使用CUSTOMFVF,而不是每次都输出整个FVF代码。我们将在一分钟后来看这样的一个例子。
我们可以在这个表达式里添加各种标识。以下是一组贯穿本套教程始终的标识表,以及他们做什么的说明。

 

[Table 4.1 - FVF Code Flags]

标识

描述

参数类型

D3DFVF_XYZ

表示该顶点格式包括X,Y和Z的一个未转换的顶点坐标。未转化意味着顶点尚未转化为屏幕坐标。

float, float, float

D3DFVF_XYZRHW

表示该顶点格式包括X,Y和Z坐标以及一个转换过的额外的RHW值。这意味着顶点已经在屏幕坐标系。Z和RHW会在构建软件引擎时使用,我们不会进入。

float, float, float, float

D3DFVF_DIFFUSE

表示顶点格式包含一个32位颜色代码,用于表示漫射光颜色。

DWORD

D3DFVF_SPECULAR

表示顶点格式包含一个32位颜色代码,用于镜面高亮使用的颜色。

DWORD

D3DFVF_TEX0
   through
D3DFVF_TEX8

表示顶点格式包含任何将被应用到模型纹理坐标。

float, float

[Close Table]

 

 


       当然了,还有更多的标识没有被提及,它们已经是包含在DirectX文档中了。而我们只需要本教程中使用到的这些标识。

 

创建顶点

       现在我们需要使用我们的新格式创建顶点。我们不使用任何新函数或诸如此类的东西,我们通过建立一个简单的结构体装入FVF代码中包含的变量。
       例如,我们用在上面的例子用D3DFVF_XYZRHW和D3DFVF_DIFFUSE两个标识一起的话,我们应该建立如下结构:

struct  CUSTOMVERTEX
{
    FLOAT x, y, z, rhw;    
// from the D3DFVF_XYZRHW flag
    DWORD color;    // from the D3DFVF_DIFFUSE flag
}

         如你所见,前四个浮点数是D3DFVF_XYZRHW标识的值,而DWORD是D3DFVF_DIFFUSE标识的值。如果您看看上表,你会发现这其中的变量类型与FVF标识。
       现在,让我们使用我们的新CUSTOMVERTEX结构来构建一个实际的顶点。我们可以像下面这样做:

CUSTOMVERTEX OurVertex  =   {320.0f50.0f1.0f1.0f, D3DCOLOR_XRGB(00255)} ;

    当然了,你也可以弄个顶点数组,就像这样:

CUSTOMVERTEX OurVertices[]  =
{
    
{320.0f50.0f1.0f1.0f, D3DCOLOR_XRGB(00255),},
    
{520.0f400.0f1.0f1.0f, D3DCOLOR_XRGB(02550),},
    
{120.0f400.0f1.0f1.0f, D3DCOLOR_XRGB(25500),},
}
;

        结果会是一个三角形,我们很快会在屏幕上看到。

          这仅仅是一个灵活顶点格式的示例。我们稍后会继续就如何建立更复杂的顶点格式,恩,就从现在开始吧。

顶点缓存


        现在,我们已经完成了两件事情。首先,我们建立了FVF代码。第二,我们已经创建了一个三角形。现在我们需要得到那个三角形以准备给Direct3D使用。要做到这一点,我们创建了所谓的顶点缓冲区。
        一个顶点缓冲区是一个简单的接口,它存储在一段内存中(显存或内存),以持有你的游戏中顶点或模型的信息。我们通过函数CreateVertexBuffer()来创建这个接口。不过它的参数有点复杂。下面是函数原型:

HRESULT CreateVertexBuffer(
    UINT Length,
    DWORD Usage,
    DWORD FVF,
    D3DPOOL Pool,
    LPDIRECT3DVERTEXBUFFER9 ppVertexBuffer,
    HANDLE
*  pSharedHandle);

         我们来逐个分析一下这些个参数 

UINT Length,

    这个参数包含将要创建的顶点缓存的大小。我们得到将存储在缓冲区中的顶点数目乘以一个顶点大小的结果。例如,一个三角形包含三个顶点,因此该三角形的缓冲区大小是:3* sizeof(CUSTOMVERTEX)。 

DWORD Usage,

    有时候,有些特殊的方法能改变DirectX处理的顶点集。在本教程我们不会深入讨论这些。这个参数可以包含标志表明这些特殊的方式。因为我们不会使用任何所以我们只要把它设置为0。 

DWORD FVF,

    这是FVF代码中我们接触得比较早的。我们只需填写CUSTOMFVF。如果我们要改变FVF代码,这部分也将改变(改变那个#define)。这是告诉DirectX顶点是什么格式了,这个参数很重要。 

D3DPOOL Pool,

    这个参数告诉Direct3D在哪创建顶点缓存以及如何创建之。以下是一个表,说明该参数的可能的条目。在本教程中,我们将使用标志D3DPOOL_MANAGED。
 

[Table 4.2 - D3DPOOL Values]

描述

D3DPOOL_DEFAULT

此标志表示该缓存应该创建在最适当的内存以便设置和资源可用。然而,强加一些限制并不总是对游戏有好处。

D3DPOOL_MANAGED

这表明,缓冲将在位于显存

D3DPOOL_SYSTEMMEM

这表明,缓存将在系统内存中。顶点缓存设在这里通常不能由Direct3D设备访问,但可以通过其他更高级的手段访问。

D3DPOOL_SCRATCH

这也表明了缓存将坐落在系统内存中,但是,又没有办法让显存访问它。这种类型一般用于存储图像信息,现在我们用不到(但稍后将使用),比如屏幕已经转到另一个地图但角色暂时还没有到达(不久后就到)。

[Close Table]

 


LPDIRECT3DVERTEXBUFFER9 ppVertexBuffer,   

    如果你理解它,那我告诉你它是我们正在创建的顶点缓存的接口。我们给这个参数一个空指针,函数会给他赋值。
 

HANDLE* pSharedHandle

      文档里说过这个参数,我引述一下:“保留。设置这个参数为NULL。“我不能说肯定,但显然微软希望我们将其设置为NULL。就这样吧。我们将它设置为NULL。
      看完这些参数,让我们来看看这个功能在我们的程序中如何写: 

LPDIRECT3DVERTEXBUFFER9 v_buffer;

d3ddev
-> CreateVertexBuffer( 3 * sizeof (CUSTOMVERTEX),
                           
0 ,
                           CUSTOMFVF,
                           D3DPOOL_MANAGED,
                           
& v_buffer,
                           NULL);

        现在您已经创建了顶点缓存,下面你需要把顶点加载进去。你用一个简单的函数memcpy()就可以完成。但是,在您访问到顶点缓存之前,你需要将其锁定。
        基于两个原因,你需要锁定这个缓存。首先,你需要告诉Direct3D你需要内存的完全控制权。换句话说,它不应该由任何可能的其他进程使用。第二,你需要告诉视频硬件别动它。否则可没法保证显存保持不动。锁定告诉显存与内存当你正在使用它时别干蠢事儿。
        要锁定一个缓冲区,可以使用函数Lock(),它有四个参数,但都相当简单:

HRESULT Lock(UINT OffsetToLock,
             UINT SizeToLock,
             VOID
**  ppbData,
             DWORD Flags);

   让我们来看看这些参数: 

UINT OffsetToLock, UINT SizeToLock,

如果我们只是想锁定我们的顶点缓冲的一部分,我们将表明在这两个参数。第一个指示自缓存的起始点到开始锁定位置的偏移量,以字节为单位。第二个表示多少字节被锁定。因为我们现在要锁定整个缓冲区,所以我们将设置这些都为0。 

VOID** ppbData, 

    除非你是至少中等水平以上的C+ +,否则这个参数您老还是别动了。基本上这是一个void*指针并且没有指向特定类型的变量。例如,一个**double,而一个int*指向一个int。每个指针类型都有它自己的格式,因此它不能转换不会丢失数据为另一种类型。但是一个void *指针,却可以转换为任何类型。
    在这里,我们有一个空指针*.这个指针被锁定的存数去起始位置的指针。顶点缓冲区接口会处理其细节,但我们在下一步会需要这个指针。所以函数lock()函数将填充恰当的地址给这个指针。有一个在下面的例子,看看我们如何填补这个参数。

DWORD Flags 

        这是一个很高级的参数,我们不会在本教程中深入。本上它提供特殊的方式来处锁定内存。如果你是真正感兴趣的,它们可以研究在DirectX文档。现在,我们只是将它设置为0。

       让我们来补完这个函数,看看它的样子:

VOID *  pVoid;     //  the void* we were talking about

v_buffer
-> Lock( 0 0 , ( void ** ) & pVoid,  0 );     //  locks v_buffer, the buffer we made earlier

   接下来,我们调用memcpy()复制顶点到顶点缓存。

memcpy(pVoid, OurVertices,  sizeof (OurVertices));     //  copy vertices to the vertex buffer

       最后,我们还有一个非常复杂的函数:Unlock()。这个函数没有参数。它所做的是告诉Direct3D,跟内存搞完了,解开束缚吧。写起来像这样:

v_buffer -> Unlock();     //  unlock v_buffer

    由于我们刚刚得知命令的数量,我们要把我们自己创建的功能放进一个单独的函数里init_graphics()。

void  init_graphics( void )
{
    
// create three vertices using the CUSTOMVERTEX struct built earlier
    CUSTOMVERTEX vertices[] =
    
{
        
320.0f50.0f0.5f1.0f, D3DCOLOR_XRGB(00255), },
        
520.0f400.0f0.5f1.0f, D3DCOLOR_XRGB(02550), },
        
120.0f400.0f0.5f1.0f, D3DCOLOR_XRGB(25500), },
    }
;

    
// create the vertex and store the pointer into v_buffer, which is created globally
    d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
                               
0,
                               CUSTOMFVF,
                               D3DPOOL_MANAGED,
                               
&v_buffer,
                               NULL);

    VOID
* pVoid;    // the void pointer

    v_buffer
->Lock(00, (void**)&pVoid, 0);    // lock the vertex buffer
    memcpy(pVoid, vertices, sizeof(vertices));    // copy the vertices to the locked buffer
    v_buffer->Unlock();    // unlock the vertex buffer
}

      在这里,我建议您多读几次以确保你彻底明白了这一切。这是3D编程中一个相当关键的的部分,我们将在教程的休息时间使用和修改它。
 

绘制图元

         现在,我们实际上已经获得屏幕上的内容!但在此发生之前我们有三个非常简单的函数要认识一下。每一个被从Direct3D设备接口调用。让我们来看看。

SetFVF()

        这些函数的第一个是SetFVF()。 SetFVF()是一种告诉Direct3D使用当前使用什么样的FVF代码的函数。我们当然可以有多个FVF代码并使用在两个不同的三维场景。在我们开始画之前,我们只需要告诉我们的Direct3D使用的是哪一个。这个函数写出来是这样的:

d3ddev -> SetFVF(CUSTOMFVF);

SetStreamSource()

    下一步,我们的函数SetStreamSource(),它告诉Direct3D我们从哪个顶点缓冲取顶点。这其中有一对参数,让我们来看看函数原型:

HRESULT SetStreamSource(UINT StreamNumber,
                        LPDIRECT3DVERTEXBUFFER9 pStreamData,
                        UINT OffsetInBytes,
                        UINT Stride);

    第一个参数是要用的顶点缓存的序号。我们稍后深入它的工作原理,但现在将它设置为0,因为我们只有一个顶点缓冲区。
    第二个参数是指向我们先前创建的顶点缓存的指针。
    第三个参数指应该从顶点缓冲的第几个字节开始。这通常是0。
    最后一个参数是每个顶点的大小。我们填写如下: SizeOf(CUSTOMVERTEX)。
    让我们来看看在函数怎样被调用:

d3ddev -> SetStreamSource( 0 , v_buffer,  0 sizeof (CUSTOMVERTEX));

DrawPrimitive()

       现在我们已经告诉Direct3D我们正在使用哪种格式的顶点以及哪里得到它们,我们告诉它请绘制我们已经建立的顶点。这个函数绘制在选定的顶点缓存的图元到屏幕上。这里是函数原型:

HRESULT DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType,
                      UINT StartVertex,
                      UINT PrimitiveCount);

    第一个参数是使用的图元类型。这些在第3课已经讲过了,但所用的代码在这里: 

[Table 4.3 - D3DPRIMITIVETYPE Values]

Value

Description

D3DPT_POINTLIST

点阵
[翻译]Direct3D Tutrial-04 画个三角_第3张图片

D3DPT_LINELIST

线列表
[翻译]Direct3D Tutrial-04 画个三角_第4张图片

D3DPT_LINESTRIP

线带
[翻译]Direct3D Tutrial-04 画个三角_第5张图片

D3DPT_TRIANGLELIST

三角形列表
[翻译]Direct3D Tutrial-04 画个三角_第6张图片

D3DPT_TRIANGLESTRIP

三角形带
[翻译]Direct3D Tutrial-04 画个三角_第7张图片

D3DPT_TRIANGLEFAN

三角扇形
[翻译]Direct3D Tutrial-04 画个三角_第8张图片

[Close Table]

 


       第二个参数是我们要绘制在屏幕上的第一个顶点的序号。如果我们愿意,我们可以在顶点缓冲区的中间开始。但是,现在我们希望绘制整个缓冲区,因此我们将在这里把0。
        第三个也是最后一个参数是我们要绘制图元的数量。如果我们要画一个三角形,我们设1(只有一个三角形)。如果我们画点,我们会设为3,有三点。画线条也是设为3。
        现在让我们来看看整个render_frame()函数,现在我们已经修改了它。

//  this is the function used to render a single frame
void  render_frame( void )
{
    d3ddev
->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(000), 1.0f0);

    d3ddev
->BeginScene();

        
// select which vertex format we are using
        d3ddev->SetFVF(CUSTOMFVF);

        
// select the vertex buffer to display

        d3ddev->SetStreamSource(0, v_buffer, 0sizeof(CUSTOMVERTEX));

        
// copy the vertex buffer to the back buffer

        d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 01);

    d3ddev
->EndScene();

    d3ddev
->Present(NULL, NULL, NULL, NULL);
}


        在看整个程序之前,先来看看最后一个步骤是很有必要的。

释放顶点缓存

        就像Direct3D设备和Direct3D一样,顶点缓冲区也必须在程序关闭之前被释放。

//  this is the function that cleans up Direct3D and COM
void  cleanD3D( void )
{
    v_buffer
->Release();    // close and release the vertex buffer
    d3ddev->Release();    // close and release the 3D device
    d3d->Release();    // close and release Direct3D
}

 

         现在让我们来看看整个程序,看看我们都干了什么。


最终代码

        好吧,让我们来看看这个三角长啥样。如果你从来没有见过三角形,这将是一个教育的经验。否则你可以看到一个三角形是made in Direct3D。
       无论如何,让我们来看看最后的DirectX代码。在本课程中所涵盖的新的部分像往常是加粗的。

  1 //  include the basic windows header files and the Direct3D header file
  2 #include  < windows.h >
  3 #include  < windowsx.h >
  4 #include  < d3d9.h >
  5
  6 //  define the screen resolution
  7 #define  SCREEN_WIDTH 800
  8 #define  SCREEN_HEIGHT 600
  9
 10 //  include the Direct3D Library file
 11 #pragma comment (lib,  " d3d9.lib " )
 12
 13 //  global declarations
 14 LPDIRECT3D9 d3d;     //  the pointer to our Direct3D interface
 15 LPDIRECT3DDEVICE9 d3ddev;     //  the pointer to the device class
 16 LPDIRECT3DVERTEXBUFFER9 v_buffer = NULL;    //  the pointer to the vertex buffer
 17
 18 //  function prototypes
 19 void  initD3D(HWND hWnd);     //  sets up and initializes Direct3D
 20 void  render_frame( void );     //  renders a single frame
 21 void  cleanD3D( void );     //  closes Direct3D and releases memory
 22void init_graphics(void);    // 3D declarations
 23
 24struct CUSTOMVERTEX {FLOAT X, Y, Z, RHW; DWORD COLOR;} ;
 25#define CUSTOMFVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

 26
 27 //  the WindowProc function prototype
 28 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 29
 30
 31 //  the entry point for any Windows program
 32 int  WINAPI WinMain(HINSTANCE hInstance,
 33                    HINSTANCE hPrevInstance,
 34                    LPSTR lpCmdLine,
 35                     int  nCmdShow)
 36 {
 37    HWND hWnd;
 38    WNDCLASSEX wc;
 39
 40    ZeroMemory(&wc, sizeof(WNDCLASSEX));
 41
 42    wc.cbSize = sizeof(WNDCLASSEX);
 43    wc.style = CS_HREDRAW | CS_VREDRAW;
 44    wc.lpfnWndProc = WindowProc;
 45    wc.hInstance = hInstance;
 46    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
 47    wc.lpszClassName = L"WindowClass";
 48
 49    RegisterClassEx(&wc);
 50
 51    hWnd = CreateWindowEx(NULL,
 52                          L"WindowClass",
 53                          L"Our Direct3D Program",
 54                          WS_OVERLAPPEDWINDOW,
 55                          00,
 56                          SCREEN_WIDTH, SCREEN_HEIGHT,
 57                          NULL,
 58                          NULL,
 59                          hInstance,
 60                          NULL);
 61
 62    ShowWindow(hWnd, nCmdShow);
 63
 64    // set up and initialize Direct3D
 65    initD3D(hWnd);
 66
 67    // enter the main loop:
 68
 69    MSG msg;
 70
 71    while(TRUE)
 72    {
 73        while(PeekMessage(&msg, NULL, 00, PM_REMOVE))
 74        {
 75            TranslateMessage(&msg);
 76            DispatchMessage(&msg);
 77        }

 78
 79        if(msg.message == WM_QUIT)
 80            break;
 81
 82        render_frame();
 83    }

 84
 85    // clean up DirectX and COM
 86    cleanD3D();
 87
 88    return msg.wParam;
 89}

 90
 91
 92 //  this is the main message handler for the program
 93 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 94 {
 95    switch(message)
 96    {
 97        case WM_DESTROY:
 98            {
 99                PostQuitMessage(0);
100                return 0;
101            }
 break;
102    }

103
104    return DefWindowProc (hWnd, message, wParam, lParam);
105}

106
107
108 //  this function initializes and prepares Direct3D for use
109 void  initD3D(HWND hWnd)
110 {
111    d3d = Direct3DCreate9(D3D_SDK_VERSION);
112
113    D3DPRESENT_PARAMETERS d3dpp;
114
115    ZeroMemory(&d3dpp, sizeof(d3dpp));
116    d3dpp.Windowed = TRUE;
117    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
118    d3dpp.hDeviceWindow = hWnd;
119    d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
120    d3dpp.BackBufferWidth = SCREEN_WIDTH;
121    d3dpp.BackBufferHeight = SCREEN_HEIGHT;
122
123    // create a device class using this information and the info from the d3dpp stuct
124    d3d->CreateDevice(D3DADAPTER_DEFAULT,
125                      D3DDEVTYPE_HAL,
126                      hWnd,
127                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
128                      &d3dpp,
129                      &d3ddev);
130
131    init_graphics();    // call the function to initialize the triangle
132}

133
134
135 //  this is the function used to render a single frame
136 void  render_frame( void )
137 {
138    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(000), 1.0f0);
139
140    d3ddev->BeginScene();
141
142        // select which vertex format we are using
143        d3ddev->SetFVF(CUSTOMFVF);
144

145        // select the vertex buffer to display

146        d3ddev->SetStreamSource(0, v_buffer, 0sizeof(CUSTOMVERTEX));
147

148        // copy the vertex buffer to the back buffer

149        d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 01);
150
151    d3ddev->EndScene();
152
153    d3ddev->Present(NULL, NULL, NULL, NULL);
154}

155
156
157 //  this is the function that cleans up Direct3D and COM
158 void  cleanD3D( void )
159 {
160    v_buffer->Release();    // close and release the vertex buffer
161    d3ddev->Release();    // close and release the 3D device
162    d3d->Release();    // close and release Direct3D
163}

164
165
166// this is the function that puts the 3D models into video RAM
167void init_graphics(void )
168
{
169    // create the vertices using the CUSTOMVERTEX struct

170    CUSTOMVERTEX vertices[] =
171    {
172        400.0f62.5f0.5f1.0f, D3DCOLOR_XRGB(00255), }
,
173        650.0f500.0f0.5f1.0f, D3DCOLOR_XRGB(02550), }
,
174        150.0f500.0f0.5f1.0f, D3DCOLOR_XRGB(25500), }
,
175    }
;
176

177    // create a vertex buffer interface called v_buffer

178    d3ddev->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
179                               0
,
180
                               CUSTOMFVF,
181
                               D3DPOOL_MANAGED,
182                               &
v_buffer,
183
                               NULL);
184

185    VOID* pVoid;    //
 a void pointer
186

187    // lock v_buffer and load the vertices into it

188    v_buffer->Lock(00, (void**)&pVoid, 0);
189    memcpy(pVoid, vertices, sizeof
(vertices));
190    v_buffer->
Unlock();
191}

192

 

       来吧,更新您的程序,让我们看看我们得到的。如果你运行这个,你应该在屏幕上看到以下内容:

[翻译]Direct3D Tutrial-04 画个三角_第9张图片

   如果你看到这样的三角,那么恭喜你!你成功了。当然,后面还有更多,在开始下一课之前我建议你试着做做下面的小练习,更可让你更熟悉程序。

      1。改变三角形的颜色。
      2。在程序运行时改变三角的形状。
      3。将一个点的颜色褪色成另一个点的颜色。

 

       当然,你可能会失望地发现,这一个三角形算哪门子三维啊?让我们继续下一课的学习,并使其通过旋转,调整大小和移动让你感觉到它确确实实在三维空间中。

下一课:转变顶点

英文原文:http://www.directxtutorial.com/tutorial9/b-direct3dbasics/dx9B4.aspx 

Translate By 王大宝(OneDouble.net)

你可能感兴趣的:([翻译]Direct3D Tutrial-04 画个三角)