Direct3D 彩色立方体 就是练习

本文提供了一个使用Direct3D进行游戏渲染的例子程序。该程序通过Direct3D API创建了一个窗口,并初始化Direct3D环境,包括设备创建、字体创建等。此外,还实现了顶点缓冲区和索引缓冲区的创建,以及绘制一个旋转的三维立方体。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么也不想说,就是一张效果图
这里写图片描述


// tWinMain.cpp : Defines the entry point for the application.

#include "windows.h"
#include "tchar.h"

#include "d3d9.h"
#include "d3dx9.h"

#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "winmm.lib")

#define WNDWIDTH 800
#define WNDHEIGHT 600

typedef struct _CUSTOMVERTEX
{
    FLOAT x, y, z;
    DWORD color;
}CUSTOMVERTEX;
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

// Global Variables:
HWND g_hWnd                                             = NULL;
LPDIRECT3D9 g_pDirect3D                                 = NULL;
LPDIRECT3DDEVICE9 g_pDirect3DDevice                     = NULL;
LPD3DXFONT g_pD3DXFont                                  = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVertextBuffer = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIndexBuffer = NULL;

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

HRESULT Direct3DInit();
VOID Direct3DRender();
VOID Direct3DClean();

bool GameInit();
void MatrixSet();
void GameRender();
void GameClean();

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.
    MSG msg = {0};

    // Initialize global strings
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    // Main message loop:
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            Direct3DRender();
        }
    }

    return (int) msg.wParam;
}

ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = NULL;
    wcex.lpszClassName  = _T("WndClass");
    wcex.hIconSm = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));

    return RegisterClassEx(&wcex);
}

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   g_hWnd = CreateWindow(_T("WndClass"), _T("LearnGame"), WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, CW_USEDEFAULT, WNDWIDTH, WNDHEIGHT, NULL, NULL, hInstance, NULL);

   if (!g_hWnd)
   {
      return FALSE;
   }

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

   ShowWindow(g_hWnd, nCmdShow);
   UpdateWindow(g_hWnd);

   return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        {
            Direct3DClean();
            DestroyWindow(hWnd);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

HRESULT Direct3DInit()
{
    g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
    if (g_pDirect3D == NULL)
    {
        return E_FAIL;
    }

    D3DCAPS9 d3dcaps;
    ZeroMemory(&d3dcaps, sizeof(D3DCAPS9));
    if (FAILED(g_pDirect3D->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps)))
    {
        return E_FAIL;
    }

    int vp = 0;
    if (d3dcaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
    {
        vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    }
    else
    {
        vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }

    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
    d3dpp.BackBufferWidth = WNDWIDTH;
    d3dpp.BackBufferHeight = WNDHEIGHT;
    d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
    d3dpp.BackBufferCount = 1;
    d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
    d3dpp.MultiSampleQuality = 0;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = g_hWnd;
    d3dpp.Windowed = TRUE;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
    d3dpp.Flags = 0;
    d3dpp.FullScreen_RefreshRateInHz = 0;
    d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
    if (FAILED(g_pDirect3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vp, &d3dpp, &g_pDirect3DDevice)))
    {
        return E_FAIL;
    }

    if (FAILED(D3DXCreateFont(g_pDirect3DDevice, 24, 0, 0, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("Arial"), &g_pD3DXFont)))
    {
        return E_FAIL;
    }

    if (!GameInit())
    {
        return E_FAIL;
    }

    return S_OK;
}

VOID Direct3DRender()
{
    g_pDirect3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);
    if (SUCCEEDED(g_pDirect3DDevice->BeginScene()))
    {
        GameRender();
        g_pDirect3DDevice->EndScene();
        g_pDirect3DDevice->Present(NULL, NULL, NULL, NULL);
    }
}

VOID Direct3DClean()
{
    GameClean();

    g_pD3DXFont->Release();
    g_pD3DXFont = NULL;

    g_pDirect3DDevice->Release();
    g_pDirect3DDevice = NULL;

    g_pDirect3D->Release();
    g_pDirect3D = NULL;
}

bool GameInit()
{
    if (FAILED(g_pDirect3DDevice->CreateVertexBuffer(8 * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertextBuffer, NULL)))
    {
        return false;
    }

    if (FAILED(g_pDirect3DDevice->CreateIndexBuffer(36 * sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIndexBuffer, NULL)))
    {
        return false;
    }

    CUSTOMVERTEX vertices[] = 
    {
        { -20.0f, 20.0f, -20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
        { -20.0f, 20.0f, 20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
        { 20.0f, 20.0f, 20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
        { 20.0f, 20.0f, -20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },

        { -20.0f, -20.0f, -20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
        { -20.0f, -20.0f, 20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
        { 20.0f, -20.0f, 20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
        { 20.0f, -20.0f, -20.0f, D3DCOLOR_XRGB(rand() % 256, rand() % 256, rand() % 256) },
    };

    VOID* pVertices = NULL;
    if (FAILED(g_pVertextBuffer->Lock(0,sizeof(vertices), &pVertices, 0)))
    {
        return false;
    }
    memcpy(pVertices, vertices,sizeof(vertices));
    g_pVertextBuffer->Unlock();

    WORD indices[] =
    {
        0, 1, 2,
        0, 2, 3,
        0, 4, 5,
        0, 5, 1,
        0, 3, 7,
        0, 7, 4,
        6, 7, 3,
        6, 3, 2,
        6, 2, 1,
        6, 1, 5,
        6, 5, 4,
        6, 4, 7
    };
    void* pIndices = NULL;
    if (FAILED(g_pIndexBuffer->Lock(0, sizeof(indices), &pIndices, 0)))
    {
        return false;
    }
    memcpy(pIndices, indices, sizeof(indices));
    g_pIndexBuffer->Unlock();

    g_pDirect3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
    g_pDirect3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

    return true;
}

void MatrixSet()
{
    D3DXMATRIX matWorld, Rx, Ry, Rz;
    D3DXMatrixIdentity(&matWorld);
    D3DXMatrixRotationX(&Rx, D3DX_PI * timeGetTime() / 1000.0f);
    D3DXMatrixRotationY(&Ry, D3DX_PI * timeGetTime() / 1000.0f /2.0f);
    D3DXMatrixRotationZ(&Rz, D3DX_PI * timeGetTime() / 1000.0f /3.0f);

    matWorld = Rx * Ry * Rz * matWorld;
    g_pDirect3DDevice->SetTransform(D3DTS_WORLD, &matWorld);

    D3DXMATRIX matView;
    D3DXVECTOR3 vEye(0.0f, 0.0f, -200.0f);
    D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f);
    D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f);
    D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp);
    g_pDirect3DDevice->SetTransform(D3DTS_VIEW, &matView);

    D3DXMATRIX matProj;
    D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4.0f, 1.0f, 1.0f, 1000.0f);
    g_pDirect3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);

    D3DVIEWPORT9 vp;
    vp.X = 0;
    vp.Y = 0;
    vp.Width = WNDWIDTH;
    vp.Height = WNDHEIGHT;
    vp.MinZ = 0.0f;
    vp.MaxZ = 1.0f;
    g_pDirect3DDevice->SetViewport(&vp);
}

void GameRender()
{
    MatrixSet();
    if (::GetAsyncKeyState(0x31 & 0x8000F))
    {
        g_pDirect3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
    }

    if (::GetAsyncKeyState(0x32 & 0x8000F))
    {
        g_pDirect3DDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    }

    g_pDirect3DDevice->SetStreamSource(0, g_pVertextBuffer, 0, sizeof(CUSTOMVERTEX));
    g_pDirect3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
    g_pDirect3DDevice->SetIndices(g_pIndexBuffer);
    g_pDirect3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
}

void GameClean()
{
    g_pVertextBuffer->Release();
    g_pVertextBuffer = NULL;

    g_pIndexBuffer->Release();
    g_pIndexBuffer = NULL;
}

心里好难受,不知道什么时候才能学到手。
练习撒~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

当当小螳螂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值