void RenderShadowMap() { D3DXMATRIX wMat; // world matrix for each object we want to render // Begin rendering to the shadow map texture gRenderTarget.begin(&gShadowMap); gRenderTarget.clear(D3DCOLOR_XRGB(255, 255, 255)); D3DXMATRIXA16 viewMat; D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); // Point where light is focused D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); // World's up vector // Create view matrix for light // **NOTE** It is very important to remember that we are treating the light as // a point light when rendering the objects, but for shadow casting, we are // assuming the light is always shining towards (0,0,0). Keep that in mind when thinking about // if the shadows look correct or not. D3DXMatrixLookAtLH(&viewMat, &gLightPos, &target, &up); // Set the view matrix of the light g3D->mShader->SetFloatArray("gLightViewMat", &viewMat._11, 16); // Set world matrix of box and render D3DXMatrixTranslation(&wMat, kBoxPos.x, kBoxPos.y, kBoxPos.z); g3D->setWorldMatrix(&wMat); g3D->render("ShadowMap", gBox); // Set world matrix of sphere and render D3DXMatrixTranslation(&wMat, kSherePos.x, kSherePos.y, kSherePos.z); g3D->setWorldMatrix(&wMat); g3D->render("ShadowMap", gSphere); gRenderTarget.end(); // Finish rendering to the shadow map }
void Combined() { // Begin rendering the Sobel Filter along the X-axis gRenderTarget.begin(&gBlurTexture2); gRenderTarget.clear(D3DCOLOR_XRGB(255, 255, 255)); // Select unfiltered render target to the left side of the screen gDiffTex.select(); g3D->renderSAQ(0, 0, 256, 256, "GuassianBlurVert"); gRenderTarget.end(); // Finish rendering to the shadow map // Begin rendering the Sobel Filter along the Y-axis gRenderTarget.begin(&gBlurTexture1); gRenderTarget.clear(D3DCOLOR_XRGB(255, 255, 255)); // Select unfiltered render target to the left side of the screen gBlurTexture2.select(); g3D->renderSAQ(0, 0, 256, 256, "GuassianBlurHorz"); gRenderTarget.end(); // Finish rendering to the shadow map ////// Sobel // Begin rendering the Sobel Filter along the X-axis gRenderTarget.begin(&gBlurTexture2); gRenderTarget.clear(D3DCOLOR_XRGB(255, 255, 255)); // Select unfiltered render target to the left side of the screen gBlurTexture1.select(); g3D->renderSAQ(0, 0, 256, 256, "SobelFilter"); gRenderTarget.end(); // Finish rendering to the shadow map }
void RenderSobelFilter() { // Begin rendering the Sobel Filter along the X-axis gRenderTarget.begin(&gBlurTexture2); gRenderTarget.clear(D3DCOLOR_XRGB(255, 255, 255)); // Select unfiltered render target to the left side of the screen gDiffTex.select(); g3D->renderSAQ(0, 0, 256, 256, "SobelFilter"); gRenderTarget.end(); // Finish rendering to the shadow map }
// WinProc LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { const float kMoveAmt = 0.05f; // Amount to move light by switch(message) { case WM_SYSKEYDOWN: // Toggle on ALT + ENTER if(wparam == VK_RETURN && (lparam & (1 << 29))) { // Shut down are render texture and render target gRenderTarget.deinit(); g3D->toggleFullScreen(); // Toggle! // Reinitialize the render texture and target gRenderTarget.init(256, 256, D3DFMT_A8R8G8B8, D3DFMT_D24S8); g3D->setViewMatrix(kEyePos, CPos(0.0f, 0.0f, 0.0f)); // Reset the view of our scene return 0; } break; // Allow other system keys to be handled by DefWindowProc() case WM_KEYDOWN: switch(wparam) { case VK_ESCAPE: SendMessage(hwnd, WM_CLOSE, 0, 0); break; case VK_F8: gToggle = !gToggle; break; } return 0; case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hwnd, message, wparam, lparam); }
// WinProc LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { const float kMoveAmt = 0.05f; // Amount to move light by switch(message) { case WM_SYSKEYDOWN: // Toggle on ALT + ENTER if(wparam == VK_RETURN && (lparam & (1 << 29))) { // Shut down are render texture and render target gShadowMap.deinit(); gRenderTarget.deinit(); g3D->toggleFullScreen(); // Toggle! // Reinitialize the render texture and target gShadowMap.createRenderTexture(512, 512, D3DFMT_R32F); gRenderTarget.init(512, 512, D3DFMT_R32F, D3DFMT_D24S8); g3D->setViewMatrix(kEyePos, CPos(0.0f, 0.0f, 0.0f)); // Reset the view of our scene return 0; } break; // Allow other system keys to be handled by DefWindowProc() case WM_KEYDOWN: switch(wparam) { case VK_LEFT: // Move the light along the -X axis gLightPos.x -= kMoveAmt; break; case VK_RIGHT: // Move the light along the +X axis gLightPos.x += kMoveAmt; break; case VK_UP: // Move the light along the +Z axis gLightPos.z += kMoveAmt; break; case VK_DOWN: // Move the light along the -Z axis gLightPos.z -= kMoveAmt; break; case VK_ESCAPE: SendMessage(hwnd, WM_CLOSE, 0, 0); break; } return 0; case WM_DESTROY: { PostQuitMessage(0); return 0; } } return DefWindowProc(hwnd, message, wparam, lparam); }
// Our Win32 main int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow) { HWND hwnd = NULL; // Handle to our window MSG msg = {0}; WNDCLASSEX wndclassex = {0}; // Init fields we care about wndclassex.cbSize = sizeof(WNDCLASSEX); // Always set to size of WNDCLASSEX wndclassex.style = CS_HREDRAW | CS_VREDRAW; wndclassex.lpfnWndProc = WinProc; wndclassex.hInstance = hinstance; wndclassex.lpszClassName = kClassName; wndclassex.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED); RegisterClassEx(&wndclassex); // Register the WNDCLASSEX RECT rect = { 0, 0, kWinWid, kWinHgt }; // Desired window client rect DWORD winStyleEx = WS_EX_CLIENTEDGE; DWORD winStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME; // Adjust window rect so it gives us our desired client rect when we // create the window AdjustWindowRectEx(&rect, winStyle, false, winStyleEx); // Create the window hwnd = CreateWindowEx(winStyleEx, kClassName, "www.GameTutorials.com -- Shadow Mapping (HLSL)", winStyle, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hinstance, NULL); // Get the client rect and make sure our client is the size we want GetClientRect(hwnd, &rect); assert(rect.right == kWinWid && rect.bottom == kWinHgt); // Init our global 3D object if(g3D->init(hwnd) == false) return EXIT_FAILURE; // There's been an error, lets get out of this joint if(!CreateSphere(0.05f, D3DCOLOR_XRGB(255,255,0), &gLight)) return false; // Couldn't create the sphere... Something very bad happened... if(!CreateSphere(0.75f, D3DCOLOR_XRGB(0,128,64), &gSphere)) return false; // Couldn't create the sphere... Something very bad happened... if(!CreateBox(1.0f, 2.0f, 1.0f, D3DCOLOR_XRGB(0, 128, 64), &gBox)) return false; // Couldn't create the box... This isn't good! if(!CreateBox(16.0f, 0.05f, 16.0f, D3DCOLOR_XRGB(225, 225, 255), &gGround)) return false; // Couldn't create the ground... Time to bail if(!gShadowMap.createRenderTexture(512, 512, D3DFMT_R32F)) return false; // Couldn't create a shadow map texture. Your video card // probably doesn't support the D3DFMT_R32F format. You will need a beefier card to // run this tutorial if(!gRenderTarget.init(512, 512, D3DFMT_R32F, D3DFMT_D24S8)) return false; // Couldn't create a shadow map texture. Your video card doesn't support render // targets or it probably doesn't support the D3DFMT_R32F format. You will need // a beefier card to run this tutorial // Set up our projection matrix once because it will not change g3D->setProjMatrix(DEG2RAD(60), 1.0f, 2048.0f); // We set up our view matrix once because it will never change g3D->setViewMatrix(kEyePos, CPos(0.0f, 0.0f, 0.0f)); D3DXMATRIXA16 projMat; // Create texture projection matrix D3DXMatrixPerspectiveFovLH(&projMat, DEG2RAD(60), 1.0f, 0.1f, 100.0f); // Set data in our shader that will never change g3D->mShader->SetFloatArray("gLightProjMat", &projMat._11, 16); g3D->mShader->SetFloatArray("gEyePos", &kEyePos.x, 3); // Set the camera's eye position g3D->mShader->SetFloatArray("gDiffuse", &kDiffuse.r, 3); // Lights diffuse color g3D->mShader->SetFloatArray("gSpecular", &kSpecular.r, 3); // Lights specular color g3D->mShader->SetFloatArray("gAmbient", &kAmbient.r, 3); // Lights ambient color // Show and update the window ShowWindow(hwnd, ishow); UpdateWindow(hwnd); while(1) // While the app is alive { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // If the OS has a message for us { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else if(LockFrameRate()) // Else, if it's time to draw { static int angle = 0; // Stores the amount rotated in degrees D3DXMATRIX tMat, rMat; // This will hold translation and rotation matrices D3DXMATRIX wMat; // This will hold the world matrix of objects we want rendered D3DXMATRIX shadowMat; // The matrix for projecting the shadow to a plane // The light is going to potentially move, so we need to // set it's position every frame g3D->mShader->SetFloatArray("gLightPos", &gLightPos.x, 3); // Render the shadow map RenderShadowMap(); // Render the ground, box and sphere with shadows RenderScene(); } else Sleep(1); // Otherwise, give the OS some time to process other programs } // end of while(1) gLight->Release(); // Free up the light gSphere->Release(); // Free up the sphere gBox->Release(); // Free up the box gGround->Release(); // Free up the ground g3D->deinit(); // Free up the D3D object UnregisterClass(kClassName,hinstance); // Free up WNDCLASSEX return EXIT_SUCCESS; // Application was a success }
// Our Win32 main int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprev, PSTR cmdline, int ishow) { HWND hwnd = NULL; // Handle to our window MSG msg = {0}; WNDCLASSEX wndclassex = {0}; // Init fields we care about wndclassex.cbSize = sizeof(WNDCLASSEX); // Always set to size of WNDCLASSEX wndclassex.style = CS_HREDRAW | CS_VREDRAW; wndclassex.lpfnWndProc = WinProc; wndclassex.hInstance = hinstance; wndclassex.lpszClassName = kClassName; wndclassex.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_SHARED); RegisterClassEx(&wndclassex); // Register the WNDCLASSEX RECT rect = { 0, 0, kWinWid, kWinHgt }; // Desired window client rect DWORD winStyleEx = WS_EX_CLIENTEDGE; DWORD winStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME; // Adjust window rect so it gives us our desired client rect when we // create the window AdjustWindowRectEx(&rect, winStyle, false, winStyleEx); // Create the window hwnd = CreateWindowEx(winStyleEx, kClassName, "www.GameTutorials.com -- Render Targets", winStyle, CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hinstance, NULL); // Get the client rect and make sure our client is the size we want GetClientRect(hwnd, &rect); assert(rect.right == kWinWid && rect.bottom == kWinHgt); // Init our global 3D object if(g3D->init(hwnd) == false) return EXIT_FAILURE; // There's been an error, lets get out of this joint if(!gBlurTexture1.createRenderTexture(256, 256, D3DFMT_A8R8G8B8)) return false; // Couldn't create a off screen texture to render to if(!gBlurTexture2.createRenderTexture(256, 256, D3DFMT_A8R8G8B8)) return false; // Couldn't create a off screen texture to render to if(!gDiffTex.load("texture.jpg")) return false; if(!gRenderTarget.init(256, 256, D3DFMT_A8R8G8B8, D3DFMT_D24S8)) return false; // Couldn't create a render texture... Does your video card support this? Make3x3GuassianDistribution(); // Set up our projection matrix once because it will not change g3D->setProjMatrix(DEG2RAD(60), 1.0f, 2048.0f); // We set up our view matrix once because it will never change g3D->setViewMatrix(kEyePos, CPos(0.0f, 0.0f, 0.0f)); g3D->mShader->SetFloatArray("gEyePos", &kEyePos.x, 3); // Set the camera's eye position g3D->mShader->SetFloatArray("gBlurWeights", gBlurWeights, 9); // Gaussian blur weights // Show and update the window ShowWindow(hwnd, ishow); UpdateWindow(hwnd); while(1) // While the app is alive { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // If the OS has a message for us { if(msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else if(LockFrameRate()) // Else, if it's time to draw { // Render the off screen texture (created directly above) to another // off screen texture using a Gaussian blur if(gToggle) Combined(); else RenderSobelFilter(); // Render the two textures to the screen RenderScene(); } else Sleep(1); // Otherwise, give the OS some time to process other programs } // end of while(1) g3D->deinit(); // Free up the D3D object UnregisterClass(kClassName,hinstance); // Free up WNDCLASSEX return EXIT_SUCCESS; // Application was a success }