1 // =============================================================
2 // Sean Smith
3 // Main.cpp
4 // =============================================================
5
6 // include the basic windows header files and the Direct3D header file
7 #include <windows.h>
8 #include <windowsx.h>
9 #include <d3d9.h>
10 #include <d3dx9.h>
11 #include <vector>
12 #include <time.h>
13 #include <math.h>
14 #include <sstream>
15 using namespace std;
16
17 // define the screen resolution and keyboard macros
18 #define SCREEN_WIDTH 1024
19 #define SCREEN_HEIGHT 768
20 #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
21 #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
22
23 // include the Direct3D Library files
24 #pragma comment (lib, "d3d9.lib")
25 #pragma comment (lib, "d3dx9.lib")
26
27 // global declarations
28 LPDIRECT3D9 d3d; // the pointer to our Direct3D interface
29 LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
30
31 // object variables
32 int numObjects = 5000;
33 float innerRadius = 3;
34 float outerRadius = 5;
35 int sides = 10;
36 int rings = 10;
37
38 // variables for benchmark
39 int startTime = 0, counter = 0, framerate = 0;
40
41 // color definitions
42 const D3DXCOLOR BLACK = D3DXCOLOR(0.0, 0.0, 0.0, 1.0);
43 const D3DXCOLOR WHITE = D3DXCOLOR(1.0, 1.0, 1.0, 1.0);
44 const D3DXCOLOR BLUE = D3DXCOLOR(0.0, 0.0, 1.0, 1.0);
45 const D3DXCOLOR GREEN = D3DXCOLOR(0.0, 1.0, 0.0, 1.0);
46 const D3DXCOLOR RED = D3DXCOLOR(1.0, 0.0, 0.0, 1.0);
47 const D3DXCOLOR CYAN = D3DXCOLOR(0.0, 1.0, 1.0, 1.0);
48 const D3DXCOLOR PURPLE = D3DXCOLOR(1.0, 0.0, 1.0, 1.0);
49
50 // function prototypes
51 void initD3D(HWND hWnd); // sets up and initializes Direct3D
52 void render_frame(void); // renders a single frame
53 void cleanD3D(void); // closes Direct3D and releases memory
54 void init_graphics(void); // 3D declarations
55 struct Torus; // mesh struct
56 void init_Torus(); //
57
58 // mesh declarations
59 LPD3DXMESH meshTorus; // define the mesh pointer
60 LPD3DXEFFECT shaderEffect1;
61 vector<Torus> torusVector;
62
63 // sprite declaration
64 //ID3DXSprite ID3DXSprite;
65 LPD3DXSPRITE textSprite;
66 ID3DXFont *font = NULL;
67
68 // the WindowProc function prototype
69 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
70
71 // mesh object struct
72 struct Torus
73 {
74 D3DXMATRIX pos;
75 D3DXMATRIX rotY;
76 D3DXCOLOR color;
77 };
78
79 //initialization
80 //describe an Arial 32-point font
81 D3DXFONT_DESC desc = {
82 32, //height
83 0, //width
84 0, //escapement
85 0, //orientation
86 0, //weight
87 false, //italic
88 false, //underline
89 false, //strikeout
90 DEFAULT_CHARSET, //character set
91 OUT_TT_PRECIS, //precision
92 CLIP_DEFAULT_PRECIS, //clipping
93 DEFAULT_QUALITY, //quality
94 DEFAULT_PITCH, //pitch and family
95 "Arial" //font name
96 };
97
98
99
100 // the entry point for any Windows program
101 int WINAPI WinMain(HINSTANCE hInstance,
102 HINSTANCE hPrevInstance,
103 LPSTR lpCmdLine,
104 int nCmdShow)
105 {
106 HWND hWnd;
107 WNDCLASSEX wc;
108
109 ZeroMemory(&wc, sizeof(WNDCLASSEX));
110
111 wc.cbSize = sizeof(WNDCLASSEX);
112 wc.style = CS_HREDRAW | CS_VREDRAW;
113 wc.lpfnWndProc = (WNDPROC)WindowProc;
114 wc.hInstance = hInstance;
115 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
116 wc.lpszClassName = "WindowClass";
117
118 RegisterClassEx(&wc);
119
120 hWnd = CreateWindowEx(NULL, "WindowClass", "D3DX Vertext and Pixel Shader 2",
121 WS_OVERLAPPEDWINDOW, 300, 300, SCREEN_WIDTH, SCREEN_HEIGHT,
122 NULL, NULL, hInstance, NULL);
123
124 ShowWindow(hWnd, nCmdShow);
125
126 // set up and initialize Direct3D
127 initD3D(hWnd);
128
129 // enter the main loop:
130
131 MSG msg;
132
133 while(TRUE)
134 {
135 DWORD starting_point = GetTickCount();
136
137 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
138 {
139 if (msg.message == WM_QUIT)
140 break;
141
142 TranslateMessage(&msg);
143 DispatchMessage(&msg);
144 }
145
146 render_frame();
147
148 // check the 'escape' key
149 if(KEY_DOWN(VK_ESCAPE))
150 PostMessage(hWnd, WM_DESTROY, 0, 0);
151
152 while ((GetTickCount() - starting_point) < 25);
153 }
154
155 // clean up DirectX and COM
156 cleanD3D();
157
158 return msg.wParam;
159 }
160
161
162 // this is the main message handler for the program
163 LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
164 {
165 switch(message)
166 {
167 case WM_DESTROY:
168 {
169 PostQuitMessage(0);
170 return 0;
171 } break;
172 }
173
174 return DefWindowProc (hWnd, message, wParam, lParam);
175 }
176
177
178 // this function initializes and prepares Direct3D for use
179 void initD3D(HWND hWnd)
180 {
181 d3d = Direct3DCreate9(D3D_SDK_VERSION);
182
183 D3DPRESENT_PARAMETERS d3dpp;
184
185 ZeroMemory(&d3dpp, sizeof(d3dpp));
186 d3dpp.Windowed = TRUE;
187 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
188 d3dpp.hDeviceWindow = hWnd;
189 d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
190 d3dpp.BackBufferWidth = SCREEN_WIDTH;
191 d3dpp.BackBufferHeight = SCREEN_HEIGHT;
192 d3dpp.EnableAutoDepthStencil = TRUE;
193 d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
194
195 // create a device class using this information and the info from the d3dpp stuct
196 d3d->CreateDevice(D3DADAPTER_DEFAULT,
197 D3DDEVTYPE_HAL,
198 hWnd,
199 D3DCREATE_HARDWARE_VERTEXPROCESSING,
200 &d3dpp,
201 &d3ddev);
202
203 srand(time(NULL));
204 init_graphics(); // initialize graphics
205 init_Torus(); // initialize torus object
206
207 return;
208 }
209
210
211 // this is the function used to render a single frame
212 void render_frame(void)
213 {
214 d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
215 d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
216
217 d3ddev->BeginScene();
218
219 counter++;
220 if (GetTickCount() > startTime + 1000)
221 {
222 framerate = counter;
223 counter = 0;
224 startTime = GetTickCount();
225 }
226
227 // begin drawing the text sprite
228 textSprite->Begin(D3DXSPRITE_ALPHABLEND);
229
230 RECT rect = {20, 20, SCREEN_WIDTH, SCREEN_HEIGHT};
231 D3DCOLOR color = D3DCOLOR_XRGB(0,255,0);
232
233 string fps = "";
234 static char string[256];
235 int vertObject = meshTorus->GetNumVertices();
236 int faceObject = meshTorus->GetNumFaces();
237 sprintf(string, "FPS: %d\n"
238 "Vertices per Object: %d\n"
239 "Faces per Object: %d\n"
240 "Total Verticies: %d\n"
241 "Total Faces: %d\n"
242 "Total Objects: %d\n",
243 framerate,
244 vertObject,
245 faceObject,
246 vertObject * numObjects,
247 faceObject * numObjects,
248 numObjects);
249 font->DrawText(textSprite, string, -1, &rect, DT_NOCLIP, color);
250
251 // set the view transform
252 D3DXMATRIX matView; // the view transform matrix
253 D3DXMatrixLookAtLH(&matView,
254 &D3DXVECTOR3 (0.0f, 3.0f, 250.0f), // the camera position
255 &D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // the look-at position
256 &D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction
257
258 // set the projection transform
259 D3DXMATRIX matProjection; // the projection transform matrix
260 D3DXMatrixPerspectiveFovLH(&matProjection,
261 D3DXToRadian(45), // the horizontal field of view
262 (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio
263 1.0f, // the near view-plane
264 2000.0f); // the far view-plane
265
266 //set the ambient/diffuse light source vector
267 D3DXVECTOR3 mLightVecW = D3DXVECTOR3(0.0, 1.0f, 1.0f);
268
269 //set the ambient/diffuse colors
270 float ambLevel = 0.1f;
271 float difLevel = 0.7f;
272 D3DXCOLOR mDiffuseLight = D3DXCOLOR(difLevel, difLevel, difLevel, 1.0f);
273 D3DXCOLOR mAmbientMtrl = WHITE;
274 D3DXCOLOR mAmbientLight = D3DXCOLOR(ambLevel, ambLevel, ambLevel, 1.0f);
275
276 //pass variables to shader
277 shaderEffect1->SetValue("gLightVecW", &mLightVecW, sizeof(D3DXVECTOR3));
278 shaderEffect1->SetValue("gDiffuseLight", &mDiffuseLight, sizeof(D3DXCOLOR));
279 shaderEffect1->SetValue("gAmbientMtrl", &mAmbientMtrl, sizeof(D3DXCOLOR));
280 shaderEffect1->SetValue("gAmbientLight", &mAmbientLight, sizeof(D3DXCOLOR));
281
282 shaderEffect1->SetMatrix("mView", &(matView));
283 shaderEffect1->SetMatrix("mProjection", &(matProjection));
284
285 static float index = 0.0f; index += 0.05f;
286
287 /**
288 ** RENDERING ALL OF THE OBJECTS
289 **/
290 vector<Torus>::iterator vecIterator;
291
292 for (vecIterator = torusVector.begin(); vecIterator != torusVector.end(); vecIterator++)
293 {
294 Torus t = *vecIterator;
295
296 D3DXMatrixRotationYawPitchRoll( &t.rotY, 0, 0, -index);
297
298 //calculate lighting normal based on current transforms
299 D3DXMATRIX worldInverseTranspose;
300 D3DXMatrixInverse(&worldInverseTranspose, 0, &(t.rotY * t.pos));
301 D3DXMatrixTranspose(&worldInverseTranspose, &worldInverseTranspose);
302
303 //send data to the shader
304 shaderEffect1->SetMatrix("mRotation", &(t.rotY));
305 shaderEffect1->SetMatrix("mTranslation", &(t.pos));
306 shaderEffect1->SetMatrix("gWorldInverseTranspose", &worldInverseTranspose);
307 shaderEffect1->SetValue("gDiffuseMtrl", &(t.color), sizeof(D3DXCOLOR));
308
309 UINT numPasses = 0;
310 shaderEffect1->Begin(&numPasses, 0);
311
312 for (int i=0; i<numPasses; ++i)
313 {
314 shaderEffect1->BeginPass(i);
315 meshTorus->DrawSubset(0);
316 shaderEffect1->EndPass();
317 }
318
319 shaderEffect1->End();
320 }
321 /**
322 ** RENDERING OBJECTS END
323 **/
324
325 textSprite->End();
326
327 d3ddev->EndScene();
328
329 d3ddev->Present(NULL, NULL, NULL, NULL);
330
331 return;
332 }
333
334
335 // this is the function that cleans up Direct3D and COM
336 void cleanD3D(void)
337 {
338 font->Release();
339 shaderEffect1->Release();
340 meshTorus->Release(); // close and release the teapot mesh
341 d3ddev->Release(); // close and release the 3D device
342 d3d->Release(); // close and release Direct3D
343
344 return;
345 }
346
347
348 // this is the function that puts the 3D models into video RAM
349 void init_graphics(void)
350 {
351 D3DXCreateSprite(d3ddev, &textSprite);
352
353 //create the font object
354 D3DXCreateFontIndirect(d3ddev, &desc, &font);
355
356 D3DXCreateTorus(d3ddev, innerRadius, outerRadius, sides, rings, &meshTorus, NULL);
357 ID3DXBuffer *errors = 0;
358
359 D3DXCreateEffectFromFile(d3ddev, "ProgrammableShader.fx", NULL, NULL, 0, NULL, &shaderEffect1, &errors);
360 if (errors )
361 MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);
362
363 shaderEffect1->SetTechnique("technique1");
364
365 return;
366 }
367
368 void init_Torus()
369 {
370 int iRandColor;
371
372 // Create all torus objects
373 for (int i = 0; i < numObjects; i++)
374 {
375 Torus torusObject;
376
377 // Apply movement function
378 D3DXMatrixTranslation(&torusObject.pos,
379 (((float)i * 2) * cos(6 * (float)i)), (((float)i * 2) * sin(6 * (float)i)), -(i * 4));
380
381 // Get random color
382 iRandColor = rand() % 6 + 1;
383 if (iRandColor == 1)
384 torusObject.color = WHITE;
385 else if (iRandColor == 2)
386 torusObject.color = BLUE;
387 else if (iRandColor == 3)
388 torusObject.color = GREEN;
389 else if (iRandColor == 4)
390 torusObject.color = RED;
391 else if (iRandColor == 5)
392 torusObject.color = CYAN;
393 else if (iRandColor == 6)
394 torusObject.color = PURPLE;
395
396 // Add object
397 torusVector.push_back(torusObject);
398 }
399 }