DirectX9 龙书学习笔记(1) 矩形的绘制

DX9龙书的学习笔记第一弹,主要讲解如何从零开始绘制出一个矩形,也是DX9使用的入门。建议有一定WIN32编程和3D数学的基础知识。学完这本之后就可以慢慢的读些图形学的论文和REAL-TIME RENDERING 3RD了。

关于库文件和头文件的路径设置请参考龙书,这里不再赘述。本文并不使用由该书作者提供的d3dUtility.h和d3dUtility.cpp,不过下一篇开始应该就会使用,因为这两个文件提供了创建DX9程序所需的最基本的定义和操作,可以避免重复劳动,让我们更加专注于新的内容。

本文使用的是vs2010,DirectX SDK版本Microsoft DirectX SDK (June 2010),应该也是目前最新的版本了。

程序基本流程如下:

1. 首先创建一个WIN32空项目,设计,注册并创建一个标题为“First DX9”,大小为640*480的主窗口。

2. 初始化DX9,即使用Direct3Dcreate方法创建对象,D3D_SDK_VERSION为当前SDK版本。并测试图像硬件性能,建议不要略过这一步。

3. 填充D3DPRESENT_PARAMETERS结构,该结构定义了Direct3D设备的信息

4. 创建Direct3D设备,也就代表着我们的图形卡(第一个参数就表示使用哪一块图形卡,默认为当前正在使用的)

5. 创建顶点缓存,按程序中的顺序定义好6个顶点(实质为4个),注意第二个三角顺序有错的话绘制会出现问题(这里我们并不使用索引缓存,各位同学可以自己试试)

6. 设定虚拟摄像机和观察目标的位置,

7. 设置投影矩阵,具体的原理可以参考其他资料。

8. 开始进行绘制,在开始之前应调用BeginScene()方法,而在绘制结束后,必须调用EndScene()方法,两者必须成对出现。这里采用DrawPrimitive进行绘制,方式为D3DPT_TRIANGLELIST,用来绘制一系列三角形,与其他几种方式的区别大家可以参考http://blog.csdn.net/lsmdiao0812/article/details/3166410

另外填充方式这里用的是D3DFILL_WIREFRAME,如果采用SOLID方式,那么就看不出矩形是有两个三角组成的了。

9. 最后进入窗口的消息循环。

10. 退出消息循环返回之前,应当释放Direct3D资源。


代码如下:


#include <Windows.h>
#include <stdio.h>
#include <d3dx9.h>
using namespace std;
#pragma  comment(lib,"d3dx9.lib")
#pragma  comment(lib,"d3d9.lib")
#pragma  comment(lib,"winmm.lib")

IDirect3DVertexBuffer9* VB = 0;
IDirect3DIndexBuffer9*  IB = 0;


// Vertex struct

struct Vertex
{
    Vertex(){}
    Vertex(float x, float y, float z)
    {
        _x = x;  _y = y;  _z = z;
    }
    float _x, _y, _z;
    static const DWORD FVF;
};

const DWORD Vertex::FVF = D3DFVF_XYZ; //灵活顶点格式

LRESULT CALLBACK Dx9WndProc(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
);

int WINAPI WinMain(
  HINSTANCE hInstance,      // handle to current instance
  HINSTANCE hPrevInstance,  // handle to previous instance
  LPSTR lpCmdLine,          // command line
  int nCmdShow              // show state
)
{
    WNDCLASSEX wndcls;
    wndcls.cbSize = sizeof(WNDCLASSEX);
    wndcls.cbClsExtra=0;
    wndcls.cbWndExtra=0;
    wndcls.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);//(HBRUSH)GetStockObject(WHITE_BRUSH);
    wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
    wndcls.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wndcls.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
    wndcls.hInstance=hInstance;
    wndcls.lpfnWndProc=Dx9WndProc;
    wndcls.lpszClassName="DX9";
    wndcls.lpszMenuName=NULL;
    wndcls.style=CS_HREDRAW | CS_VREDRAW;
    RegisterClassEx(&wndcls);

    HWND hwnd;
    hwnd=CreateWindow("DX9","First DX9",WS_OVERLAPPEDWINDOW,
        0,0,640,480,NULL,NULL,hInstance,NULL);
 

  // Step1: Dx9 Init
    IDirect3D9* pd3d9 = NULL;
    pd3d9 = Direct3DCreate9(D3D_SDK_VERSION);

    if( !pd3d9 )
    {
        ::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
        return false;
    }


    // Step 2: Check for hardware vp and pixel shaders
    D3DCAPS9 caps;
    pd3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
    int vp = 0;
    if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
        vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

    ShowWindow(hwnd,SW_SHOWNORMAL);//显示窗口
    UpdateWindow(hwnd);

    // Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
     D3DPRESENT_PARAMETERS d3dpp;
    d3dpp.BackBufferWidth            = 640;
    d3dpp.BackBufferHeight           = 480;
    d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
    d3dpp.BackBufferCount            = 1;
    d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality         = 0;
    d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow              = hwnd;
    d3dpp.Windowed                   = true;
    d3dpp.EnableAutoDepthStencil     = true;
    d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
    d3dpp.Flags                      = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;//立即提交缓存
    
    // Step 4: Create the device
    LPDIRECT3DDEVICE9  g_pd3dDevice = NULL;
    if( FAILED( pd3d9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &d3dpp, &g_pd3dDevice ) ) )
    {
        pd3d9->Release(); // done with d3d9 object
        ::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
        return false;
    }

    // Clear the back buffer to a blue color
    //g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,0,0), 1.0f, 0 );
    //g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
    
    // Step 5: Create vertex buffer

    g_pd3dDevice->CreateVertexBuffer(
        8 * sizeof(Vertex),
        D3DUSAGE_WRITEONLY,
        Vertex::FVF,
        D3DPOOL_MANAGED,
        &VB,
        0);

    // Step 6: define unique vertices
    Vertex* vertices;
    VB->Lock(0, 0, (void**)&vertices, 0);

    // vertices of rectangle
    vertices[0] = Vertex(-1.0f, -1.0f, -1.0f); //左下,Z轴坐标相等(在同一XY平面)
    vertices[1] = Vertex(-1.0f,  1.0f, -1.0f); //左上
    vertices[2] = Vertex( 1.0f,  1.0f, -1.0f); //右上
    vertices[3] = Vertex( 1.0f, -1.0f, -1.0f); //右下
    vertices[4] = Vertex(-1.0f, -1.0f, -1.0f);//左下
    vertices[5] = Vertex( 1.0f,  1.0f, -1.0f);//右上
    
    VB->Unlock();

    // step7: set the position and aim the camera.

    D3DXVECTOR3 position(0.0f, 0.0f, -5.0f);
    D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);//上方
    D3DXMATRIX V;
   D3DXMatrixLookAtLH (&V, &position, &target, &up); //设置摄像机

    g_pd3dDevice->SetTransform(D3DTS_VIEW, &V);

    // step8: Set the projection matrix.

    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(
            &proj,
            D3DX_PI * 0.5f, // 90 - degree
            640 / 480,
            1.0f,
            1000.0f);
    g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);

    //
    // Switch to wireframe mode.
    //

    g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

    g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
    g_pd3dDevice->BeginScene();

        g_pd3dDevice->SetStreamSource(0, VB, 0, sizeof(Vertex)); //设置数据源
        g_pd3dDevice->SetIndices(IB);
        g_pd3dDevice->SetFVF(Vertex::FVF);
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2); //绘制矩阵实质是绘制两个三角形

        g_pd3dDevice->EndScene();
        g_pd3dDevice->Present(0, 0, 0, 0);
    

    MSG msg;
    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    if (NULL != g_pd3dDevice)
   {            
        g_pd3dDevice->Release();     
   }
        if (NULL !=pd3d9)
   {
        pd3d9->Release();
   }


    return 0;
}

LRESULT CALLBACK Dx9WndProc(
  HWND hwnd,      // handle to window
  UINT uMsg,      // message identifier
  WPARAM wParam,  // first message parameter
  LPARAM lParam   // second message parameter
)
{
    switch(uMsg)
    {
    
    case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd,uMsg,wParam,lParam);
    }
    return 0;
}


结果如下:

DirectX9 龙书学习笔记(1) 矩形的绘制_第1张图片


需要说明的是本文的编程风格并不好,主要是为了说明从零开始绘制一个矩形的步骤流程,实际使用时建议将绘制过程放在消息循环里,在没有消息到来时进行绘制。

更新完毕,另外祝贺拜仁夺冠。

你可能感兴趣的:(DirectX)