Direct3D入門之框架的搭建

    學習一樣東西,最好能夠從最基礎做起。學習D3D,筆者並不贊同直接繼承SDK Sample的CD3DApplication,然後override那幾個虛函數,因爲這樣會讓初學者對D3D更感神祕,因此我們需要從頭開始,不用害怕,其實一點都不難:)

一、Win32 SDK框架

    看過Petzold的《Windows程序設計》的朋友應該知道創建窗口的固定步驟。而利用Win32 SDK搭建D3D框架只不過是在這些步驟中加入一些調料罷了。具體步驟如下:

1、註冊窗體類;
2、創建窗口;
3、創建消息處理函數;
4、顯示窗口;
5、初始化D3D、初始化資源數據(如:頂點向量、紋理等);
6、進入消息循環,用PeekMessage處理消息,以便在空閒時進行渲染。

而初始化D3D又分下面四個步驟:

1、創建IDirect3D9[1]對象;
2、檢查硬件性能,判斷硬件是否支持特定的功能;
3、填充D3DPRESENT_PARAMETERS結構;
4、利用第3步中的結構體對象創建D3D設備(由於該步驟需要窗體的句柄,所以初始化D3D必須放在顯示窗口之後)。

 下面是框架代碼:

 

000001    //
000002    
// 全局變量
000003    
//
000004    
000005    IDirect3DDevice9* Device = 0;
000006    
000007    
000008    bool InitD3D(
000009        HINSTANCE hInstance,
000010        int width, int height,
000011        bool windowed,
000012        D3DDEVTYPE deviceType,
000013        IDirect3DDevice9** device)
000014    {
000015        WNDCLASS wc;
000016    
000017        wc.style = CS_HREDRAW | CS_VREDRAW;
000018        wc.lpfnWndProc = (WNDPROC)WndProc;
000019        wc.cbClsExtra = 0;
000020        wc.cbWndExtra = 0;
000021        wc.hInstance = hInstance;
000022        wc.hIcon = LoadIcon(0, IDI_APPLICATION);
000023        wc.hCursor = LoadCursor(0, IDC_ARROW);
000024        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
000025        wc.lpszMenuName = 0;
000026        wc.lpszClassName = "Direct3D9App";
000027        
// 註冊窗口類
000028        if( !RegisterClass(&wc) )
000029        {
000030            MessageBox(0, "RegisterClass() - FAILED", 0, 0);
000031            return false;
000032        }
000033            
000034        HWND hwnd = 0;
000035        
// 創建窗口
000036        hwnd = CreateWindow("Direct3D9App", "Direct3D9App",
000037            WS_EX_TOPMOST,
000038            0, 0, width, height,
000039            0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/);
000040    
000041        if( !hwnd )
000042        {
000043            MessageBox(0, "CreateWindow() - FAILED", 0, 0);
000044            return false;
000045        }
000046        
// 顯示窗口
000047        ShowWindow(hwnd, SW_SHOW);
000048        UpdateWindow(hwnd);
000049    
000050        
//
000051        
// 初始化D3D
000052        
//
000053    
000054        HRESULT hr = 0;
000055    
000056        
// 步驟1:創建IDirect3D9對象。
000057    
000058        IDirect3D9* d3d9 = 0;
000059     d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
000060    
000061     if( !d3d9 )
000062        {
000063            MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
000064            return false;
000065        }
000066    
000067        
// 步驟2:檢查硬件性能(這裏只檢查了是否支持頂點的硬件處理)
000068    
000069        D3DCAPS9 caps;
000070        d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);
000071    
000072        int vp = 0;
000073        if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
000074            vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
000075        else
000076            vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
000077    
000078        
// 步驟3:填充D3DPRESENT_PARAMETERS結構(參數說明請參考MSDN)
000079    
000080        D3DPRESENT_PARAMETERS d3dpp;
000081        d3dpp.BackBufferWidth = width;
000082        d3dpp.BackBufferHeight = height;
000083        d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
000084        d3dpp.BackBufferCount = 1;
000085        d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
000086        d3dpp.MultiSampleQuality = 0;
000087        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
000088        d3dpp.hDeviceWindow = hwnd;
000089        d3dpp.Windowed = windowed;
000090        d3dpp.EnableAutoDepthStencil = true;
000091        d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
000092        d3dpp.Flags = 0;
000093        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
000094        d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
000095    
000096        
// 步驟4:創建D3D設備
000097    
000098        hr = d3d9->CreateDevice(
000099            D3DADAPTER_DEFAULT,
// 主設備
000100            deviceType,
// 設備類型
000101            hwnd,
// 分配給設備的窗口句柄
000102            vp,
// 頂點處理方式
000103         &d3dpp,
// 表現參數
000104         device);
// 返回創建的設備
000105    
000106        if( FAILED(hr) )
000107        {
000108            
// 如果創建失敗,採用16爲深度緩存試試
000109            d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
000110            
000111            hr = d3d9->CreateDevice(
000112                D3DADAPTER_DEFAULT,
000113                deviceType,
000114                hwnd,
000115                vp,
000116                &d3dpp,
000117                device);
000118    
000119            if( FAILED(hr) )
000120            {
000121                d3d9->Release();
000122                MessageBox(0, "CreateDevice() - FAILED", 0, 0);
000123                return false;
000124            }
000125        }
000126    
000127        d3d9->Release();
000128        
000129        return true;
000130    }
000131    
000132    
// 消息循環
000133    int MsgLoop()
000134    {
000135        MSG msg;
000136        ZeroMemory(&msg, sizeof(MSG));
000137    
000138        while(msg.message != WM_QUIT)
000139        {
000140            if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
000141            {
000142                TranslateMessage(&msg);
000143                DispatchMessage(&msg);
000144            }
000145            else
000146     {    
000147                Display();    
// 渲染
000148     }
000149     }
000150     return msg.wParam;
000151    }
000152    
000153    
000154    
//
000155    
// 框架函數
000156    
//
000157    
000158    bool Setup()
000159    {
000160        
// 你可以在此初始化頂點向量、載入紋理等
000161    
000162        return true;
000163    }
000164    
000165    void Cleanup()
000166    {
000167        
// 清除在Setup中載入的資源
000168    }
000169    
000170    bool Display()
000171    {
000172        if( Device )
// 只有當設備有效時才能渲染
000173        {
000174            
// 在此填入渲染代碼
000175        }
000176        return true;
000177    }
000178    
000179    
//
000180    
// 窗口處理函數
000181    
//
000182    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
000183    {
000184        switch( msg )
000185        {
000186        case WM_DESTROY:
000187            PostQuitMessage(0);
000188            break;
000189            
000190        case WM_KEYDOWN:
000191            if( wParam == VK_ESCAPE )
000192                DestroyWindow(hwnd);
000193            break;
000194        }
000195        return DefWindowProc(hwnd, msg, wParam, lParam);
000196    }
000197    
000198    
//
000199    
// 程序入口
000200    
//
000201    int WINAPI WinMain(HINSTANCE hinstance,
000202                     HINSTANCE prevInstance,
000203                     PSTR cmdLine,
000204                     int showCmd)
000205    {
000206        if(!InitD3D(hinstance,
000207            640, 480, true, D3DDEVTYPE_HAL, &Device))
000208        {
000209            MessageBox(0, "InitD3D() - FAILED", 0, 0);
000210            return 0;
000211        }
000212            
000213        if(!Setup())
000214        {
000215            MessageBox(0, "Setup() - FAILED", 0, 0);
000216            return 0;
000217        }
000218    
000219        MsgLoop();
000220    
000221        Cleanup();
000222    
000223        Device->Release();
000224    
000225        return 0;
000226    }

二、MFC框架

    利用MFC,我們不用寫一行代碼就可以創建一個窗體,這是MFC封裝了那些繁瑣而固定的窗口創建代碼,這樣我們只需要初始化D3D就可以了。下面是通過不帶文檔的SDI 作爲示例來創建D3D的框架,具體步驟如下:

1、將InitD3D、Setup、Cleanup、Display作爲CMainFrame的成員函數,其中InitD3D需被應用程序類調用,應該將其置爲public,其餘爲內部函數;
2、在應用程序類(CWinApp的子類)的InitInstance()中顯示窗口之後,對D3D進行初始化;
3、override Run(),其實,這裏就是消息循環;

這裏需要注意:

填充D3DPRESENT_PARAMETERS時,BackBufferWidth和BackBufferHeight最好設置爲客戶區大小,hDeviceWindow設置爲視窗口的句柄m_wndView.m_hWnd,最重要的是Windowed[2]一定要置爲true,否則會產生“無效調用”的錯誤。

下面是實際代碼,該代碼渲染了一個帶貼圖的旋轉正方體:

000001    // MFCD3D.cpp : 定義應用程序的類行爲。
000002    
//
000003    
000004    #include "stdafx.h"
000005    #include "MFCD3D.h"
000006    #include "MainFrm.h"
000007    #include <mmsystem.h>
000008    
000009    #ifdef _DEBUG
000010    #define new DEBUG_NEW
000011    #endif
000012    
000013    
000014    
// CMFCD3DApp
000015    
000016    BEGIN_MESSAGE_MAP(CMFCD3DApp, CWinApp)
000017        ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
000018    END_MESSAGE_MAP()
000019    
000020    
000021    
// CMFCD3DApp 構造
000022    
000023    CMFCD3DApp::CMFCD3DApp()
000024    {
000025        
// TODO: 在此處添加構造代碼,
000026        
// 將所有重要的初始化放置在 InitInstance 中
000027    }
000028    
000029    
000030    
// 唯一的一個 CMFCD3DApp 對象
000031    
000032    CMFCD3DApp theApp;
000033    
000034    
// CMFCD3DApp 初始化
000035    
000036    BOOL CMFCD3DApp::InitInstance()
000037    {
000038        
// 如果一個運行在 Windows XP 上的應用程序清單指定要
000039        
// 使用 ComCtl32.dll 版本 6 或更高版本來啓用可視化方式,
000040        
//則需要 InitCommonControls()。否則,將無法創建窗口。
000041        InitCommonControls();
000042    
000043        CWinApp::InitInstance();
000044    
000045        
// 初始化 OLE 庫
000046        if (!AfxOleInit())
000047        {
000048            AfxMessageBox(IDP_OLE_INIT_FAILED);
000049            return FALSE;
000050        }
000051        AfxEnableControlContainer();
000052        
// 標準初始化
000053        
// 如果未使用這些功能並希望減小
000054        
// 最終可執行文件的大小,則應移除下列
000055        
// 不需要的特定初始化例程
000056        
// 更改用於存儲設置的註冊表項
000057        
// TODO: 應適當修改該字符串,
000058        
// 例如修改爲公司或組織名
000059        SetRegistryKey(_T("應用程序嚮導生成的本地應用程序"));
000060        
// 若要創建主窗口,此代碼將創建新的框架窗口
000061        
// 對象,然後將其設置爲應用程序的主窗口對象
000062        CMainFrame* pFrame = new CMainFrame;
000063        if (!pFrame)
000064            return FALSE;
000065        m_pMainWnd = pFrame;
000066        
// 創建並加載帶有其資源的框架
000067        pFrame->LoadFrame(IDR_MAINFRAME,
000068            WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
000069            NULL);
000070        
// 唯一的一個窗口已初始化,因此顯示它並對其進行更新
000071        pFrame->ShowWindow(SW_SHOW);
000072        pFrame->UpdateWindow();
000073        
// 僅當存在後綴時才調用 DragAcceptFiles,
000074        
// 在 SDI 應用程序中,這應在 ProcessShellCommand 之後發生
000075        
// D3D初始化
000076        return pFrame->InitD3D();
000077    }
000078    
000079    
000080    
// CMFCD3DApp 消息處理程序
000081    
000082    
000083    
000084    
// 用於應用程序“關於”菜單項的 CAboutDlg 對話框
000085    
000086    class CAboutDlg : public CDialog
000087    {
000088    public:
000089        CAboutDlg();
000090    
000091    
// 對話框數據
000092        enum { IDD = IDD_ABOUTBOX };
000093    
000094    protected:
000095        virtual void DoDataExchange(CDataExchange* pDX);
// DDX/DDV 支持
000096    
000097    
// 實現
000098    protected:
000099        DECLARE_MESSAGE_MAP()
000100    };
000101    
000102    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
000103    {
000104    }
000105    
000106    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
000107    {
000108        CDialog::DoDataExchange(pDX);
000109    }
000110    
000111    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
000112    END_MESSAGE_MAP()
000113    
000114    
// 用於運行對話框的應用程序命令
000115    void CMFCD3DApp::OnAppAbout()
000116    {
000117        CAboutDlg aboutDlg;
000118        aboutDlg.DoModal();
000119    }
000120    
000121    
000122    
// CMFCD3DApp 消息處理程序
000123    
000124    
000125    int CMFCD3DApp::Run()
000126    {
000127        MSG msg;
000128        ::ZeroMemory(&msg, sizeof(MSG));
000129    
000130        static float lastTime = (float)timeGetTime();
000131    
000132        while(msg.message != WM_QUIT)
000133        {
000134            if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
000135            {
000136                ::TranslateMessage(&msg);
000137                ::DispatchMessage(&msg);
000138            }
000139            else
000140            {
000141                float currTime = (float)timeGetTime();
000142                float timeDelta = (currTime - lastTime)*0.001f;
000143                lastTime = currTime;
000144    
000145                ((CMainFrame*)m_pMainWnd)->Render(timeDelta);
000146            }
000147     }
000148        return CWinApp::Run();
000149    }

 

000001    // MainFrm.cpp : CMainFrame 類的實現
000002    
//
000003    
000004    #include "stdafx.h"
000005    #include "MFCD3D.h"
000006    
000007    #include "MainFrm.h"
000008    
000009    #ifdef _DEBUG
000010    #define new DEBUG_NEW
000011    #endif
000012    
000013    const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_TEX1;
000014    
000015    
// CMainFrame
000016    
000017    IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
000018    
000019    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
000020        ON_WM_CREATE()
000021        ON_WM_SETFOCUS()
000022        ON_WM_DESTROY()
000023    END_MESSAGE_MAP()
000024    
000025    
000026    
// CMainFrame 構造/析構
000027    
000028    CMainFrame::CMainFrame()
000029    : m_d3dDevice(NULL)
000030     ,    m_pVB(NULL)
000031     , m_pIB(NULL)
000032     , m_pTex(NULL)
000033    {
000034        
// TODO: 在此添加成員初始化代碼
000035    }
000036    
000037    CMainFrame::~CMainFrame()
000038    {
000039    }
000040    
000041    
000042    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
000043    {
000044        if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
000045            return -1;
000046        
// 創建一個視圖以佔用框架的工作區
000047        if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
000048            CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
000049        {
000050            TRACE0("未能創建視圖窗口/n");
000051            return -1;
000052        }
000053        
000054        if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
000055            | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
000056            !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
000057        {
000058            TRACE0("未能創建工具欄/n");
000059            return -1;
// 未能創建
000060        }
000061        
// TODO: 如果不需要工具欄可停靠,則刪除這三行
000062        m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
000063        EnableDocking(CBRS_ALIGN_ANY);
000064        DockControlBar(&m_wndToolBar);
000065    
000066        return 0;
000067    }
000068    
000069    BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
000070    {
000071        if( !CFrameWnd::PreCreateWindow(cs) )
000072            return FALSE;
000073        
// TODO: 在此處通過修改 CREATESTRUCT cs 來修改窗口類或
000074        
// 樣式
000075    
000076        cs.style = WS_OVERLAPPED | WS_CAPTION | FWS_ADDTOTITLE
000077             | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
000078    
000079        cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
000080        cs.lpszClass = AfxRegisterWndClass(0);
000081        return TRUE;
000082    }
000083    
000084    
000085    
// CMainFrame 診斷
000086    
000087    #ifdef _DEBUG
000088    void CMainFrame::AssertValid() const
000089    {
000090        CFrameWnd::AssertValid();
000091    }
000092    
000093    void CMainFrame::Dump(CDumpContext& dc) const
000094    {
000095        CFrameWnd::Dump(dc);
000096    }
000097    
000098    #endif
//_DEBUG
000099    
000100    
000101    
// CMainFrame 消息處理程序
000102    
000103    void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/)
000104    {
000105        
// 將焦點前移到視圖窗口
000106        m_wndView.SetFocus();
000107    }
000108    
000109    BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
000110    {
000111        
// 讓視圖第一次嘗試該命令
000112        if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
000113            return TRUE;
000114    
000115        
// 否則,執行默認處理
000116        return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
000117    }
000118    
000119    
// 初始化D3D
000120    BOOL CMainFrame::InitD3D(void)
000121    {
000122        ASSERT(IsWindow(m_wndView.m_hWnd));
000123        
// 初始化Direct3D9
000124        
// Step1.獲得IDirect3D9接口
000125        IDirect3D9* _d3d9;
000126        _d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
000127        if(!_d3d9)
000128        {
000129            ::AfxMessageBox(_T("Get Interface of Direct3D Failed!") , MB_ICONSTOP);
000130            return FALSE;
000131        }
000132        
// Step2.檢查顯卡能力
000133        D3DCAPS9 caps;
000134        _d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT ,
000135            D3DDEVTYPE_HAL ,
000136            &caps);
000137        int vp = 0;
000138        if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
000139            vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
000140        else
000141            vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
000142        
// Step3.填充D3DPRESENT_PARAMETERS
000143        D3DPRESENT_PARAMETERS d3dpp;
000144        CRect rect;
000145        GetClientRect(&rect);
000146        ZeroMemory(&d3dpp,sizeof(D3DPRESENT_PARAMETERS));
000147        d3dpp.BackBufferWidth = rect.Width();
000148        d3dpp.BackBufferHeight = rect.Height();
000149        d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
000150        d3dpp.BackBufferCount = 1;
000151        d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
000152        d3dpp.MultiSampleQuality = 0;
000153        d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
000154        d3dpp.hDeviceWindow = m_wndView.m_hWnd;
000155        d3dpp.Windowed = true;        
// 一定要爲true
000156        d3dpp.EnableAutoDepthStencil = true;
000157        d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
000158        d3dpp.Flags = 0;
000159        d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
000160        d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
000161    
000162        
// Step4.創建Direct3D設備
000163        HRESULT hr;
000164        hr = _d3d9->CreateDevice(D3DADAPTER_DEFAULT ,
000165            D3DDEVTYPE_HAL ,
000166            m_wndView.m_hWnd ,
000167            vp ,
000168            &d3dpp ,
000169            &m_d3dDevice);
000170        if(FAILED(hr))
000171        {
000172            switch(hr)
000173            {
000174            case D3DERR_DEVICELOST:
000175                AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_DEVICELOST>") , MB_ICONSTOP);
000176                break;
000177            case D3DERR_INVALIDCALL:
000178                AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_INVALIDCALL>") , MB_ICONSTOP);
000179                break;
000180            case D3DERR_NOTAVAILABLE:
000181                AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_NOTAVAILABLE>") , MB_ICONSTOP);
000182                break;
000183            case D3DERR_OUTOFVIDEOMEMORY:
000184                AfxMessageBox(_T("Create D3D Device Failed!<Error:D3DERR_OUTOFVIDEOMEMORY>") , MB_ICONSTOP);
000185                break;
000186            }
000187            _d3d9->Release();
000188            return FALSE;
000189        }
000190        _d3d9->Release();
000191        
// Direct3D9初始化完成
000192        
// 裝載資源
000193        Setup();
000194        return TRUE;
000195    }
000196    
000197    
// 裝載資源
000198    BOOL CMainFrame::Setup(void)
000199    {
000200        
// 創建頂點緩衝區和索引緩衝
000201        m_d3dDevice->CreateVertexBuffer(36 * sizeof(Vertex) ,
000202            D3DUSAGE_WRITEONLY ,
000203            Vertex::FVF ,
000204            D3DPOOL_MANAGED ,
000205            &m_pVB ,
000206            0);
000207        
// 填充頂點緩衝區
000208        Vertex* pVertices;
000209        m_pVB->Lock(0 , 0 , (void**)&pVertices , 0);
000210    
000211        
// 前面
000212        pVertices[0] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 0.0f);
000213        pVertices[1] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000214        pVertices[2] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000215        pVertices[3] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 0.0f);
000216        pVertices[4] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000217        pVertices[5] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000218        
// 後面
000219        pVertices[6] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000220        pVertices[7] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000221        pVertices[8] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 1.0f);
000222        pVertices[9] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000223        pVertices[10] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 1.0f);
000224        pVertices[11] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000225        
// 上面
000226        pVertices[12] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000227        pVertices[13] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000228        pVertices[14] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 1.0f);
000229        pVertices[15] = Vertex(1.0f , 1.0f , 1.0f , 1.0f , 0.0f);
000230        pVertices[16] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 1.0f);
000231        pVertices[17] = Vertex(-1.0f , 1.0f , -1.0f , 0.0f , 1.0f);
000232        
// 下面
000233        pVertices[18] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 0.0f);
000234        pVertices[19] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 0.0f);
000235        pVertices[20] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000236        pVertices[21] = Vertex(1.0f , -1.0f , 1.0f , 1.0f , 0.0f);
000237        pVertices[22] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000238        pVertices[23] = Vertex(-1.0f , -1.0f , -1.0f , 0.0f , 1.0f);
000239        
// 左面
000240        pVertices[24] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000241        pVertices[25] = Vertex(-1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000242        pVertices[26] = Vertex(-1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000243        pVertices[27] = Vertex(-1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000244        pVertices[28] = Vertex(-1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000245        pVertices[29] = Vertex(-1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000246        
// 右面
000247        pVertices[30] = Vertex(1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000248        pVertices[31] = Vertex(1.0f , 1.0f , -1.0f , 1.0f , 0.0f);
000249        pVertices[32] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000250        pVertices[33] = Vertex(1.0f , 1.0f , 1.0f , 0.0f , 0.0f);
000251        pVertices[34] = Vertex(1.0f , -1.0f , -1.0f , 1.0f , 1.0f);
000252        pVertices[35] = Vertex(1.0f , -1.0f , 1.0f , 0.0f , 1.0f);
000253    
000254    
000255        m_pVB->Unlock();
000256    
000257        
// 創建紋理
000258        D3DXCreateTextureFromFile(m_d3dDevice , _T("bbq.jpg") , &m_pTex);
000259        m_d3dDevice->SetTexture(0 , m_pTex);
000260    
000261        m_d3dDevice->SetSamplerState(0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR);
000262        m_d3dDevice->SetSamplerState(0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR);
000263        m_d3dDevice->SetSamplerState(0 , D3DSAMP_MIPFILTER , D3DTEXF_POINT);
000264        
// 攝像機位置
000265        D3DXVECTOR3 pos(0.0f , 0.0f , -5.0f);
000266        D3DXVECTOR3 tag(0.0f , 0.0f , 0.0f);
000267        D3DXVECTOR3 up(0.0f , 1.0f , 0.0f);
000268        D3DXMATRIX v;
000269        D3DXMatrixLookAtLH(&v , &pos , &tag , &up);
000270        m_d3dDevice->SetTransform(D3DTS_VIEW , &v);
000271    
000272        
// 設置投影矩陣
000273        D3DXMATRIX proj;
000274        CRect rect;
000275        GetClientRect(&rect);
000276        D3DXMatrixPerspectiveFovLH(&proj , D3DX_PI * 0.5f ,
000277            (float)rect.Width()/(float)rect.Height() ,
000278            1.0f ,
000279            1000.0f);
000280        m_d3dDevice->SetTransform(D3DTS_PROJECTION , &proj);
000281    
000282        
// 設置渲染狀態
000283        m_d3dDevice->SetRenderState(D3DRS_LIGHTING , false);
000284        m_d3dDevice->SetRenderState(D3DRS_CULLMODE , D3DCULL_NONE);
000285    
000286        return TRUE;
000287    }
000288    
000289    
// 渲染
000290    void CMainFrame::Render(float timeDelta)
000291    {
000292        if(m_d3dDevice)
// Only use Device methods if we have a valid device.
000293        {
000294            
// 旋轉正方體
000295            D3DXMATRIX Rx , Ry;
000296                
// 在x方向旋轉45度
000297            D3DXMatrixRotationX(&Rx , 3.14f / 4.0f);
000298                
// 每一幀增加y
000299            static float y = 0.0f;
000300            D3DXMatrixRotationY(&Ry , y);
000301            y += timeDelta;
000302                
// 當繞y軸旋轉的角度達到360度時,置y爲0
000303            if(y >= 6.28f) y = 0.0f;
000304            
// 組合兩個方向上的旋轉
000305            D3DXMATRIX p = Rx * Ry;
000306            m_d3dDevice->SetTransform(D3DTS_WORLD , &p);
000307            
000308            
// 繪製場景
000309            m_d3dDevice->Clear(0 , 0 , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 0x000000ff , 1.0f , 0);
000310                
// 開始
000311            m_d3dDevice->BeginScene();
000312            {
000313                m_d3dDevice->SetStreamSource(0 , m_pVB , 0 , sizeof(Vertex));
000314                m_d3dDevice->SetFVF(Vertex::FVF);
000315                m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST , 0 , 12);
000316            }
000317            m_d3dDevice->EndScene();
000318                
// 結束
000319            m_d3dDevice->Present(0 , 0 , 0 , 0);
000320        }
000321    }
000322    
000323    
// 清除資源
000324    void CMainFrame::CleanUp(void)
000325    {
000326        m_pVB->Release();
000327        m_pTex->Release();
000328    }
000329    
000330    void CMainFrame::OnDestroy()
000331    {
000332        CFrameWnd::OnDestroy();
000333    
000334        CleanUp();
000335    
000336        m_d3dDevice->Release();
000337    }

 
效果圖:

[Groov0V]

__________________________

[1] 這裏以Direct3D 9.0爲例。
[2]該參數表示是否全屏(僅在Win32 SDK框架中有效)。
發佈了69 篇原創文章 · 獲贊 2 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章