1 /*---------------------------------------------------------------------------*
2 
3 Copyright (C) Nintendo.  All rights reserved.
4 
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law.  They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10 
11 *---------------------------------------------------------------------------*/
12 
13 #include "windows.h"
14 
15 #include <iostream>
16 #include <fstream>
17 
18 #include <d3dx9.h>
19 #pragma comment(lib, "d3d9.lib")
20 #pragma comment(lib, "d3dx9.lib")
21 
22 #pragma comment(lib, "gdi32.lib")
23 #pragma comment(lib, "user32.lib")
24 
25 // GLOBALS ///////////////////////////////////////////////////////////////////
26 
27 HWND hWnd;
28 
29 unsigned width = 1280;
30 unsigned height = 720;
31 
32 LPDIRECT3DSURFACE9 diffuseSurface = NULL;
33 LPDIRECT3DSURFACE9 normalSurface = NULL;
34 LPDIRECT3DSURFACE9 positionSurface = NULL;
35 
36 LPDIRECT3DTEXTURE9 diffuseTex = NULL;
37 LPDIRECT3DTEXTURE9 normalTex = NULL;
38 LPDIRECT3DTEXTURE9 positionTex = NULL;
39 
40 D3DXVECTOR3 cameraPos;
41 D3DXMATRIX modelMtx;
42 D3DXMATRIX viewProjMtx;
43 
44 LPDIRECT3DDEVICE9 pDevice = NULL;
45 LPD3DXEFFECT pEffect = NULL;
46 LPDIRECT3DSURFACE9 pBackBuffer = NULL;
47 
48 D3DPRESENT_PARAMETERS presentParameters;
49 
50 #define POSTEX_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
51 
52 struct PosTexVertex
53 {
54     float pos[4];
55     float tex[2];
56 };
57 
58 PosTexVertex posTexQuad[] =
59 {
60     {         0.0f,          0.0f, 0.5f, 1.0f, 0.0f + 0.5f / float(width), 0.0f + 0.5f / float(height) },
61     { float(width),          0.0f, 0.5f, 1.0f, 1.0f + 0.5f / float(width), 0.0f + 0.5f / float(height) },
62     {         0.0f, float(height), 0.5f, 1.0f, 0.0f + 0.5f / float(width), 1.0f + 0.5f / float(height) },
63     { float(width), float(height), 0.5f, 1.0f, 1.0f + 0.5f / float(width), 1.0f + 0.5f / float(height) },
64 };
65 
66 #define POSNORM_FVF (D3DFVF_XYZ | D3DFVF_NORMAL)
67 
68 struct PosNormVertex
69 {
70     float pos[3];
71     float norm[3];
72 };
73 
74 const char* MODEL_FILES[3] =
75 {
76     "teapotPosition.dat",
77     "teapotNormal.dat",
78     "teapotIdx.dat",
79 };
80 
81 unsigned numVerts, numTris;
82 LPDIRECT3DVERTEXBUFFER9 vertexBuffer;
83 LPDIRECT3DINDEXBUFFER9 indexBuffer;
84 
85 bool quit = false;
86 
87 #define PI 3.14159f
88 
89 // FUNCTIONS /////////////////////////////////////////////////////////////////
90 
LoadModel()91 void LoadModel()
92 {
93     std::ifstream posFile, normFile;
94     posFile.open(MODEL_FILES[0], std::ios::binary);
95     normFile.open(MODEL_FILES[1], std::ios::binary);
96 
97     posFile.seekg(0, std::ios::end);
98     numVerts = (unsigned)posFile.tellg() / (3*sizeof(float));
99     posFile.seekg(0, std::ios::beg);
100 
101     pDevice->CreateVertexBuffer(numVerts * sizeof(PosNormVertex), D3DUSAGE_WRITEONLY, POSNORM_FVF, D3DPOOL_MANAGED, &vertexBuffer, NULL);
102 
103     PosNormVertex* copyTo;
104     vertexBuffer->Lock(0, numVerts * sizeof(PosNormVertex), (void**)&copyTo, 0);
105 
106     float x = 141.8f;
107 
108     for(unsigned i = 0; i < numVerts; ++i)
109     {
110         for(unsigned j = 0; j < 3; ++j)
111         {
112             char temp[4];
113             posFile.read((char*)&temp, sizeof(temp));
114             ((char*)&copyTo[i].pos[j])[0] = temp[3];
115             ((char*)&copyTo[i].pos[j])[1] = temp[2];
116             ((char*)&copyTo[i].pos[j])[2] = temp[1];
117             ((char*)&copyTo[i].pos[j])[3] = temp[0];
118         }
119         for(unsigned j = 0; j < 3; ++j)
120         {
121             char temp[4];
122             normFile.read((char*)&temp, sizeof(temp));
123             ((char*)&copyTo[i].norm[j])[0] = temp[3];
124             ((char*)&copyTo[i].norm[j])[1] = temp[2];
125             ((char*)&copyTo[i].norm[j])[2] = temp[1];
126             ((char*)&copyTo[i].norm[j])[3] = temp[0];
127         }
128     }
129 
130     vertexBuffer->Unlock();
131 
132     posFile.close();
133     normFile.close();
134 
135     std::ifstream idxFile;
136     idxFile.open(MODEL_FILES[2], std::ios::binary);
137 
138     idxFile.seekg(0, std::ios::end);
139     unsigned idxSize = (unsigned)idxFile.tellg();
140     idxFile.seekg(0, std::ios::beg);
141 
142     pDevice->CreateIndexBuffer(idxSize, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_MANAGED, &indexBuffer, NULL);
143 
144     unsigned* idxCopyTo;
145     indexBuffer->Lock(0, numVerts * sizeof(PosNormVertex), (void**)&idxCopyTo, 0);
146 
147     for(unsigned i = 0; i < idxSize / 4; ++i)
148     {
149         char temp[4];
150         idxFile.read((char*)&temp, sizeof(temp));
151         ((char*)&idxCopyTo[i])[0] = temp[3];
152         ((char*)&idxCopyTo[i])[1] = temp[2];
153         ((char*)&idxCopyTo[i])[2] = temp[1];
154         ((char*)&idxCopyTo[i])[3] = temp[0];
155     }
156 
157     indexBuffer->Unlock();
158 
159     numTris = idxSize / sizeof(unsigned) / 3;
160 
161     idxFile.close();
162 }
163 
InitGlobals()164 bool InitGlobals()
165 {
166     LoadModel();
167 
168     pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &diffuseTex, NULL);
169     diffuseTex->GetSurfaceLevel(0, &diffuseSurface);
170 
171     pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &normalTex, NULL);
172     normalTex->GetSurfaceLevel(0, &normalSurface);
173 
174     pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &positionTex, NULL);
175     positionTex->GetSurfaceLevel(0, &positionSurface);
176 
177     D3DXMATRIX matProjection;
178     D3DXMatrixPerspectiveFovRH(&matProjection,
179                                30.0f * PI / 180.0f,
180                                (float)width / (float)height,
181                                50.0f,
182                                2000.0f);
183 
184     cameraPos = D3DXVECTOR3(0.0f, 0.0f, 300.0f);
185 
186     D3DXMATRIX matView;
187     D3DXMatrixLookAtRH(&matView,
188                        &cameraPos,
189                        &D3DXVECTOR3(0.0f, 0.0f, 0.0f),
190                        &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
191 
192     D3DXMatrixMultiply(&viewProjMtx, &matView, &matProjection);
193 
194     return true;
195 }
196 
Animate()197 void Animate()
198 {
199     static float rotateY = 0.0f;
200 
201     D3DXMATRIX matYAxisRotation, matScaling;
202     D3DXMatrixScaling(&matScaling, 1.0f, 1.0f, 1.0f);
203     D3DXMatrixRotationY(&matYAxisRotation, rotateY);
204     D3DXMatrixMultiply(&modelMtx, &matYAxisRotation, &matScaling);
205 
206     rotateY += 0.015f;
207     if(rotateY > PI*2.0f)
208     {
209         rotateY -= PI*2.0f;
210     }
211 
212     pEffect->SetVector("u_cameraPosition",(D3DXVECTOR4*)&cameraPos);
213     pEffect->SetMatrix("u_viewprojMtx",&viewProjMtx);
214 }
215 
SetupPass()216 void SetupPass()
217 {
218     pDevice->SetRenderTarget(0, diffuseSurface);
219     pDevice->SetRenderTarget(1, normalSurface);
220     pDevice->SetRenderTarget(2, positionSurface);
221 
222     pDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0);
223 
224     pEffect->SetTechnique("setup");
225     pEffect->SetMatrix("u_modelMtx", &modelMtx);
226 
227     pEffect->Begin(NULL, 0);
228 
229     D3DXVECTOR4 color(1.0f, 0.0f, 0.0f, 80.0f / 255.0f); // shininess / 255.0f
230     pEffect->SetVector("u_color", &color);
231 
232     pEffect->BeginPass(0);
233 
234     pDevice->SetFVF(POSNORM_FVF);
235     pDevice->SetIndices(indexBuffer);
236     pDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(PosNormVertex));
237     pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVerts, 0, numTris);
238 
239     pEffect->EndPass();
240 
241     pEffect->End();
242 
243     pDevice->SetRenderTarget(0,pBackBuffer);
244     pDevice->SetRenderTarget(1,NULL);
245     pDevice->SetRenderTarget(2,NULL);
246     pDevice->SetRenderTarget(3,NULL);
247 }
248 
LightingPass()249 void LightingPass()
250 {
251     pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00888888, 1.0f, 0);
252 
253     pEffect->SetTechnique("lighting");
254 
255     D3DXVECTOR4 lightPos(40.0f, 30.0f, 40.0f, 1.0f);
256     pEffect->SetVector("u_lightPosition", &lightPos);
257     D3DXVECTOR4 ambientColor(0.3f, 0.3f, 0.3f, 1.0f);
258     pEffect->SetVector("u_ambientColor", &ambientColor);
259     D3DXVECTOR4 lightColor(1.0f, 1.0f, 1.0f, 10.0f / 255.0f); // attenuation / 255.0f
260     pEffect->SetVector("u_lightColor", &lightColor);
261 
262     pEffect->SetTexture("t_diffuse", diffuseTex);
263     pEffect->SetTexture("t_normal", normalTex);
264     pEffect->SetTexture("t_position", positionTex);
265 
266     pEffect->Begin(NULL, 0);
267 
268     pEffect->BeginPass(0);
269     pDevice->SetFVF(POSTEX_FVF);
270     pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, posTexQuad, sizeof(PosTexVertex));
271     pEffect->EndPass();
272 
273     pEffect->End();
274 }
275 
WndProc(HWND hWnd,unsigned int uMsg,WPARAM wParam,LPARAM lParam)276 LRESULT CALLBACK WndProc(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam)
277 {
278     switch(uMsg)
279     {
280     case WM_SYSCOMMAND:
281         switch (wParam)
282         {
283         case SC_CLOSE:
284             quit = true;
285             return 0;
286         }
287         break;
288 
289     case WM_PAINT:
290         pDevice->Present( NULL, NULL, NULL, NULL );
291         break;
292     }
293 
294     return DefWindowProc(hWnd, uMsg, wParam, lParam);
295 }
296 
InitWindow()297 bool InitWindow()
298 {
299     HINSTANCE hInstance = GetModuleHandle(NULL);
300 
301     WNDCLASS wc;
302     SecureZeroMemory(&wc, sizeof(wc));
303     wc.style = CS_HREDRAW | CS_VREDRAW;
304     wc.lpfnWndProc = WndProc;
305     wc.hInstance = hInstance;
306     wc.lpszClassName = (LPCSTR)"GameWindow";
307 
308     RegisterClass(&wc);
309 
310     RECT WindowRect;
311     DWORD dwExStyle;
312     DWORD dwStyle;
313 
314     WindowRect.left = GetSystemMetrics(SM_CXSCREEN)/2 - width/2;
315     WindowRect.right = GetSystemMetrics(SM_CXSCREEN)/2 + width/2;
316     WindowRect.top = GetSystemMetrics(SM_CYSCREEN)/2 - height/2;
317     WindowRect.bottom = GetSystemMetrics(SM_CYSCREEN)/2 + height/2;
318 
319     dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | WS_EX_NOPARENTNOTIFY;
320     dwStyle = WS_OVERLAPPEDWINDOW;
321 
322     AdjustWindowRectEx(&WindowRect, dwStyle, false, dwExStyle);
323 
324     hWnd = CreateWindowEx(  dwExStyle, (LPCSTR)"GameWindow", (LPCSTR)"deferredTest",
325         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
326         WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top,
327         NULL, NULL, hInstance, NULL);
328 
329     ShowWindow(hWnd, SW_SHOW);
330     SetForegroundWindow(hWnd);
331     SetFocus(hWnd);
332 
333     return true;
334 }
335 
InitDX9()336 bool InitDX9()
337 {
338     LPDIRECT3D9 pObject = Direct3DCreate9(D3D_SDK_VERSION);
339 
340     D3DDISPLAYMODE d3ddm;
341     pObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
342 
343     SecureZeroMemory(&presentParameters, sizeof(presentParameters));
344     presentParameters.Windowed = TRUE;
345     presentParameters.BackBufferWidth = width;
346     presentParameters.BackBufferHeight = height;
347     presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
348     presentParameters.BackBufferFormat = d3ddm.Format;
349     presentParameters.EnableAutoDepthStencil = TRUE;
350     presentParameters.AutoDepthStencilFormat = D3DFMT_D24S8;
351     presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
352 
353     pObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presentParameters, &pDevice);
354 
355     D3DCAPS9 deviceCaps;
356     ZeroMemory(&deviceCaps, sizeof(deviceCaps));
357 
358     pDevice->GetDeviceCaps(&deviceCaps);
359 
360     D3DXCreateEffectFromFile(pDevice, "deferredTest.fx", NULL, NULL, 0, NULL, &pEffect, NULL);
361 
362     pDevice->GetRenderTarget(0, &pBackBuffer);
363 
364     return true;
365 }
366 
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)367 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
368 {
369     if(!InitWindow()) return 1;
370     if(!InitDX9()) return 2;
371     if(!InitGlobals()) return 3;
372 
373     while(quit == false)
374     {
375         MSG msg;
376         while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
377         {
378             if(msg.message == WM_QUIT)
379             {
380                 quit = true;
381                 break;
382             }
383 
384             TranslateMessage(&msg);
385             DispatchMessage(&msg);
386         }
387 
388         if(SUCCEEDED(pDevice->BeginScene()))
389         {
390             Animate();
391             SetupPass();
392             LightingPass();
393 
394             pDevice->EndScene();
395         }
396         pDevice->Present(NULL, NULL, NULL, NULL);
397     }
398 
399     return 0;
400 }
401