/*---------------------------------------------------------------------------* Copyright (C) 2010-2012 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ #include "windows.h" #include #include #include #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") #pragma comment(lib, "gdi32.lib") #pragma comment(lib, "user32.lib") // GLOBALS /////////////////////////////////////////////////////////////////// HWND hWnd; unsigned width = 1280; unsigned height = 720; LPDIRECT3DSURFACE9 diffuseSurface = NULL; LPDIRECT3DSURFACE9 normalSurface = NULL; LPDIRECT3DSURFACE9 positionSurface = NULL; LPDIRECT3DTEXTURE9 diffuseTex = NULL; LPDIRECT3DTEXTURE9 normalTex = NULL; LPDIRECT3DTEXTURE9 positionTex = NULL; D3DXVECTOR3 cameraPos; D3DXMATRIX modelMtx; D3DXMATRIX viewProjMtx; LPDIRECT3DDEVICE9 pDevice = NULL; LPD3DXEFFECT pEffect = NULL; LPDIRECT3DSURFACE9 pBackBuffer = NULL; D3DPRESENT_PARAMETERS presentParameters; #define POSTEX_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1) struct PosTexVertex { float pos[4]; float tex[2]; }; PosTexVertex posTexQuad[] = { { 0.0f, 0.0f, 0.5f, 1.0f, 0.0f + 0.5f / float(width), 0.0f + 0.5f / float(height) }, { float(width), 0.0f, 0.5f, 1.0f, 1.0f + 0.5f / float(width), 0.0f + 0.5f / float(height) }, { 0.0f, float(height), 0.5f, 1.0f, 0.0f + 0.5f / float(width), 1.0f + 0.5f / float(height) }, { float(width), float(height), 0.5f, 1.0f, 1.0f + 0.5f / float(width), 1.0f + 0.5f / float(height) }, }; #define POSNORM_FVF (D3DFVF_XYZ | D3DFVF_NORMAL) struct PosNormVertex { float pos[3]; float norm[3]; }; const char* MODEL_FILES[3] = { "teapotPosition.dat", "teapotNormal.dat", "teapotIdx.dat", }; unsigned numVerts, numTris; LPDIRECT3DVERTEXBUFFER9 vertexBuffer; LPDIRECT3DINDEXBUFFER9 indexBuffer; bool quit = false; #define PI 3.14159f // FUNCTIONS ///////////////////////////////////////////////////////////////// void LoadModel() { std::ifstream posFile, normFile; posFile.open(MODEL_FILES[0], std::ios::binary); normFile.open(MODEL_FILES[1], std::ios::binary); posFile.seekg(0, std::ios::end); numVerts = (unsigned)posFile.tellg() / (3*sizeof(float)); posFile.seekg(0, std::ios::beg); pDevice->CreateVertexBuffer(numVerts * sizeof(PosNormVertex), D3DUSAGE_WRITEONLY, POSNORM_FVF, D3DPOOL_MANAGED, &vertexBuffer, NULL); PosNormVertex* copyTo; vertexBuffer->Lock(0, numVerts * sizeof(PosNormVertex), (void**)©To, 0); float x = 141.8f; for(unsigned i = 0; i < numVerts; ++i) { for(unsigned j = 0; j < 3; ++j) { char temp[4]; posFile.read((char*)&temp, sizeof(temp)); ((char*)©To[i].pos[j])[0] = temp[3]; ((char*)©To[i].pos[j])[1] = temp[2]; ((char*)©To[i].pos[j])[2] = temp[1]; ((char*)©To[i].pos[j])[3] = temp[0]; } for(unsigned j = 0; j < 3; ++j) { char temp[4]; normFile.read((char*)&temp, sizeof(temp)); ((char*)©To[i].norm[j])[0] = temp[3]; ((char*)©To[i].norm[j])[1] = temp[2]; ((char*)©To[i].norm[j])[2] = temp[1]; ((char*)©To[i].norm[j])[3] = temp[0]; } } vertexBuffer->Unlock(); posFile.close(); normFile.close(); std::ifstream idxFile; idxFile.open(MODEL_FILES[2], std::ios::binary); idxFile.seekg(0, std::ios::end); unsigned idxSize = (unsigned)idxFile.tellg(); idxFile.seekg(0, std::ios::beg); pDevice->CreateIndexBuffer(idxSize, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_MANAGED, &indexBuffer, NULL); unsigned* idxCopyTo; indexBuffer->Lock(0, numVerts * sizeof(PosNormVertex), (void**)&idxCopyTo, 0); for(unsigned i = 0; i < idxSize / 4; ++i) { char temp[4]; idxFile.read((char*)&temp, sizeof(temp)); ((char*)&idxCopyTo[i])[0] = temp[3]; ((char*)&idxCopyTo[i])[1] = temp[2]; ((char*)&idxCopyTo[i])[2] = temp[1]; ((char*)&idxCopyTo[i])[3] = temp[0]; } indexBuffer->Unlock(); numTris = idxSize / sizeof(unsigned) / 3; idxFile.close(); } bool InitGlobals() { LoadModel(); pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &diffuseTex, NULL); diffuseTex->GetSurfaceLevel(0, &diffuseSurface); pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &normalTex, NULL); normalTex->GetSurfaceLevel(0, &normalSurface); pDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16F, D3DPOOL_DEFAULT, &positionTex, NULL); positionTex->GetSurfaceLevel(0, &positionSurface); D3DXMATRIX matProjection; D3DXMatrixPerspectiveFovRH(&matProjection, 30.0f * PI / 180.0f, (float)width / (float)height, 50.0f, 2000.0f); cameraPos = D3DXVECTOR3(0.0f, 0.0f, 300.0f); D3DXMATRIX matView; D3DXMatrixLookAtRH(&matView, &cameraPos, &D3DXVECTOR3(0.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f)); D3DXMatrixMultiply(&viewProjMtx, &matView, &matProjection); return true; } void Animate() { static float rotateY = 0.0f; D3DXMATRIX matYAxisRotation, matScaling; D3DXMatrixScaling(&matScaling, 1.0f, 1.0f, 1.0f); D3DXMatrixRotationY(&matYAxisRotation, rotateY); D3DXMatrixMultiply(&modelMtx, &matYAxisRotation, &matScaling); rotateY += 0.015f; if(rotateY > PI*2.0f) { rotateY -= PI*2.0f; } pEffect->SetVector("u_cameraPosition",(D3DXVECTOR4*)&cameraPos); pEffect->SetMatrix("u_viewprojMtx",&viewProjMtx); } void SetupPass() { pDevice->SetRenderTarget(0, diffuseSurface); pDevice->SetRenderTarget(1, normalSurface); pDevice->SetRenderTarget(2, positionSurface); pDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 1.0f, 0); pEffect->SetTechnique("setup"); pEffect->SetMatrix("u_modelMtx", &modelMtx); pEffect->Begin(NULL, 0); D3DXVECTOR4 color(1.0f, 0.0f, 0.0f, 80.0f / 255.0f); // shininess / 255.0f pEffect->SetVector("u_color", &color); pEffect->BeginPass(0); pDevice->SetFVF(POSNORM_FVF); pDevice->SetIndices(indexBuffer); pDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(PosNormVertex)); pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, numVerts, 0, numTris); pEffect->EndPass(); pEffect->End(); pDevice->SetRenderTarget(0,pBackBuffer); pDevice->SetRenderTarget(1,NULL); pDevice->SetRenderTarget(2,NULL); pDevice->SetRenderTarget(3,NULL); } void LightingPass() { pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00888888, 1.0f, 0); pEffect->SetTechnique("lighting"); D3DXVECTOR4 lightPos(40.0f, 30.0f, 40.0f, 1.0f); pEffect->SetVector("u_lightPosition", &lightPos); D3DXVECTOR4 ambientColor(0.3f, 0.3f, 0.3f, 1.0f); pEffect->SetVector("u_ambientColor", &ambientColor); D3DXVECTOR4 lightColor(1.0f, 1.0f, 1.0f, 10.0f / 255.0f); // attenuation / 255.0f pEffect->SetVector("u_lightColor", &lightColor); pEffect->SetTexture("t_diffuse", diffuseTex); pEffect->SetTexture("t_normal", normalTex); pEffect->SetTexture("t_position", positionTex); pEffect->Begin(NULL, 0); pEffect->BeginPass(0); pDevice->SetFVF(POSTEX_FVF); pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, posTexQuad, sizeof(PosTexVertex)); pEffect->EndPass(); pEffect->End(); } LRESULT CALLBACK WndProc(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_SYSCOMMAND: switch (wParam) { case SC_CLOSE: quit = true; return 0; } break; case WM_PAINT: pDevice->Present( NULL, NULL, NULL, NULL ); break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } bool InitWindow() { HINSTANCE hInstance = GetModuleHandle(NULL); WNDCLASS wc; SecureZeroMemory(&wc, sizeof(wc)); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.lpszClassName = (LPCSTR)"GameWindow"; RegisterClass(&wc); RECT WindowRect; DWORD dwExStyle; DWORD dwStyle; WindowRect.left = GetSystemMetrics(SM_CXSCREEN)/2 - width/2; WindowRect.right = GetSystemMetrics(SM_CXSCREEN)/2 + width/2; WindowRect.top = GetSystemMetrics(SM_CYSCREEN)/2 - height/2; WindowRect.bottom = GetSystemMetrics(SM_CYSCREEN)/2 + height/2; dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | WS_EX_NOPARENTNOTIFY; dwStyle = WS_OVERLAPPEDWINDOW; AdjustWindowRectEx(&WindowRect, dwStyle, false, dwExStyle); hWnd = CreateWindowEx( dwExStyle, (LPCSTR)"GameWindow", (LPCSTR)"deferredTest", WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle, WindowRect.left, WindowRect.top, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, SW_SHOW); SetForegroundWindow(hWnd); SetFocus(hWnd); return true; } bool InitDX9() { LPDIRECT3D9 pObject = Direct3DCreate9(D3D_SDK_VERSION); D3DDISPLAYMODE d3ddm; pObject->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); SecureZeroMemory(&presentParameters, sizeof(presentParameters)); presentParameters.Windowed = TRUE; presentParameters.BackBufferWidth = width; presentParameters.BackBufferHeight = height; presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; presentParameters.BackBufferFormat = d3ddm.Format; presentParameters.EnableAutoDepthStencil = TRUE; presentParameters.AutoDepthStencilFormat = D3DFMT_D24S8; presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; pObject->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presentParameters, &pDevice); D3DCAPS9 deviceCaps; ZeroMemory(&deviceCaps, sizeof(deviceCaps)); pDevice->GetDeviceCaps(&deviceCaps); D3DXCreateEffectFromFile(pDevice, "deferredTest.fx", NULL, NULL, 0, NULL, &pEffect, NULL); pDevice->GetRenderTarget(0, &pBackBuffer); return true; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { if(!InitWindow()) return 1; if(!InitDX9()) return 2; if(!InitGlobals()) return 3; while(quit == false) { MSG msg; while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if(msg.message == WM_QUIT) { quit = true; break; } TranslateMessage(&msg); DispatchMessage(&msg); } if(SUCCEEDED(pDevice->BeginScene())) { Animate(); SetupPass(); LightingPass(); pDevice->EndScene(); } pDevice->Present(NULL, NULL, NULL, NULL); } return 0; }