DirectX Box

通过该Demo,可以清楚了解DirectX流程。将完整程序贴出,自己加以注释,方面查看理解。

  1 /*
  2 2015.4
  3 d3dUtil.h
  4 
  5 d3d 常用工具代码
  6 */
  7 
  8 #ifndef D3DUTIL_H
  9 #define D3DUTIL_H
 10 
 11 // Let VC++ know we are compiling for WinXP and up.  This let's us use
 12 // API functions specific to WinXP (e.g., WM_INPUT API).
 13 #ifndef _WIN32_WINNT
 14 #define _WIN32_WINNT   0x0600 // Vista
 15 #endif
 16 
 17 // Enable extra D3D debugging in debug builds if using the debug DirectX runtime.  
 18 // This makes D3D objects work well in the debugger watch window, but slows down 
 19 // performance slightly.
 20 #if defined(DEBUG) || defined(_DEBUG)
 21     #ifndef D3D_DEBUG_INFO
 22     #define D3D_DEBUG_INFO
 23     #endif
 24 #endif
 25 
 26 #if defined(DEBUG) || defined(_DEBUG)
 27 #define _CRTDBG_MAP_ALLOC
 28 #include <crtdbg.h>
 29 #endif
 30 
 31 
 32 #include <d3dx10.h>
 33 #include <dxerr.h>
 34 #include <cassert>
 35 
 36 // Simple d3d error checker.
 37 #if defined(DEBUG) | defined(_DEBUG)
 38 #ifndef HR
 39 #define HR(x)                                                    \
 40     {                                                            \
 41         HRESULT hr = (x);                                        \
 42         if (FAILED(hr))                                            \
 43         {                                                        \
 44             DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true);    \
 45         }                                                        \
 46     }                                                            \
 47 /*当DXTrace函数的最后一个参数设为false时,该函数不会显示消息框,
 48 而是把调试信息输出到Visual C++的输出窗口*/
 49 #endif
 50 
 51 #else
 52 #ifndef HR
 53 #define HR(x) (x)
 54 #endif
 55 #endif 
 56 
 57 // releasing COM objects
 58 #define ReleaseCOM(x) { if(x){ x->Release();x = 0; } }
 59 
 60 // 内联函数
 61 // Converts ARGB 32-bit color format to ABGR 32-bit color format.
 62 D3DX10INLINE UINT ARGB2ABGR(UINT argb)
 63 {
 64     BYTE A = (argb >> 24) & 0xff;
 65     BYTE R = (argb >> 16) & 0xff;
 66     BYTE G = (argb >> 8) & 0xff;
 67     BYTE B = (argb >> 0) & 0xff;
 68 
 69     return (A << 24) | (B << 16) | (G << 8) | (R << 0);
 70 }
 71 
 72 // Returns random float in [0, 1).
 73 D3DX10INLINE float RandF()
 74 {
 75     return (float)(rand()) / (float)RAND_MAX;
 76 }
 77 // Returns random float in [a, b).
 78 D3DX10INLINE float RandF(float a, float b)
 79 {
 80     return a + RandF()*(b - a);
 81 }
 82 
 83 // 获得单位球体向量
 84 D3DX10INLINE D3DXVECTOR3 RandUnitVec3()
 85 {
 86     D3DXVECTOR3 v(RandF(), RandF(), RandF());
 87     D3DXVec3Normalize(&v, &v);
 88     return v;
 89 }
 90 
 91 template<typename T>
 92 D3DX10INLINE T Min(const T& a, const T& b)
 93 {
 94     return a < b ? a : b;
 95 }
 96 
 97 template<typename T>
 98 D3DX10INLINE T Max(const T& a, const T& b)
 99 {
100     return a > b ? a : b;
101 }
102 
103 //线性插值,在不生成像素的情况下增加图像像素大小的一种方法
104 template<typename T>
105 D3DX10INLINE T Lerp(const T& a, const T& b, float t)
106 {
107     return a + (b - a)*t;
108 }
109 
110 template<typename T>
111 D3DX10INLINE T Clamp(const T& x, const T& low, const T& high)
112 {
113     return x < low ? low : (x > high ? high : x);
114 }
115 
116 const float PI = 3.14159265358979323f;
117 const float MATH_EPS = 0.0001f;
118 
119 const D3DXCOLOR WHITE(1.0f, 1.0f, 1.0f, 1.0f);
120 const D3DXCOLOR BLACK(0.0f, 0.0f, 0.0f, 1.0f);
121 const D3DXCOLOR RED(1.0f, 0.0f, 0.0f, 1.0f);
122 const D3DXCOLOR GREEN(0.0f, 1.0f, 0.0f, 1.0f);
123 const D3DXCOLOR BLUE(0.0f, 0.0f, 1.0f, 1.0f);
124 const D3DXCOLOR YELLOW(1.0f, 1.0f, 0.0f, 1.0f);
125 const D3DXCOLOR CYAN(0.0f, 1.0f, 1.0f, 1.0f);
126 const D3DXCOLOR MAGENTA(1.0f, 0.0f, 1.0f, 1.0f);
127 
128 const D3DXCOLOR BEACH_SAND(1.0f, 0.96f, 0.62f, 1.0f);
129 const D3DXCOLOR LIGHT_YELLOW_GREEN(0.48f, 0.77f, 0.46f, 1.0f);
130 const D3DXCOLOR DARK_YELLOW_GREEN(0.1f, 0.48f, 0.19f, 1.0f);
131 const D3DXCOLOR DARKBROWN(0.45f, 0.39f, 0.34f, 1.0f);
132 
133 #endif

 

 1 /*
 2 2015.4
 3 GameTimer.h
 4 
 5 */
 6 
 7 #ifndef GAMETIMER_H
 8 #define GAMETIMER_H
 9 
10 class GameTimer
11 {
12 public:
13     GameTimer();
14 
15     float getGameTime()const;  // in seconds
16 
17     // 获得增量
18     float getDeltaTime()const; // in seconds
19 
20     void reset(); // Call before message loop.
21     void start(); // Call when unpaused.
22     void stop();  // Call when paused.
23     void tick();  // Call every frame.
24 
25 private:
26     double mSecondsPerCount;
27     double mDeltaTime;
28 
29     __int64 mBaseTime;
30     __int64 mPausedTime;
31     __int64 mStopTime;
32     __int64 mPrevTime;
33     __int64 mCurrTime;
34 
35     bool mStopped;
36 };
37 
38 #endif 

 

  1 /*
  2 2015.4
  3 GameTimer.cpp
  4 
  5 */
  6 #include "GameTimer.h"
  7 #include <windows.h>
  8 
  9 GameTimer::GameTimer()
 10 : mSecondsPerCount(0.0), mDeltaTime(-1.0), mBaseTime(0),
 11 mPausedTime(0), mPrevTime(0), mCurrTime(0), mStopped(false)
 12 {
 13     __int64 countsPerSec;
 14 
 15     // 获取性能计时器的频率(每秒的计数次数)
 16     QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec);
 17     mSecondsPerCount = 1.0 / (double)countsPerSec;
 18 }
 19 
 20 // Returns the total time elapsed since reset() was called, NOT counting any
 21 // time when the clock is stopped.
 22 float GameTimer::getGameTime()const
 23 {
 24     // If we are stopped, do not count the time that has passed since we stopped.
 25     //
 26     // ----*---------------*------------------------------*------> time
 27     //  mBaseTime       mStopTime                      mCurrTime
 28 
 29     if (mStopped)
 30     {
 31         return (float)((mStopTime - mBaseTime)*mSecondsPerCount);
 32     }
 33 
 34     // The distance mCurrTime - mBaseTime includes paused time,
 35     // which we do not want to count.  To correct this, we can subtract 
 36     // the paused time from mCurrTime:  
 37     //
 38     //  (mCurrTime - mPausedTime) - mBaseTime 
 39     //
 40     //                     |<-------d------->|
 41     // ----*---------------*-----------------*------------*------> time
 42     //  mBaseTime       mStopTime        startTime     mCurrTime
 43 
 44     else
 45     {
 46         return (float)(((mCurrTime - mPausedTime) - mBaseTime)*mSecondsPerCount);
 47     }
 48 }
 49 
 50 float GameTimer::getDeltaTime()const
 51 {
 52     return (float)mDeltaTime;
 53 }
 54 
 55 void GameTimer::reset()
 56 {
 57     __int64 currTime;
 58     QueryPerformanceCounter((LARGE_INTEGER*)&currTime);
 59 
 60     mBaseTime = currTime;
 61     mPrevTime = currTime;
 62     mStopTime = 0;
 63     mStopped = false;
 64 }
 65 
 66 void GameTimer::start()
 67 {
 68     __int64 startTime;
 69     QueryPerformanceCounter((LARGE_INTEGER*)&startTime);
 70 
 71 
 72     // Accumulate the time elapsed between stop and start pairs.
 73     //
 74     //                     |<-------d------->|
 75     // ----*---------------*-----------------*------------> time
 76     //  mBaseTime       mStopTime        startTime     
 77 
 78     if (mStopped)
 79     {
 80         mPausedTime += (startTime - mStopTime);
 81 
 82         mPrevTime = startTime;
 83         mStopTime = 0;
 84         mStopped = false;
 85     }
 86 }
 87 
 88 void GameTimer::stop()
 89 {
 90     if (!mStopped)
 91     {
 92         __int64 currTime;
 93         QueryPerformanceCounter((LARGE_INTEGER*)&currTime);
 94 
 95         mStopTime = currTime;
 96         mStopped = true;
 97     }
 98 }
 99 
100 void GameTimer::tick()
101 {
102     if (mStopped)
103     {
104         mDeltaTime = 0.0;
105         return;
106     }
107 
108     __int64 currTime;
109     QueryPerformanceCounter((LARGE_INTEGER*)&currTime);
110     mCurrTime = currTime;
111 
112     // Time difference between this frame and the previous.
113     mDeltaTime = (mCurrTime - mPrevTime)*mSecondsPerCount;
114 
115     // Prepare for next frame.
116     mPrevTime = mCurrTime;
117 
118     // Force nonnegative.  The DXSDK's CDXUTTimer mentions that if the 
119     // processor goes into a power save mode or we get shuffled to another
120     // processor, then mDeltaTime can be negative.
121     if (mDeltaTime < 0.0)
122     {
123         mDeltaTime = 0.0;
124     }
125 }

 

 1 /*
 2 2015.4
 3 d3dApp.h
 4 
 5 Simple Direct3D demo application class.
 6 
 7 Make sure you link: d3d10.lib d3dx10d.lib dxerr.lib dxguid.lib.
 8 Link d3dx10.lib for release mode builds instead of d3dx10d.lib.
 9 */
10 
11 #ifndef D3DAPP_H
12 #define D3DAPP_H
13 
14 
15 #include "d3dUtil.h"
16 #include "GameTimer.h"
17 #include <string>
18 
19 #pragma comment(lib, "d3d10.lib")
20 #pragma comment(lib, "d3dx10d.lib")
21 #pragma comment(lib, "dxguid.lib")
22 #pragma comment(lib, "dxerr.lib")
23 
24 class D3DApp
25 {
26 public:
27     D3DApp(HINSTANCE hInstance);
28     virtual ~D3DApp();
29 
30     HINSTANCE getAppInst();
31     HWND      getMainWnd();
32 
33     int run();
34 
35     // Framework methods.  Derived client class overrides these methods to 
36     // implement specific application requirements.
37 
38     virtual void initApp();
39     virtual void onResize();// reset projection/etc
40     virtual void updateScene(float dt);
41     virtual void drawScene();
42     virtual LRESULT msgProc(UINT msg, WPARAM wParam, LPARAM lParam);
43 
44 protected:
45     void initMainWindow();
46     void initDirect3D();
47 
48 protected:
49 
50     HINSTANCE mhAppInst;
51     HWND      mhMainWnd;
52     bool      mAppPaused;
53     bool      mMinimized;
54     bool      mMaximized;
55     bool      mResizing;
56 
57     GameTimer mTimer;
58 
59     std::wstring mFrameStats;
60 
61     ID3D10Device*    md3dDevice;
62     IDXGISwapChain*  mSwapChain;
63     ID3D10Texture2D* mDepthStencilBuffer;
64     ID3D10RenderTargetView* mRenderTargetView;
65     ID3D10DepthStencilView* mDepthStencilView;
66     ID3DX10Font* mFont;
67 
68     // Derived class should set these in derived constructor to customize starting values.
69     std::wstring mMainWndCaption;
70     D3D10_DRIVER_TYPE md3dDriverType;
71     D3DXCOLOR mClearColor;
72     int mClientWidth;
73     int mClientHeight;
74 };
75 
76 #endif // D3DAPP_H

 

  1 /*
  2 2015.4
  3 d3dApp.cpp
  4 
  5 */
  6 #include "d3dApp.h"
  7 #include <sstream>
  8 
  9 LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 10 {
 11     static D3DApp* app = 0;
 12 
 13     switch (msg)
 14     {
 15     case WM_CREATE:
 16     {
 17         // Get the 'this' pointer we passed to CreateWindow via the lpParam parameter.
 18         // CREATESTRUCT结构定义了应用程序中窗口过程的初始化参数
 19         CREATESTRUCT* cs = (CREATESTRUCT*)lParam;
 20         app = (D3DApp*)cs->lpCreateParams;
 21         return 0;
 22     }
 23     }
 24 
 25     // Don't start processing messages until after WM_CREATE.
 26     if (app)
 27         return app->msgProc(msg, wParam, lParam);
 28     else
 29         return DefWindowProc(hwnd, msg, wParam, lParam);
 30 }
 31 
 32 D3DApp::D3DApp(HINSTANCE hInstance)
 33 {
 34     mhAppInst = hInstance;
 35     mhMainWnd = 0;
 36     mAppPaused = false;
 37     mMinimized = false;
 38     mMaximized = false;
 39     mResizing = false;
 40 
 41     mFrameStats = L"";
 42 
 43     md3dDevice = 0;
 44     mSwapChain = 0;
 45     mDepthStencilBuffer = 0;
 46     mRenderTargetView = 0;
 47     mDepthStencilView = 0;
 48     mFont = 0;
 49 
 50     mMainWndCaption = L"D3D10 Application";
 51     md3dDriverType = D3D10_DRIVER_TYPE_HARDWARE;
 52     mClearColor = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);    // Set background color
 53     mClientWidth = 800;
 54     mClientHeight = 600;
 55 }
 56 
 57 D3DApp::~D3DApp()
 58 {
 59     ReleaseCOM(mRenderTargetView);
 60     ReleaseCOM(mDepthStencilView);
 61     ReleaseCOM(mSwapChain);
 62     ReleaseCOM(mDepthStencilBuffer);
 63     ReleaseCOM(md3dDevice);
 64     ReleaseCOM(mFont);
 65 }
 66 
 67 HINSTANCE D3DApp::getAppInst()
 68 {
 69     return mhAppInst;
 70 }
 71 
 72 HWND D3DApp::getMainWnd()
 73 {
 74     return mhMainWnd;
 75 }
 76 
 77 int D3DApp::run()
 78 {
 79     MSG msg = { 0 };
 80 
 81     mTimer.reset();
 82 
 83     while (msg.message != WM_QUIT)
 84     {
 85         // If there are Window messages then process them.
 86         if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
 87         {
 88             TranslateMessage(&msg);
 89             DispatchMessage(&msg);
 90         }
 91         // Otherwise, do animation/game.
 92         else
 93         {
 94             mTimer.tick();
 95 
 96             if (!mAppPaused)
 97                 updateScene(mTimer.getDeltaTime());
 98             else
 99                 Sleep(50);
100 
101             drawScene();
102         }
103     }
104     return (int)msg.wParam;
105 }
106 
107 void D3DApp::initApp()
108 {
109     initMainWindow();
110     initDirect3D();
111 
112     D3DX10_FONT_DESC fontDesc;
113     fontDesc.Height = 20;
114     fontDesc.Width = 0;
115     fontDesc.Weight = 500; // 字体的粗细0~1000
116     fontDesc.MipLevels = 1;
117     fontDesc.Italic = false;//非斜体
118     fontDesc.CharSet = DEFAULT_CHARSET;
119     fontDesc.OutputPrecision = OUT_DEFAULT_PRECIS;
120     fontDesc.Quality = DEFAULT_QUALITY;
121     fontDesc.PitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
122     wcscpy_s(fontDesc.FaceName, L"Arial");// font style
123 
124     D3DX10CreateFontIndirect(md3dDevice, &fontDesc, &mFont);
125     ////文本输出示例:
126     //// We specify DT_NOCLIP, so we do not care about width/height of the rect.
127     //const D3DXCOLOR BLACK(0.0f, 0.0f, 0.0f, 1.0f);
128     //RECT R = { 5, 5, 0, 0 };
129     //mFont->DrawText(0, L"Hello, Direct3D!", -1, &R, DT_NOCLIP, BLACK);
130 }
131 
132 void D3DApp::onResize()
133 {
134     // Release the old views, as they hold references to the buffers we
135     // will be destroying.  Also release the old depth/stencil buffer.
136 
137     ReleaseCOM(mRenderTargetView);
138     ReleaseCOM(mDepthStencilView);
139     ReleaseCOM(mDepthStencilBuffer);
140 
141 
142     // Resize the swap chain and recreate the render target view.
143 
144     HR(mSwapChain->ResizeBuffers(1, mClientWidth, mClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
145     ID3D10Texture2D* backBuffer;
146     HR(mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)));
147     HR(md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView));
148     ReleaseCOM(backBuffer);
149 
150 
151     // Create the depth/stencil buffer and view.
152 
153     D3D10_TEXTURE2D_DESC depthStencilDesc;
154 
155     depthStencilDesc.Width = mClientWidth;
156     depthStencilDesc.Height = mClientHeight;
157     depthStencilDesc.MipLevels = 1;
158     depthStencilDesc.ArraySize = 1;
159     depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
160     depthStencilDesc.SampleDesc.Count = 1; // multisampling must match
161     depthStencilDesc.SampleDesc.Quality = 0; // swap chain values.
162     depthStencilDesc.Usage = D3D10_USAGE_DEFAULT;
163     depthStencilDesc.BindFlags = D3D10_BIND_DEPTH_STENCIL;
164     depthStencilDesc.CPUAccessFlags = 0;
165     depthStencilDesc.MiscFlags = 0;
166 
167     HR(md3dDevice->CreateTexture2D(&depthStencilDesc, 0, &mDepthStencilBuffer));
168     HR(md3dDevice->CreateDepthStencilView(mDepthStencilBuffer, 0, &mDepthStencilView));
169 
170 
171     // Bind the render target view and depth/stencil view to the pipeline.
172 
173     md3dDevice->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView);
174 
175 
176     // Set the viewport transform.
177 
178     D3D10_VIEWPORT vp;
179     vp.TopLeftX = 0;
180     vp.TopLeftY = 0;
181     vp.Width = mClientWidth;
182     vp.Height = mClientHeight;
183     vp.MinDepth = 0.0f;
184     vp.MaxDepth = 1.0f;
185 
186     md3dDevice->RSSetViewports(1, &vp);
187 }
188 
189 void D3DApp::updateScene(float dt)
190 {
191     // Code computes the average frames per second, and also the 
192     // average time it takes to render one frame.
193 
194     static int frameCnt = 0;
195     static float t_base = 0.0f;
196 
197     frameCnt++;
198 
199     // Compute averages over one second period.
200     if ((mTimer.getGameTime() - t_base) >= 1.0f)
201     {
202         float fps = (float)frameCnt; // fps = frameCnt / 1
203         float mspf = 1000.0f / fps;
204 
205         std::wostringstream outs;
206         outs.precision(6);
207         outs << L"FPS: " << fps << L"\n"
208             << "Milliseconds(Per Frame): " << mspf;
209         mFrameStats = outs.str();
210 
211         // Reset for next average.
212         frameCnt = 0;
213         t_base += 1.0f;
214     }
215 }
216 
217 void D3DApp::drawScene()
218 {
219     // Set all the elements in a render target to one value
220     md3dDevice->ClearRenderTargetView(mRenderTargetView, mClearColor);
221 
222     // Clears the depth-stencil resource
223     md3dDevice->ClearDepthStencilView(mDepthStencilView, D3D10_CLEAR_DEPTH | D3D10_CLEAR_STENCIL, 1.0f, 0);
224 }
225 
226 LRESULT D3DApp::msgProc(UINT msg, WPARAM wParam, LPARAM lParam)
227 {
228     switch (msg)
229     {
230         // WM_ACTIVATE is sent when the window is activated or deactivated.  
231         // We pause the game when the window is deactivated and unpause it 
232         // when it becomes active.  
233     case WM_ACTIVATE:
234         if (LOWORD(wParam) == WA_INACTIVE)
235         {
236             mAppPaused = true;
237             mTimer.stop();
238         }
239         else
240         {
241             mAppPaused = false;
242             mTimer.start();
243         }
244         return 0;
245 
246         // WM_SIZE is sent when the user resizes the window.  
247     case WM_SIZE:
248         // Save the new client area dimensions.
249         mClientWidth = LOWORD(lParam);
250         mClientHeight = HIWORD(lParam);
251         if (md3dDevice)
252         {
253             if (wParam == SIZE_MINIMIZED)
254             {
255                 mAppPaused = true;
256                 mMinimized = true;
257                 mMaximized = false;
258             }
259             else if (wParam == SIZE_MAXIMIZED)
260             {
261                 mAppPaused = false;
262                 mMinimized = false;
263                 mMaximized = true;
264                 onResize();
265             }
266             else if (wParam == SIZE_RESTORED)
267             {
268 
269                 // Restoring from minimized state?
270                 if (mMinimized)
271                 {
272                     mAppPaused = false;
273                     mMinimized = false;
274                     onResize();
275                 }
276 
277                 // Restoring from maximized state?
278                 else if (mMaximized)
279                 {
280                     mAppPaused = false;
281                     mMaximized = false;
282                     onResize();
283                 }
284                 else if (mResizing)
285                 {
286                     // If user is dragging the resize bars, we do not resize 
287                     // the buffers here because as the user continuously 
288                     // drags the resize bars, a stream of WM_SIZE messages are
289                     // sent to the window, and it would be pointless (and slow)
290                     // to resize for each WM_SIZE message received from dragging
291                     // the resize bars.  So instead, we reset after the user is 
292                     // done resizing the window and releases the resize bars, which 
293                     // sends a WM_EXITSIZEMOVE message.
294                 }
295                 else // API call such as SetWindowPos or mSwapChain->SetFullscreenState.
296                 {
297                     onResize();
298                 }
299             }
300         }
301         return 0;
302 
303         // WM_EXITSIZEMOVE is sent when the user grabs the resize bars.
304     case WM_ENTERSIZEMOVE:
305         mAppPaused = true;
306         mResizing = true;
307         mTimer.stop();
308         return 0;
309 
310         // WM_EXITSIZEMOVE is sent when the user releases the resize bars.
311         // Here we reset everything based on the new window dimensions.
312     case WM_EXITSIZEMOVE:
313         mAppPaused = false;
314         mResizing = false;
315         mTimer.start();
316         onResize();
317         return 0;
318 
319         // WM_DESTROY is sent when the window is being destroyed.
320     case WM_DESTROY:
321         PostQuitMessage(0);
322         return 0;
323 
324         // The WM_MENUCHAR message is sent when a menu is active and the user presses 
325         // a key that does not correspond to any mnemonic or accelerator key. 
326     case WM_MENUCHAR:
327         // Don't beep when we alt-enter.
328         return MAKELRESULT(0, MNC_CLOSE);
329 
330         // Catch this message so to prevent the window from becoming too small.
331     case WM_GETMINMAXINFO:
332         ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200;
333         ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
334         return 0;
335     }
336 
337     return DefWindowProc(mhMainWnd, msg, wParam, lParam);
338 }
339 
340 void D3DApp::initMainWindow()
341 {
342     WNDCLASS wc;
343     wc.style = CS_HREDRAW | CS_VREDRAW;
344     wc.lpfnWndProc = MainWndProc;
345     wc.cbClsExtra = 0;
346     wc.cbWndExtra = 0;
347     wc.hInstance = mhAppInst;
348     wc.hIcon = LoadIcon(0, IDI_APPLICATION);
349     wc.hCursor = LoadCursor(0, IDC_ARROW);
350     wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
351     wc.lpszMenuName = 0;
352     wc.lpszClassName = L"D3DWndClassName";
353 
354     if (!RegisterClass(&wc))
355     {
356         MessageBox(0, L"RegisterClass FAILED", 0, 0);
357         PostQuitMessage(0);
358     }
359 
360     // Compute window rectangle dimensions based on requested client area dimensions.
361     RECT R = { 0, 0, mClientWidth, mClientHeight };
362     AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
363     int width = R.right - R.left;
364     int height = R.bottom - R.top;
365 
366     mhMainWnd = CreateWindow(L"D3DWndClassName", mMainWndCaption.c_str(),
367         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, mhAppInst, this);
368     if (!mhMainWnd)
369     {
370         MessageBox(0, L"CreateWindow FAILED", 0, 0);
371         PostQuitMessage(0);
372     }
373 
374     ShowWindow(mhMainWnd, SW_SHOW);
375     UpdateWindow(mhMainWnd);
376 }
377 
378 void D3DApp::initDirect3D()
379 {
380     // Fill out a DXGI_SWAP_CHAIN_DESC to describe our swap chain.
381     DXGI_SWAP_CHAIN_DESC sd;
382 
383     // describes the backbuffer display mode
384     sd.BufferDesc.Width = mClientWidth;
385     sd.BufferDesc.Height = mClientHeight;
386     sd.BufferDesc.RefreshRate.Numerator = 60;
387     sd.BufferDesc.RefreshRate.Denominator = 1;
388     sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
389     sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
390     sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
391 
392     // describes multi-sampling parameters
393     // No multisampling.
394     sd.SampleDesc.Count = 1;
395     sd.SampleDesc.Quality = 0;
396 
397     // The back buffer can be used for shader input or render-target output
398     sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
399 
400     sd.BufferCount = 1;
401 
402     sd.OutputWindow = mhMainWnd;
403 
404     sd.Windowed = true;
405 
406     sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
407 
408     sd.Flags = 0;
409 
410 
411     // Create the device.
412     UINT createDeviceFlags = 0;
413 #if defined(DEBUG) || defined(_DEBUG)  
414     createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
415 #endif
416 
417     HR(D3D10CreateDeviceAndSwapChain(
418         0,                 //default adapter
419         md3dDriverType,
420         0,                 // no software device
421         createDeviceFlags,
422         D3D10_SDK_VERSION,
423         &sd,
424         &mSwapChain,
425         &md3dDevice));
426 
427     onResize();
428 }

 

 1 /*
 2 2015.4
 3 Box.h
 4 
 5 */
 6 #ifndef BOX_H
 7 #define BOX_H
 8 
 9 #include "d3dUtil.h"
10 
11 struct Vertex
12 {
13     D3DXVECTOR3 pos;
14     D3DXCOLOR   color;
15 };
16 
17 class Box
18 {
19 public:
20     Box();
21     ~Box();
22 
23     void init(ID3D10Device* device, float scale);
24     void draw();
25 
26 private:
27     DWORD mNumVertices;
28     DWORD mNumFaces;
29 
30     ID3D10Device* md3dDevice;
31     ID3D10Buffer* mVB;
32     ID3D10Buffer* mIB;
33 };
34 
35 #endif // BOX_H

 

  1 /*
  2 2015.4
  3 Box.cpp
  4 
  5 */
  6 
  7 #include "Box.h"
  8 
  9 Box::Box()
 10 : mNumVertices(0), mNumFaces(0), md3dDevice(0), mVB(0), mIB(0)
 11 {
 12 }
 13  
 14 Box::~Box()
 15 {
 16     ReleaseCOM(mVB);
 17     ReleaseCOM(mIB);
 18 }
 19 
 20 void Box::init(ID3D10Device* device, float scale)
 21 {
 22     md3dDevice = device;
 23  
 24     mNumVertices = 8;
 25     mNumFaces    = 12; 
 26 
 27     // Create vertex buffer
 28     Vertex vertices[] =
 29     {
 30         { D3DXVECTOR3(-1.0f, -1.0f, -1.0f), WHITE},
 31         { D3DXVECTOR3(-1.0f, +1.0f, -1.0f), BLACK},
 32         { D3DXVECTOR3(+1.0f, +1.0f, -1.0f), RED},
 33         { D3DXVECTOR3(+1.0f, -1.0f, -1.0f), GREEN},
 34         { D3DXVECTOR3(-1.0f, -1.0f, +1.0f),  BLUE},
 35         { D3DXVECTOR3(-1.0f, +1.0f, +1.0f), YELLOW},
 36         { D3DXVECTOR3(+1.0f, +1.0f, +1.0f), CYAN},
 37         { D3DXVECTOR3(+1.0f, -1.0f, +1.0f), MAGENTA},
 38     };
 39 
 40     // Scale the box.
 41     // 乘上比例
 42     for(DWORD i = 0; i < mNumVertices; ++i)
 43         vertices[i].pos *= scale;
 44 
 45     // Describes a buffer resource
 46     /*
 47     typedef enum D3D10_USAGE { 
 48         D3D10_USAGE_DEFAULT    = 0,
 49         D3D10_USAGE_IMMUTABLE  = 1,    // only be read by the GPU.
 50         D3D10_USAGE_DYNAMIC    = 2,    // is accessible by both the GPU and the CPU (write only).
 51         D3D10_USAGE_STAGING    = 3
 52     } D3D10_USAGE;
 53 
 54     */
 55     D3D10_BUFFER_DESC vbd;
 56     vbd.Usage = D3D10_USAGE_IMMUTABLE;
 57     vbd.ByteWidth = sizeof(Vertex) * mNumVertices;
 58     vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
 59     vbd.CPUAccessFlags = 0;
 60     vbd.MiscFlags = 0;
 61 
 62     // Specifies data for initializing a subresource
 63     D3D10_SUBRESOURCE_DATA vinitData;
 64     vinitData.pSysMem = vertices;
 65 
 66     // Create a buffer (vertex buffer, index buffer, or shader-constant buffer)
 67     /*
 68     HRESULT CreateBuffer(
 69         [in]   const D3D10_BUFFER_DESC *pDesc,
 70         [in]   const D3D10_SUBRESOURCE_DATA *pInitialData,
 71         [out]  ID3D10Buffer **ppBuffer );
 72     */
 73     HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mVB));
 74 
 75     // Create the index buffer
 76     // Box 六面
 77     DWORD indices[] = {
 78         // front face
 79         0, 1, 2,
 80         0, 2, 3,
 81 
 82         // back face
 83         4, 6, 5,
 84         4, 7, 6,
 85 
 86         // left face
 87         4, 5, 1,
 88         4, 1, 0,
 89 
 90         // right face
 91         3, 2, 6,
 92         3, 6, 7,
 93 
 94         // top face
 95         1, 5, 6,
 96         1, 6, 2,
 97 
 98         // bottom face
 99         4, 0, 3, 
100         4, 3, 7
101     };
102 
103     D3D10_BUFFER_DESC ibd;
104     ibd.Usage = D3D10_USAGE_IMMUTABLE;
105     ibd.ByteWidth = sizeof(DWORD) * mNumFaces*3;
106     ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
107     ibd.CPUAccessFlags = 0;
108     ibd.MiscFlags = 0;
109 
110     D3D10_SUBRESOURCE_DATA iinitData;
111     iinitData.pSysMem = indices;
112     HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mIB));
113 }
114 
115 void Box::draw()
116 {
117     UINT stride = sizeof(Vertex);
118     UINT offset = 0;
119     /*
120     Bind an array of vertex buffers to the input-assembler stage
121 
122     void IASetVertexBuffers(
123         [in]  UINT StartSlot,
124         [in]  UINT NumBuffers,
125         [in]  ID3D10Buffer *const *ppVertexBuffers,
126         [in]  const UINT *pStrides,
127         [in]  const UINT *pOffsets );    //Pointer to an array of offset values;
128     */
129     md3dDevice->IASetVertexBuffers(0, 1, &mVB, &stride, &offset);
130 
131     /*
132     Bind an index buffer to the input-assembler stage.
133     将一个索引缓冲区绑定到输入汇编器阶段
134     void IASetIndexBuffer(
135         [in]  ID3D10Buffer *pIndexBuffer,
136         [in]  DXGI_FORMAT Format,
137         [in]  UINT Offset );
138     */
139     md3dDevice->IASetIndexBuffer(mIB, DXGI_FORMAT_R32_UINT, 0);
140 
141     /*
142     void DrawIndexed(
143         [in]  UINT IndexCount,
144         [in]  UINT StartIndexLocation,
145         [in]  INT BaseVertexLocation );    //Offset from the start of the vertex buffer to the first vertex
146     */
147     md3dDevice->DrawIndexed(mNumFaces*3, 0, 0);
148 
149 
150     /*
151     完成图元汇编后,顶点将被送往顶点着色器(vertex shader)阶段。顶点着色器可以被看成是一个以顶点作为输入输出数据的函数,
152     每个将要绘制的顶点都会通过顶点着色器推送至硬件.
153     */
154 }

 

 1 /*
 2 2015.4
 3 color.fx
 4 
 5 Transforms and colors geometry.
 6 使用下面的后缀来表示空间:L(局部空间)、W(世界空间)、V(观察空间)、H(齐次裁剪空间)
 7 */
 8 
 9 
10 cbuffer cbPerObject
11 {
12     // 常量缓冲区,由着色器来访问
13     float4x4 gWVP; 
14 };
15 
16 void VS(float3 iPosL  : POSITION,
17         float4 iColor : COLOR,
18         out float4 oPosH  : SV_POSITION,
19         out float4 oColor : COLOR)
20 {
21     // Transform to homogeneous clip space.
22     // 将顶点位置从局部空间变换到齐次裁剪空间,矩阵gWVP是世界矩阵、观察矩阵和投影矩阵的组合矩阵
23     // float4(iPosL, 1.0f)相当于“float4(iPosL.x,iPosL.y, iPosL.z, 1.0f)
24     oPosH = mul(float4(iPosL, 1.0f), gWVP);
25     
26     oColor = iColor;
27 }
28 
29 float4 PS(float4 posH  : SV_POSITION,
30           float4 color : COLOR) : SV_Target
31 {
32     // 这里像素着色器只是简单地返回插值颜色
33     return color;
34 }
35 
36 // 一个technique 由一个或多个pass 组成,每个pass实现一种不同的几何体渲染方式
37 technique10 ColorTech
38 {
39     // 一个pass 由一个顶点着色器、一个可选的几何着色器、一个像素着色器和一些渲染状态组成
40     pass P0
41     {
42         // 顶点着色器设置为版本4.0, 4.0不再使用常量寄存器,而是使用常量缓存Constant Buffer
43         SetVertexShader( CompileShader( vs_4_0, VS() ) );
44         SetGeometryShader( NULL );
45         SetPixelShader( CompileShader( ps_4_0, PS() ) );
46     }
47 }

 

  1 /*
  2 2015.4
  3 main_Box.cpp
  4 
  5 Color Cube
  6 Controls:
  7 'A'/'D'/'W'/'S' - Rotate
  8 */
  9 
 10 #include "d3dApp.h"
 11 #include "Box.h"
 12 
 13 class ColoredCubeApp : public D3DApp
 14 {
 15 public:
 16     ColoredCubeApp(HINSTANCE hInstance);
 17     ~ColoredCubeApp();
 18 
 19     void initApp();
 20     void onResize();
 21     void updateScene(float dt);
 22     void drawScene();
 23 
 24 private:
 25     void buildFX();
 26     void buildVertexLayouts();
 27 
 28 private:
 29     Box mBox;
 30 
 31     ID3D10Effect* mFX;
 32     ID3D10EffectTechnique* mTech;
 33     ID3D10InputLayout* mVertexLayout;
 34     ID3D10EffectMatrixVariable* mfxWVPVar;
 35 
 36     D3DXMATRIX mView;
 37     D3DXMATRIX mProj;
 38     D3DXMATRIX mWVP;
 39 
 40     float mTheta;
 41     float mPhi;
 42 };
 43 
 44 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,PSTR cmdLine, int showCmd)
 45 {
 46     // Enable run-time memory check for debug builds.
 47 #if defined(DEBUG) | defined(_DEBUG)
 48     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 49 #endif
 50 
 51     ColoredCubeApp theApp(hInstance);
 52     theApp.initApp();
 53 
 54     return theApp.run();
 55 }
 56 
 57 ColoredCubeApp::ColoredCubeApp(HINSTANCE hInstance)
 58 : D3DApp(hInstance), mFX(0), mTech(0), mVertexLayout(0),
 59 mfxWVPVar(0), mTheta(0.0f), mPhi(PI*0.25f)
 60 {
 61     // 设为单位矩阵
 62     D3DXMatrixIdentity(&mView);
 63     D3DXMatrixIdentity(&mProj);
 64     D3DXMatrixIdentity(&mWVP);
 65 }
 66 
 67 ColoredCubeApp::~ColoredCubeApp()
 68 {
 69     if (md3dDevice)
 70         md3dDevice->ClearState();
 71 
 72     ReleaseCOM(mFX);
 73     ReleaseCOM(mVertexLayout);
 74 }
 75 
 76 void ColoredCubeApp::initApp()
 77 {
 78     D3DApp::initApp();
 79 
 80     // Box 绑定到该 md3dDevice
 81     mBox.init(md3dDevice, 1.0f);
 82 
 83     buildFX();
 84     buildVertexLayouts();
 85 }
 86 
 87 void ColoredCubeApp::onResize()
 88 {
 89     D3DApp::onResize();
 90 
 91     float aspect = (float)mClientWidth / mClientHeight;
 92     D3DXMatrixPerspectiveFovLH(&mProj, 0.25f*PI, aspect, 1.0f, 1000.0f);
 93 }
 94 
 95 void ColoredCubeApp::updateScene(float dt)
 96 {
 97     D3DApp::updateScene(dt);
 98 
 99     // Update angles based on input to orbit camera around box.
100     //改变夹角
101     if (GetAsyncKeyState('A') & 0x8000)    mTheta -= 5.0f*dt; 
102     if (GetAsyncKeyState('D') & 0x8000)    mTheta += 5.0f*dt;
103     if (GetAsyncKeyState('W') & 0x8000)    mPhi -= 5.0f*dt;
104     if (GetAsyncKeyState('S') & 0x8000)    mPhi += 5.0f*dt;
105 
106     // Restrict the angle mPhi.
107     if (mPhi < 0.1f)    mPhi = 0.1f;
108     if (mPhi > PI - 0.1f)    mPhi = PI - 0.1f;
109 
110     // Convert Spherical to Cartesian coordinates: mPhi measured from +y
111     // and mTheta measured counterclockwise from -z.
112     float x = 5.0f*sinf(mPhi)*sinf(mTheta);
113     float z = -5.0f*sinf(mPhi)*cosf(mTheta);
114     float y = 5.0f*cosf(mPhi);
115 
116     // Build the view matrix.
117     D3DXVECTOR3 pos(x, y, z);
118     D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
119     D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
120 
121     D3DXMatrixLookAtLH(&mView, &pos, &target, &up);
122 }
123 
124 void ColoredCubeApp::drawScene()
125 {
126     D3DApp::drawScene();
127 
128     // Restore default states, input layout and primitive topology 
129     // because mFont->DrawText changes them.  Note that we can 
130     // restore the default states by passing null.
131     md3dDevice->OMSetDepthStencilState(0, 0);
132     float blendFactors[] = { 0.0f, 0.0f, 0.0f, 0.0f };
133     md3dDevice->OMSetBlendState(0, blendFactors, 0xffffffff);
134 
135     // 当一个input layout被创建以后, 调用IASetInputLayout函数可以把它绑定一个divece中
136     md3dDevice->IASetInputLayout(mVertexLayout);
137 
138     // vertex buffer只是在内存中存储了一系列内存点,用Primitive Topology告诉Direct3D用点形成几何图形的方式
139     md3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
140 
141     // set constants
142     mWVP = mView*mProj;
143     mfxWVPVar->SetMatrix((float*)&mWVP);
144 
145     D3D10_TECHNIQUE_DESC techDesc;
146     mTech->GetDesc(&techDesc);
147     for (UINT p = 0; p < techDesc.Passes; ++p)
148     {
149         /*Apply方法的作用:
150         更新存储在GPU 内存中的常量缓冲区、将着色器程序绑定到管线、并启用在pass中指定的各种渲染状态。
151         */
152         mTech->GetPassByIndex(p)->Apply(0);
153 
154         mBox.draw();
155     }
156 
157     // We specify DT_NOCLIP, so we do not care about width/height of the rect.
158     RECT R = { 5, 5, 0, 0 };
159     mFont->DrawText(0, mFrameStats.c_str(), -1, &R, DT_NOCLIP, BLACK);
160 
161     mSwapChain->Present(0, 0);
162 }
163 
164 // 着色器
165 void ColoredCubeApp::buildFX()
166 {
167     DWORD shaderFlags = D3D10_SHADER_ENABLE_STRICTNESS;
168 #if defined( DEBUG ) || defined( _DEBUG )
169     shaderFlags |= D3D10_SHADER_DEBUG;
170     shaderFlags |= D3D10_SHADER_SKIP_OPTIMIZATION;
171 #endif
172 
173     // 通用内存块,使用时应该对它执行相应的类型转换
174     // used to return object code and error messages in APIs that compile vertex, geometry and pixel shaders.
175     ID3D10Blob* compilationErrors = 0;
176 
177     HRESULT hr = 0;
178     // 编译着色器
179     hr = D3DX10CreateEffectFromFile(L"color.fx", 0, 0,
180         "fx_4_0", shaderFlags, 0, md3dDevice, 0, 0, &mFX, &compilationErrors, 0);
181     if (FAILED(hr))
182     {
183         if (compilationErrors)
184         {
185             MessageBoxA(0, (char*)compilationErrors->GetBufferPointer(), 0, 0);
186             ReleaseCOM(compilationErrors);
187         }
188         // Outputs a formatted error message to the debug stream
189         DXTrace(__FILE__, (DWORD)__LINE__, hr, L"D3DX10CreateEffectFromFile", true);
190     }
191 
192     // 获得指向technique对象的指针
193     mTech = mFX->GetTechniqueByName("ColorTech");
194 
195     /*
196     ID3D10Effect::GetVariableByName方法返回一个ID3D10EffectVariable指针。
197     它是一种通用效果变量类型;要获得指向特定类型变量的指针(例如,矩阵、向量、标量),
198     你必须使用相应的As*****方法(例如,AsMatrix、AsVector、AsScalar)。
199     然后可以通过C++接口来更新它们
200     */
201     mfxWVPVar = mFX->GetVariableByName("gWVP")->AsMatrix();
202 }
203 
204 // 构建图元
205 void ColoredCubeApp::buildVertexLayouts()
206 {
207     /*
208     typedef struct D3D10_INPUT_ELEMENT_DESC {
209         LPCSTR                     SemanticName;
210         UINT                       SemanticIndex;
211         DXGI_FORMAT                Format;
212         UINT                       InputSlot;        // between 0 and 15
213         UINT                       AlignedByteOffset;
214         D3D10_INPUT_CLASSIFICATION InputSlotClass;
215         UINT                       InstanceDataStepRate;
216     } D3D10_INPUT_ELEMENT_DESC;
217     */
218     D3D10_INPUT_ELEMENT_DESC vertexDesc[] =
219     {
220         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
221         { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }
222     };
223 
224     D3D10_PASS_DESC PassDesc;
225     // Get a pass description by calling ID3D10EffectPass::GetDesc
226     mTech->GetPassByIndex(0)->GetDesc(&PassDesc);
227 
228     /*
229     Create an input-layout object to describe the input-buffer data for the input-assembler stage.
230 
231     HRESULT CreateInputLayout(
232         [in]   const D3D10_INPUT_ELEMENT_DESC *pInputElementDescs,
233         [in]   UINT NumElements,
234         [in]   const void *pShaderBytecodeWithInputSignature,
235         [in]   SIZE_T BytecodeLength,
236         [out]  ID3D10InputLayout **ppInputLayout );
237 
238     After creating an input layout object, it must be bound to the input-assembler stage
239     before calling a draw API. 
240     */
241     HR(md3dDevice->CreateInputLayout(vertexDesc, 2, PassDesc.pIAInputSignature,
242         PassDesc.IAInputSignatureSize, &mVertexLayout));
243 }

 

posted @ 2015-04-25 16:36  ht-beyond  阅读(360)  评论(0编辑  收藏  举报