Yui的狗窝
Yui的狗窝
使用directx9绘制一个正方体

在完成了设备初始化之后,可以尝试绘制一些简单的图形。

在directx中,首先提供8个顶点的空间位置信息,接着,便可以通过绘制12个三角形图元来完成正方体的绘制操作。
创建顶点缓存来保存需要用到的顶点位置信息,同理,使用索引缓存保存顶点索引信息。

//source1.cpp
#include<windows.h>
#include"header.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitWindow(HINSTANCE, int);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow)
{
    InitWindow(hInstance, cmdShow);
    Setup(800,600);
    MSG msg = { 0 };
    while (msg.message != WM_QUIT)
    {
        Display(0.001);
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    pd3dDev->Release();
    Del();
    return msg.wParam;
}
void InitWindow(HINSTANCE hInstance, int cmdShow)
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(wc);
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = L"drawCube";
    wc.lpszMenuName = NULL;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClassEx(&wc);
    HWND hWnd = CreateWindowEx(NULL, L"drawCube", L"draw cube", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        800, 600, NULL, NULL, hInstance, NULL);
    ShowWindow(hWnd, cmdShow);
    UpdateWindow(hWnd);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    switch (message)
    {
    case WM_CREATE:
        if (!InitDevice(hWnd))
            PostQuitMessage(0);
        break;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            DestroyWindow(hWnd);
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;
    case WM_SIZE:
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}
</code>
<code lang="cpp">
//header.h
#pragma once
#include<d3d9.h>
#include<d3dx9.h>
#include<windows.h>
struct Vertex
{
    //创建新的数据结构Vertex,
    static const DWORD FVF;
    float x, y, z;
    Vertex(float a, float b, float c) :x(a), y(b), z(c)
    {
    }
};
IDirect3D9                  *pd3d;
IDirect3DDevice9            *pd3dDev;
D3DCAPS9                    caps;
IDirect3DVertexBuffer9      *vb=0;
IDirect3DIndexBuffer9       *ib=0;
int                         iFlagUsePro;
const DWORD Vertex::FVF = D3DFVF_XYZ;
bool InitDevice(HWND hWnd)
{
    pd3d = Direct3DCreate9(D3D_SDK_VERSION);
    pd3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
    if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT)
        iFlagUsePro = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        iFlagUsePro = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    D3DPRESENT_PARAMETERS d3dpp;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
    d3dpp.BackBufferCount = 1;
    d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
    d3dpp.BackBufferHeight = 600;
    d3dpp.BackBufferWidth = 800;
    d3dpp.EnableAutoDepthStencil = true;
    d3dpp.Flags = 0;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.MultiSampleQuality = 0;
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.Windowed = true;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    if (FAILED(pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, iFlagUsePro,
        &d3dpp, &pd3dDev)))
    {
        MessageBox(NULL, L"Initialize d3d9x failed", NULL, NULL);
        return false;
    }
    pd3dDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
    return true;
}
void Setup(int Width,int Height)
{
    //创建顶点缓存以及索引缓存,并写入数据
    if(FAILED(pd3dDev->CreateVertexBuffer(8 * sizeof(Vertex), D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_MANAGED, &vb, 0)))
        MessageBox(NULL, L"Initialize d3d9x failed", NULL, NULL);
    if(FAILED(pd3dDev->CreateIndexBuffer(36 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ib, 0)))
        MessageBox(NULL, L"Initialize d3d9x failed", NULL, NULL);
    Vertex *vertices;
    //在对数据写入前,先调用Lock函数获取指向存储区的指针
    vb->Lock(0,0,(void**)&vertices,0);
    vertices[0] = Vertex(-1.f, -1.f, -1.f);
    vertices[1] = Vertex(-1.f,  1.f, -1.f);
    vertices[2] = Vertex( 1.f,  1.f, -1.f);
    vertices[3] = Vertex( 1.f, -1.f, -1.f);
    vertices[4] = Vertex(-1.f, -1.f,  1.f);
    vertices[5] = Vertex(-1.f,  1.f,  1.f);
    vertices[6] = Vertex( 1.f,  1.f,  1.f);
    vertices[7] = Vertex( 1.f, -1.f,  1.f);
    vb->Unlock();
    WORD *indices;
    ib->Lock(0, 0, (void**)&indices, 0);
    indices[0] = 0; indices[1] = 1; indices[2] = 2;
    indices[3] = 0; indices[4] = 2; indices[5] = 3;
    indices[6] = 4; indices[7] = 6; indices[8] = 5;
    indices[9] = 4; indices[10] = 7; indices[11] = 6;
    indices[12] = 4; indices[13] = 5; indices[14] = 1;
    indices[15] = 4; indices[16] = 1; indices[17] = 0;
    indices[18] = 3; indices[19] = 2; indices[20] = 6;
    indices[21] = 3; indices[22] = 6; indices[23] = 7;
    indices[24] = 1; indices[25] = 5; indices[26] = 6;
    indices[27] = 1; indices[28] = 6; indices[29] = 2;
    indices[30] = 4; indices[31] = 0; indices[32] = 3;
    indices[33] = 4; indices[34] = 3; indices[35] = 7;
    ib->Unlock();
    //设置摄像机
    D3DXVECTOR3 position(0.f, 0.f, -5.f);
    D3DXVECTOR3 target(0.f, 0.f, 0.f);
    D3DXVECTOR3 up(0.f, 1.f, 0.f);
    D3DXMATRIX v;
    D3DXMatrixLookAtLH(&v, &position, &target, &up);
    pd3dDev->SetTransform(D3DTS_VIEW, &v);
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI*0.5f, (float)Width / (float)Height, 1.0f, 1000.0f);
    pd3dDev->SetTransform(D3DTS_PROJECTION, &proj);
    //设置渲染模式为线条
    pd3dDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
}
void Del()
{
    ib->Release();
    vb->Release();
}
void Display(float timeDelta)
{
    if (pd3dDev)
    {
        D3DXMATRIX Rx, Ry;
        D3DXMatrixRotationX(&Rx, 3.14f / 4.0f);
        static float y = 0.;
        D3DXMatrixRotationY(&Ry, y);
        y += timeDelta;
        if (y >= 6.28f)
            y = 0.f;
        //通过世界变换来调整正方体位置
        D3DXMATRIX p = Rx * Ry;
        pd3dDev->SetTransform(D3DTS_WORLD, &p);
        //场景绘制
        pd3dDev->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffffff, 1.f, 0);
        pd3dDev->BeginScene();
        pd3dDev->SetStreamSource(0, vb, 0, sizeof(Vertex));
        pd3dDev->SetIndices(ib);
        pd3dDev->SetFVF(Vertex::FVF);
        //绘制正方体
        pd3dDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
        pd3dDev->EndScene();
        pd3dDev->Present(0,0,0,0);
    }
}

完成了绘制线框立方体后,接着尝试绘制一个表面有颜色的立方体。
通过学习了解,绘制面图形的颜色,是根据顶点进行的,为此,需要修改之前的Vertex的成员变量。
同时也不能忘记对绘制模式进行更改。

//source.cpp
#include<windows.h>
#include"header.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitWindow(HINSTANCE, int);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE prevInstance, LPWSTR cmdLine, int cmdShow)
{
    InitWindow(hInstance, cmdShow);
    Setup(800, 600);
    MSG msg = { 0 };
    while (true)
    {
        //使用龙书上的“更好的循环”
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
                break;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
            Display(0.001);
    }
    Del();
    return msg.wParam;
}
void InitWindow(HINSTANCE hInstance, int cmdShow)
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(wc);
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = L"drawCube2";
    wc.lpszMenuName = NULL;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClassEx(&wc);
    HWND hWnd = CreateWindowEx(NULL, L"drawCube2", L"draw cube2", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        800, 600, NULL, NULL, hInstance, NULL);
    ShowWindow(hWnd, cmdShow);
    UpdateWindow(hWnd);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    switch (message)
    {
    case WM_CREATE:
        if (!InitDevice(hWnd))
            PostQuitMessage(0);
        break;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            DestroyWindow(hWnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}
//header.h
#pragma once
#include<d3d9.h>
#include<d3dx9.h>
struct Vertex
{
    float x, y, z;
    D3DCOLOR color;//修改Vertex的数据结构成员,添加存储顶点颜色信息
    Vertex(float a, float b, float c, D3DCOLOR d) :x(a), y(b), z(c), color(d)
    {
    }
};
IDirect3D9              *pd3d;
IDirect3DDevice9        *pd3dDevice;
IDirect3DVertexBuffer9  *vb;
IDirect3DIndexBuffer9   *ib;
D3DCAPS9                caps;
const static DWORD      FVF = D3DFVF_DIFFUSE | D3DFVF_XYZ;
int                     iProcessingUse;
bool InitDevice(HWND hWnd)
{
    pd3d = Direct3DCreate9(D3D_SDK_VERSION);
    pd3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
    if (caps.DevCaps&D3DDEVCAPS_HWTRANSFORMANDLIGHT)
        iProcessingUse = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    else
        iProcessingUse = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    D3DPRESENT_PARAMETERS d3dpp;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
    d3dpp.BackBufferCount = 1;
    d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
    d3dpp.BackBufferHeight = 600;
    d3dpp.BackBufferWidth = 800;
    d3dpp.EnableAutoDepthStencil = true;
    d3dpp.Flags = 0;
    d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    d3dpp.hDeviceWindow = hWnd;
    d3dpp.MultiSampleQuality = 0;
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.Windowed = true;
    if (FAILED(pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, iProcessingUse, &d3dpp, &pd3dDevice)))
    {
        MessageBox(NULL, L"Init failed", 0, 0);
        return false;
    }
    return true;
}
void Setup(float width, float height)
{
    pd3dDevice->CreateVertexBuffer(sizeof(Vertex) * 8, D3DUSAGE_WRITEONLY, FVF, D3DPOOL_MANAGED,
        &vb, 0);
    pd3dDevice->CreateIndexBuffer(sizeof(WORD) * 36, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED,
        &ib, 0);
    Vertex *vertices;
    vb->Lock(0, 0, (void**)&vertices, 0);//对顶点缓存写入顶点的位置和颜色信息
    vertices[0] = Vertex(-1.f, -1.f, -1.f, D3DCOLOR_XRGB(255, 0, 0));
    vertices[1] = Vertex(-1.f, 1.f, -1.f, D3DCOLOR_XRGB(0, 255, 0));
    vertices[2] = Vertex(1.f, 1.f, -1.f, D3DCOLOR_XRGB(0, 0, 255));
    vertices[3] = Vertex(1.f, -1.f, -1.f, D3DCOLOR_XRGB(255, 255, 0));
    vertices[4] = Vertex(-1.f, -1.f, 1.f, D3DCOLOR_XRGB(0, 255, 255));
    vertices[5] = Vertex(-1.f, 1.f, 1.f, D3DCOLOR_XRGB(255, 0, 255));
    vertices[6] = Vertex(1.f, 1.f, 1.f, D3DCOLOR_XRGB(255, 255, 255));
    vertices[7] = Vertex(1.f, -1.f, 1.f, D3DCOLOR_XRGB(0, 0, 0));
    vb->Unlock();
    WORD *indices;
    ib->Lock(0, 0, (void**)&indices, 0);
    indices[0] = 0; indices[1] = 1; indices[2] = 2;
    indices[3] = 0; indices[4] = 2; indices[5] = 3;
    indices[6] = 4; indices[7] = 6; indices[8] = 5;
    indices[9] = 4; indices[10] = 7; indices[11] = 6;
    indices[12] = 4; indices[13] = 5; indices[14] = 1;
    indices[15] = 4; indices[16] = 1; indices[17] = 0;
    indices[18] = 3; indices[19] = 2; indices[20] = 6;
    indices[21] = 3; indices[22] = 6; indices[23] = 7;
    indices[24] = 1; indices[25] = 5; indices[26] = 6;
    indices[27] = 1; indices[28] = 6; indices[29] = 2;
    indices[30] = 4; indices[31] = 0; indices[32] = 3;
    indices[33] = 4; indices[34] = 3; indices[35] = 7;
    ib->Unlock();
    D3DXVECTOR3 lookAt{ 0.f,0.f,-5.f };
    D3DXVECTOR3 target{ 0.f,0.f,0.f };
    D3DXVECTOR3 up{ 0.f,1.f,0.f };
    D3DXMATRIX  v;
    D3DXMatrixLookAtLH(&v, &lookAt, &target, &up);
    pd3dDevice->SetTransform(D3DTS_VIEW, &v);
    D3DXMATRIX proj;
    D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI*0.5f, width / height, 1.f, 1000.f);
    pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);
    pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);//绘制模式的更改
}
void Del()
{
    vb->Release();
    ib->Release();
    pd3dDevice->Release();
}
void Display(float timeDelta)
{
    if (pd3dDevice)
    {
        D3DXMATRIX rx, ry;
        D3DXMatrixRotationX(&rx, 0);
        static float y = 0.f;
        D3DXMatrixRotationY(&ry, y);
        y += timeDelta;
        if (y >= 6.28)
            y = 0;
        D3DXMATRIX p = rx * ry;
        pd3dDevice->SetTransform(D3DTS_WORLD, &p);
        pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.f, 0);
        pd3dDevice->BeginScene();
        pd3dDevice->SetStreamSource(0, vb, 0, sizeof(Vertex));
        pd3dDevice->SetIndices(ib);
        pd3dDevice->SetFVF(FVF);
        pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
        pd3dDevice->EndScene();
        pd3dDevice->Present(0, 0, 0, 0);
    }
}
没有标签
首页      读书笔记      directx龙书的学习笔记      使用directx9绘制一个正方体
https://secure.gravatar.com/avatar/d0fe7f1b17d5e9122db921e3a8cc327f?s=256&d=mm&r=g

Suzumiya, Yui

文章作者

发表评论

textsms
account_circle
email

Yui的狗窝

使用directx9绘制一个正方体
在完成了设备初始化之后,可以尝试绘制一些简单的图形。 在directx中,首先提供8个顶点的空间位置信息,接着,便可以通过绘制12个三角形图元来完成正方体的绘制操作。 创建顶点缓存来保…
扫描二维码继续阅读
2018-04-14


没有激活的小工具