SHADERBOL KIVENNI A TEXTURA HASZNALATOT #include "dxstdafx.h" #include "resource.h" // Define X files path #define BUNNY L"Media\\Objects\\bunny.x" #define COLUMN L"Media\\Objects\\column.x" #define ROOM L"Media\\Objects\\room.x" #define SKULL L"Media\\Objects\\skull.x" #define SPHERE L"Media\\Objects\\sphere.x" #define TEAPOT L"Media\\Objects\\teapot.x" #define TIGER L"Media\\Objects\\tiger.x" //#define D3D_DEBUG_INFO //#define DEBUG_VS // Uncomment this line to debug vertex shaders //#define DEBUG_PS // Uncomment this line to debug pixel shaders // Define texture sizes #define CUBEMAP_SIZE 512 // size of CubeMaps #define ATLASMAP_SIZE 512 // size of Atlases (Room, Columns) #define SHADOWMAP_SIZE 512 // size of ShadowMap #define PHOTONMAP_MAX_SIZE 256 // The max size of the PhotonMap #define SNIPPET_MAX_SIZE 5 // The max size of the snippet #define STEP 0.1f // The size of a movement between two step #define CENTEROBJECTRADIUS 2.0f // radius of the center object #define LIGHTRADIUS 0.3f // radius of the light object //-------------------------------------------------------------------------------------- // UI control IDs //-------------------------------------------------------------------------------------- #define IDC_TOGGLEFULLSCREEN 1 #define IDC_TOGGLEREF 2 #define IDC_CHANGEDEVICE 3 #define WINDOW_SIZE_X 640 // Size of the screen #define WINDOW_SIZE_Y 640 // Size of the screen // HUD IDs #define IDC_SHADOW_CHECK_BOX 10 #define IDC_CAUSTICS_CHECK_BOX 11 #define IDC_CENTEROBJ_CHECK_BOX 12 #define IDC_SNIPPET_SIZE_IS_CONSTANT_CHECK_BOX 13 #define IDC_SHOW_PHOTON_MAP_CHECK_BOX 14 #define IDC_CLASSIC_METHOD 20 #define IDC_DISTANCE_IMPOSTOR_METHOD 21 #define IDC_NUMBER_OF_ITERATION_SLIDER 30 #define IDC_FRESNEL_FACTOR_SLIDER 31 #define IDC_REFRACTION_INDEX_SLIDER 32 #define IDC_SHADOW_INTENSITY_SLIDER 33 #define IDC_CAUSTICS_INTENSITY_SLIDER 34 #define IDC_PHOTON_MAP_SIZE_SLIDER 35 #define IDC_SNIPPET_SIZE_SLIDER 36 #define IDC_RESET_PARAMETERS_BUTTON 40 // These constants will be used as arguments for the RenderScene(..., int, ..) function // They are used to switch between the different shaders enum { RENDER_ROOM_COLOR_DISTANCE, RENDER_ROOM_UV, RENDER_ROOM_AND_COLUMNS_SCREEN, RENDER_PHOTON_UV_MAP, RENDER_PHOTON_HIT, RENDER_REFRACT_OBJECT_SCREEN, RENDER_LIGHT_SCREEN, RENDER_UMBRA, RENDER_SHADOW, RENDER_FULLSCREENQUAD, RENDER_PHOTON_MAP_SCREEN }; // The next two float array pairs define the Snippet's light intensity and its size. // These values (light intensity and size) depend on the PhotonMapSize. // The bigger PhotonMapSize defines bigger texture and that defines more photon. // The more photons need smaller intensity and size. // PhotonMapSize = 1 2 4 8 16 32 64 128 256 // Tries to fill the same area with constant intensity. float g_fIntensityOfSnippet[9] = { 0.05f, 0.06f, 0.08f, 0.11f, 0.185f, 0.27f, 0.53f, 1.00f, 1.65f }; float g_fSizeOfSnippet[9] = { 0.05f, 0.10f, 0.14f, 0.17f, 0.25f, 0.32f, 0.64f, 1.28f, 2.56f }; // Tries to fill the same area with texture's size independent Snippet's size. float g_fIntensityOfSnippetWithIndependentSnippetSize[9] = { 0.05f, 0.05f, 0.05f, 0.065f, 0.13f, 0.27f, 0.53f, 1.00f, 1.65f }; float g_fSizeOfSnippetWithIndependentSnippetSize[9] = { 0.01f, 0.02f, 0.04f, 0.08f, 0.16f, 0.32f, 0.64f, 1.28f, 2.56f }; //-------------------------------------------------------------------------------------- // Structs //-------------------------------------------------------------------------------------- // Vertex structure for a photon hit (called snippet) D3DVERTEXELEMENT9 g_aSnippetVertex[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, { 0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, { 0, 28, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, D3DDECL_END() }; // Vertex structure for the fullscreene quad D3DVERTEXELEMENT9 g_aFullScreneQuadVertex[] = { { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, D3DDECL_END() }; // Define a snippet struct SnippetVertexStruct { float x, y, z; float r, g, b, a; float u, v; }; struct FullScreenQuadVertexStruct { FLOAT x, y, z, rhw; // The transformed position for the vertex. }; #define D3DFVF_FULLSCREENQUADVERTEX (D3DFVF_XYZRHW) FullScreenQuadVertexStruct fullscreen[] = { { -1.0f, -1.0f, 0.5f, 1.0f, }, // x, y, z, rhw { 1.0f, -1.0f, 0.5f, 1.0f, }, { 1.0f, 1.0f, 0.5f, 1.0f, }, { -1.0f, -1.0f, 0.5f, 1.0f, }, { 1.0f, 1.0f, 0.5f, 1.0f, }, { -1.0f, 1.0f, 0.5f, 1.0f, }, }; //-------------------------------------------------------------------------------------- // Global variables //-------------------------------------------------------------------------------------- IDirect3DDevice9* g_pd3dDevice = NULL; // RenderDevice ID3DXFont* g_pFont = NULL; // Font for drawing text ID3DXSprite* g_pTextSprite = NULL; // Sprite for batching draw text calls ID3DXEffect* g_pEffect = NULL; // D3DX effect interface CModelViewerCamera g_Camera; // A model viewing camera CDXUTDialog g_HUD; // Dialog for sample specific controls // Textures LPDIRECT3DTEXTURE9 g_pPhotonUVTexture = NULL; // Texture where the Photon map is rendered LPDIRECT3DTEXTURE9 g_pPowerOfSnippetTexelTexture = NULL; // Texture to contain the power of the snippet Texels LPDIRECT3DTEXTURE9 g_pRoomModifyTexture = NULL; // Room's Texture, this has viewable black edges LPDIRECT3DTEXTURE9 g_pRoomLastTexture = NULL; // Room's Texture, this contains the original brdf, // the Caustics Effect and the shadow LPDIRECT3DTEXTURE9 g_pColumnModifyTexture[4]; // Columns Texture LPDIRECT3DTEXTURE9 g_pColumnLastTexture[5]; // Columns Texture, the last one contains the original brdf LPDIRECT3DTEXTURE9 g_pRoomTexture = NULL; // Room's original Texture (brdf) LPDIRECT3DTEXTURE9 g_pShadowMapTexture = NULL; // Shadow map's texture. This is used for shadow generation. // Surfaces for the textures LPDIRECT3DSURFACE9 g_pColumnsModifySurface[4]; // Columns Atlas LPDIRECT3DSURFACE9 g_pColumnsLastSurface[5]; // Columns Atlas LPDIRECT3DSURFACE9 g_pRoomLastSurface = NULL; // Room's Atlas LPDIRECT3DSURFACE9 g_pRoomModifySurface = NULL; // Room's Atlas LPDIRECT3DSURFACE9 g_pRoomSurface = NULL; // Room's Atlas LPDIRECT3DSURFACE9 g_pPhotonMapDepthStencilSurface = NULL; // Used to render Photon map LPDIRECT3DSURFACE9 g_pPhotonUVMapSurface = NULL; // Photon map's UV surface LPDIRECT3DSURFACE9 g_pShadowMapSurface = NULL; // Shadow map's surface LPDIRECT3DSURFACE9 g_pShadowMapDepthStencilSSurface = NULL; // Shadow DS's Z surface LPDIRECT3DSURFACE9 g_pRenderTargetSurfaceOld = NULL; // Store the original Screen's surface LPDIRECT3DSURFACE9 g_pDepthStencilSurfaceOld = NULL; // Store the original Screen's DSS // Cube map textures IDirect3DCubeTexture9* g_pRoomCubeMapColorDistTexture = NULL; // CubeMap for store: Color + Distance IDirect3DCubeTexture9* g_pRoomCubeMapUVTexture = NULL; // CubeMap for store: UV + ObjectID IDirect3DSurface9* g_pRoomCubeMapDepthStencilSurface = NULL; // Depth-stencil buffer for rendering to cube texture IDirect3DSurface9* g_pDepthStencilSurface = NULL; // Depth-stencil buffer for Room Texture IDirect3DVertexDeclaration9* g_pSnippetVertexDeclaration = NULL; // Vertex declaration for the snippet IDirect3DVertexDeclaration9* g_pFullScreenQuadVertexDeclaration = NULL; // Vertex declaration for the fullscreen quad LPDIRECT3DVERTEXBUFFER9 g_pFullScreenQuadVertexBuffer = NULL; // Contains vertex data for the fullscreen quad LPDIRECT3DVERTEXBUFFER9 g_bSnippetVertexBuffer = NULL; // Contains vertex data for the snippets // Meshes ID3DXMesh* g_pCenterObjectMesh = NULL; // Mesh for the center object ID3DXMesh* g_pRoomMesh = NULL; // Mesh representing room (wall, floor, ceiling) ID3DXMesh* g_pColumnMesh = NULL; // Mesh representing one Column ID3DXMesh* g_pLightMesh = NULL; // Mesh for the light object // Flags bool g_bShowHelp = false; // If true, it renders the UI control text bool g_bInitialization = true; // Initialization is in progress bool g_bRunGenerateCaustics = false; // Rerender Caustics Effect bool g_bShadowON = true; // Calculate shadow yes/no. bool g_bCausticsON = true; // Calculate caustics yes/no. bool g_bShowVariables = true; // Show the values of the algorithm's variables bool g_bShowVariablesUserSet = true; // The user sets to show the variables. bool g_bRenderCenterObjectWithBrdfON = true; // Render Center Objectum with normal texture or diffuse color. bool g_bShowHUD = true; // Show HUD bool g_bSaveTexture = false; // Just for debug. bool g_bSnippetSizeIsConstant = false; // The fSnippetSize is independent of the size of PhotonMap. // Its size is constant in world space. bool g_bShowPhotonMap = true; // Show PhotonMap on screen // Matrices D3DXMATRIXA16 g_mWorldCenterObject; // World matrix of the Center Object (scaling & offset) D3DXMATRIXA16 g_mWorldViewLight; // Light's worldview matrix D3DXMATRIXA16 g_mProjLight; // Light's projection matrix D3DXMATRIXA16 g_mTexScaleBiasMat; // Special texture matrix for ShadowMapping D3DXMATRIXA16 g_mLightViewTexBias; // Light view matrix multiplied by g_mTexScaleBiasMat // Floats float g_fFresnelFactor = 0.05f; // The Fresnel factor float g_fRefractionIndex = 0.9f; // The Refraction index float g_fShadowIntensity = 0.25f; // The intensity of the shadow float g_fCausticsIntensity = 0.05f; // The intensity of a caustics snippet float g_fCenterObjectSize = 1.0; // The scale of the CenterObject float g_fSnippetSize = 3.0f; // The size of a snippet; float g_dDepthBias = 0.0002f; // Depth bias value float g_dBiasSlope = 2.0f; // Bias slope // Vectors D3DXVECTOR3 g_vLightPos; // Define the position of light D3DXVECTOR3 g_vLightPosLast; // Light position at the last Caustic Effect generation D3DXVECTOR3 g_vCenterObjectPosInitial; // Define the offset of the center object in the X file D3DXVECTOR3 g_vCenterObjectPos; // Define the offset of the center object D3DXVECTOR3 g_vCenterObjectPosLast; // CenterObj position at the last Caustic Effect generation int g_iNumberOfIteration = 10; // The number of the iteration of the algorithm. int g_iObjectID = -1; // The identifier of the object in the scene. // Every object has its own ID. int g_iAlgorithmMethod = 1; // Here you can switch between the classical and our distance impstor method. int g_iPhotonMapSize = 64; // Size of the PhotonMap //-------------------------------------------------------------------------------------- // Forward declarations //-------------------------------------------------------------------------------------- bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed ); void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps ); // This function creates the vertex buffer for the snippets, // controls the compiler properties, // loads the effect file and the meshes and // sets up the matrices. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc ); // This function contains the texture generation. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc ); void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime ); // This is the most important function. It is called at every frame. Steps: // - some initialization // At the first call we make the initialization. This runs just once, when the program starts. // - update caustics if necessary // Then it decides whether the caustics effect should be rerendered or not. // Re-rendering the caustic effect is requested if there were some major changes (movements) in the scene. // - render to screen // The last task is to render the objects of the scene to the screen. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime ); LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing ); // This function handles keyboard events (user inputs). void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown ); // The next two functions clear the variables from the memory. void CALLBACK OnLostDevice(); void CALLBACK OnDestroyDevice(); // This function displays the values of the algorithm's variables and the help text. void RenderText(); // It loads a mesh from the specified X file and - after determining its size and bounding box - // centers it on the screen. HRESULT LoadMesh( WCHAR* strFileName, ID3DXMesh** ppMesh, bool bComputeBoundingBox ); // This function creates the cube maps. // The first cube map stores color and distance values, created from the CenterObject's position. (g_pRoomCubeMapColorDistTexture) // The second one is created from the same position. (g_pRoomCubeMapUVTexture) // It stores at every pixel the viewable object's ID and UV. void RenderScenePreProcessing(); // This function generates the caustics effect. // At first it creates a photon map created from the light's position. // This map stores the viewable ObjectID and UV at every pixel. // This information is gathered from the second (g_pRoomCubeMapUVTexture) CubeMap. // The second step is to create the shadow map (g_pShadowMapTexture). This map contains depth values. // This map is generated from the light's position. // The last step is to blend caustics snippets and generate shadow into the room's and the columns's atlases at the right places. void GenerateCaustics(); // This function contains the GPU calls. // It calculates and sets up the values of the variables which are needed for the actual technique. void RenderScene( D3DXMATRIXA16 *mWorld, D3DXMATRIXA16 *mProj, int method ); // This function binds the texture to the GPU. void RenderSceneInitialization(); // Functions to crate different type of textures. IDirect3DTexture9* CreateTexture( int size, D3DFORMAT Format ); IDirect3DCubeTexture9* CreateCubeTexture( int size, D3DFORMAT Format ); IDirect3DSurface9* CreateDepthStencilSurface( int size ); // This function creates vertex buffer. void CreateVertexBuffer(); void InitializeHUD(); void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl ); //-------------------------------------------------------------------------------------- // Entry point to the program. Initializes everything and goes into a message processing // loop. Idle time is used to render the scene. //-------------------------------------------------------------------------------------- INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) { // Set the callback functions. These functions allow the sample framework to notify // the application about device changes, user input, and windows messages. The // callbacks are optional so you need only set callbacks for events you're interested // in. However, if you don't handle the device reset/lost callbacks then the sample // framework won't be able to reset your device since the application must first // release all device resources before resetting. Likewise, if you don't handle the // device created/destroyed callbacks then the sample framework won't be able to // recreate your device resources. DXUTSetCallbackDeviceCreated( OnCreateDevice ); DXUTSetCallbackDeviceReset( OnResetDevice ); DXUTSetCallbackDeviceLost( OnLostDevice ); DXUTSetCallbackDeviceDestroyed( OnDestroyDevice ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( KeyboardProc ); DXUTSetCallbackFrameRender( OnFrameRender ); DXUTSetCallbackFrameMove( OnFrameMove ); // Show the cursor and clip it when in full screen DXUTSetCursorSettings( true, true ); // Initialize the sample framework and create the desired Win32 window and Direct3D // device for the application. Calling each of these functions is optional, but they // allow you to set several options which control the behavior of the framework. DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes DXUTCreateWindow( L"RayTraceEffects" ); DXUTCreateDevice( D3DADAPTER_DEFAULT, true, WINDOW_SIZE_X, WINDOW_SIZE_Y, IsDeviceAcceptable, ModifyDeviceSettings ); // Pass control to the sample framework for handling the message pump and // dispatching render calls. The sample framework will call your FrameMove // and FrameRender callback when there is idle time between handling window messages. DXUTMainLoop(); // Perform any application-level cleanup here. Direct3D device resources are released within the // appropriate callback functions and therefore don't require any cleanup code here. return DXUTGetExitCode(); } //-------------------------------------------------------------------------------------- // Initialize the app //-------------------------------------------------------------------------------------- void InitializeHUD() { // Initialize dialog int posX = 350; int posY = 35; int sliderWidth = 120; int sliderHeight = 14; g_HUD.SetCallback( OnGUIEvent ); g_HUD.AddSlider( IDC_NUMBER_OF_ITERATION_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, 0, 20, g_iNumberOfIteration ); g_HUD.AddSlider( IDC_FRESNEL_FACTOR_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, 0, 100, (int)( g_fFresnelFactor * 100.0f ) ); g_HUD.AddSlider( IDC_REFRACTION_INDEX_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, 0, 100, (int)( g_fRefractionIndex * 100.0f + 1 ) ); g_HUD.AddSlider( IDC_SHADOW_INTENSITY_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, 0, 100, (int)( g_fShadowIntensity * 100.0f ) ); g_HUD.AddSlider( IDC_CAUSTICS_INTENSITY_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, -4000, 500, (int)( log( g_fCausticsIntensity ) / log ( 1.2f ) * 100.0f ) ); g_HUD.AddSlider( IDC_PHOTON_MAP_SIZE_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, 0, (int)( log( (float)PHOTONMAP_MAX_SIZE ) / log( 2.0f ) ), (int)( log( (float)g_iPhotonMapSize ) / log( 2.0f ) ) ); g_HUD.AddSlider( IDC_SNIPPET_SIZE_SLIDER, posX, posY += 16, sliderWidth, sliderHeight, 0, SNIPPET_MAX_SIZE * 100, (int)( g_fSnippetSize * 100.0f ) ); // -------------------------------------------------------------------------------------------- posX = 0; posY = 35; g_HUD.AddCheckBox( IDC_SHADOW_CHECK_BOX, L"Shadow ON/OFF", posX, posY += 20, 125, 16, g_bShadowON, 'S' ); g_HUD.AddCheckBox( IDC_CAUSTICS_CHECK_BOX, L"Caustics ON/OFF", posX, posY += 20, 125, 16, g_bCausticsON, 'C' ); g_HUD.AddCheckBox( IDC_CENTEROBJ_CHECK_BOX, L"CenterObj ON/OFF", posX, posY += 20, 125, 16, g_bRenderCenterObjectWithBrdfON, 'X' ); g_HUD.AddCheckBox( IDC_SNIPPET_SIZE_IS_CONSTANT_CHECK_BOX, L"Indep. Snippet size?", posX, posY += 20, 125, 16, g_bSnippetSizeIsConstant, 'V' ); g_HUD.AddCheckBox( IDC_SHOW_PHOTON_MAP_CHECK_BOX, L"Show Ph.Map ON/OFF", posX, posY += 20, 125, 16, g_bShowPhotonMap, 'M' ); g_HUD.AddRadioButton( IDC_CLASSIC_METHOD, 1, L"Classic method", posX, posY += 30, 125, 16, false ); g_HUD.AddRadioButton( IDC_DISTANCE_IMPOSTOR_METHOD, 1, L"Dist. imp. method", posX, posY += 20, 125, 16, true ); g_HUD.AddButton( IDC_RESET_PARAMETERS_BUTTON, L"Reset parameters", posX, posY += 30, 125, 16, 'Y' ); } //-------------------------------------------------------------------------------------- // Called during device initialization, this code checks the device for some // minimum set of capabilities, and rejects those that don't pass by returning false. //-------------------------------------------------------------------------------------- bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed ) { // Skip backbuffer formats that don't support alpha blending IDirect3D9* pD3D = DXUTGetD3DObject(); if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat ) ) ) return false; // Must support cube textures if( !( pCaps->TextureCaps & D3DPTEXTURECAPS_CUBEMAP ) ) return false; // Must support pixel shader 3.0 if( pCaps->PixelShaderVersion < D3DPS_VERSION( 3, 0 ) ) return false; // need to support D3DFMT_A32B32G32R32F render target if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F ) ) ) return false; return true; } //-------------------------------------------------------------------------------------- // This callback function is called immediately before a device is created to allow the // application to modify the device settings. The supplied pDeviceSettings parameter // contains the settings that the framework has selected for the new device, and the // application can make any desired changes directly to this structure. Note however that // the sample framework will not correct invalid device settings so care must be taken // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail. //-------------------------------------------------------------------------------------- void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps ) { // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW then switch to SWVP. if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) ) { pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } else { pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; } // This application is designed to work on a pure device by not using // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP. if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 ) pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE; // Debugging vertex shaders requires either REF or software vertex processing // and debugging pixel shaders requires REF. #ifdef DEBUG_VS if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF ) { pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING; pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE; pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; } #endif #ifdef DEBUG_PS pDeviceSettings->DeviceType = D3DDEVTYPE_REF; #endif } // Creates VertexBuffer void CreateVertexBuffer() { HRESULT hr; SAFE_RELEASE( g_bSnippetVertexBuffer ); V( g_pd3dDevice->CreateVertexBuffer( (sizeof(float) * 54 * g_iPhotonMapSize * g_iPhotonMapSize ), D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX0 | D3DFVF_TEXCOORDSIZE2( 2 ), D3DPOOL_DEFAULT, &g_bSnippetVertexBuffer, NULL ) ); void* pData; V ( g_bSnippetVertexBuffer->Lock( 0, 0, &pData, 0 ) ); float* pVertexBuffer = (float*)pData; for ( int i = 0; i < g_iPhotonMapSize; i++ ) { for ( int j = 0; j < g_iPhotonMapSize; j++ ) { // Determines the exponent of the PhotonMap size. // It is used as an index to look up from g_fSizeOfSnippet array. int iPhotonMapSizeExponent = (int)(log( (float)g_iPhotonMapSize ) / log ( 2.0f ) + 0.5f ); // 0..8 // By default the fSnippetSize is not constant in world space float fSnippetSize = g_fSizeOfSnippet[ iPhotonMapSizeExponent ] * g_fSnippetSize / g_iPhotonMapSize; // Decides wether the Snippet size is constant in world space or not. if ( g_bSnippetSizeIsConstant ) // If constant fSnippetSize = g_fSizeOfSnippetWithIndependentSnippetSize[ iPhotonMapSizeExponent ] * g_fSnippetSize / g_iPhotonMapSize; float number = (float)( i * g_iPhotonMapSize + j ); float u = (float) i / g_iPhotonMapSize; float v = (float) j / g_iPhotonMapSize; SnippetVertexStruct snippetVertices[] = { // x, y, z, r, g,b,a, u, v, { -fSnippetSize, -fSnippetSize, 0, number, 0,1,0, u, v }, { -fSnippetSize, fSnippetSize, 0, number, 0,0,0, u, v }, { fSnippetSize, fSnippetSize, 0, number, 1,0,0, u, v }, { fSnippetSize, fSnippetSize, 0, number, 1,0,0, u, v }, { fSnippetSize, -fSnippetSize, 0, number, 1,1,0, u, v }, { -fSnippetSize, -fSnippetSize, 0, number, 0,1,0, u, v }, }; memcpy( pVertexBuffer, snippetVertices, sizeof( snippetVertices ) ); pVertexBuffer += 54; } } V (g_bSnippetVertexBuffer->Unlock() ); SAFE_RELEASE( g_pPhotonMapDepthStencilSurface ); SAFE_RELEASE( g_pPhotonUVTexture ); SAFE_RELEASE( g_pPhotonUVMapSurface ); g_pPhotonMapDepthStencilSurface = CreateDepthStencilSurface( g_iPhotonMapSize ); g_pPhotonUVTexture = CreateTexture( g_iPhotonMapSize, D3DFMT_A32B32G32R32F ); V( g_pPhotonUVTexture->GetSurfaceLevel( 0, &g_pPhotonUVMapSurface ) ); // Sends the new texture parameters to the GPU. RenderSceneInitialization(); } D3DXMATRIXA16 ScaleAndOffset(float fScale, D3DXVECTOR3 vOffset) { D3DXMATRIXA16 mScale, mOffset; D3DXMatrixIdentity(&mScale); D3DXMatrixIdentity(&mOffset); D3DXMatrixTranslation( &mOffset, vOffset.x, vOffset.y, vOffset.z ); D3DXMatrixScaling( &mScale, fScale, fScale, fScale ); return mScale * mOffset; } //-------------------------------------------------------------------------------------- // This callback function will be called immediately after the Direct3D device has been // created, which will happen during application initialization and windowed/full screen // toggles. This is the best location to create D3DPOOL_MANAGED resources since these // resources need to be reloaded whenever the device is destroyed. Resources created // here should be released in the OnDestroyDevice callback. //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc ) { HRESULT hr; // Make the device available as a global variable. g_pd3dDevice = pd3dDevice; // Initialize the font V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ) ); // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the // shader debugger. In this case shaders will be unoptimized and forced into software. DWORD dwShaderFlags = D3DXSHADER_PREFER_FLOW_CONTROL | D3DXSHADER_SKIPOPTIMIZATION; #ifdef DEBUG_VS dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT; #endif #ifdef DEBUG_PS dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT; #endif // Read the D3DX effect file WCHAR str[MAX_PATH]; V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"RayTraceEffects.fx" ) ); ID3DXBuffer* errBuff = NULL; if (FAILED(D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, NULL, &g_pEffect, &errBuff ))) { const int BufSize = 500; wchar_t wbuf[BufSize]; mbstowcs( wbuf, (const char*)errBuff->GetBufferPointer(), BufSize ); MessageBox(NULL, wbuf, L".fx compilation error", MB_ICONERROR); exit(-1); } // --- Initialize the matrices --------------------------------------------------------------- // World transform to identity D3DXMATRIXA16 mIdent; D3DXMatrixIdentity( & mIdent ); V_RETURN( pd3dDevice->SetTransform( D3DTS_WORLD, &mIdent ) ); // Setup the camera's view parameters D3DXVECTOR3 vEyePt( -4.0f, 5.0f, -11.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); g_Camera.SetViewParams( &vEyePt, &vLookatPt ); // Initialize the position of light g_vLightPos = D3DXVECTOR3( 0.0f, 4.9f, -4.9f ); // For shadow mapping // Set special texture matrix for shadow mapping float fOffsetX = 0.5f + (0.5f / (float)SHADOWMAP_SIZE); float fOffsetY = 0.5f + (0.5f / (float)SHADOWMAP_SIZE); float range = 1; //note different scale in DX9! //float fBias = -0.001f * range; float fBias = 0.0f; g_mTexScaleBiasMat = D3DXMATRIXA16( 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, range, 0.0f, fOffsetX, fOffsetY, fBias, 1.0f ); // The matrices must be initialized before mesh loading! // --- Load objects ----------------------------------------------------------------------------------- // load default center object if( FAILED( LoadMesh( SPHERE, &g_pCenterObjectMesh, true ) ) ) return DXUTERR_MEDIANOTFOUND; // load room if( FAILED( LoadMesh( ROOM, &g_pRoomMesh, false ) ) ) return DXUTERR_MEDIANOTFOUND; // load light object if( FAILED( LoadMesh( SPHERE, &g_pLightMesh, false ) ) ) return DXUTERR_MEDIANOTFOUND; // load light object if( FAILED( LoadMesh( COLUMN, &g_pColumnMesh, false ) ) ) return DXUTERR_MEDIANOTFOUND; // --- Load objects ends ------------------------------------------------------------------------------ g_pRoomCubeMapColorDistTexture = CreateCubeTexture( CUBEMAP_SIZE, D3DFMT_A16B16G16R16F ); // Because 32 can not use linear filtering. g_pRoomCubeMapUVTexture = CreateCubeTexture( CUBEMAP_SIZE, D3DFMT_A16B16G16R16F ); // Because 32 can not use linear filtering. g_pShadowMapTexture = CreateTexture( SHADOWMAP_SIZE, D3DFMT_A16B16G16R16F ); // Because we use the alpha channel. g_pRoomTexture = CreateTexture( ATLASMAP_SIZE, D3DFMT_A16B16G16R16F ); g_pRoomModifyTexture = CreateTexture( ATLASMAP_SIZE, D3DFMT_A16B16G16R16F ); // Because 32 can not use BLEND function. g_pRoomLastTexture = CreateTexture( ATLASMAP_SIZE, D3DFMT_A16B16G16R16F ); V( g_pShadowMapTexture->GetSurfaceLevel( 0, &g_pShadowMapSurface ) ); V( g_pRoomTexture->GetSurfaceLevel( 0, &g_pRoomSurface ) ); V( g_pRoomModifyTexture->GetSurfaceLevel( 0, &g_pRoomModifySurface ) ); V( g_pRoomLastTexture->GetSurfaceLevel( 0, &g_pRoomLastSurface ) ); V( D3DXLoadSurfaceFromFile( g_pRoomSurface, NULL, NULL, L"Media\\Maps\\RoomTextMap.png", NULL, D3DX_FILTER_NONE, 0xFFFFFFFF, NULL )); // Creates ColumnsTextureArray and surfaces. Load the original map from file to the last one. // The last one is used always as a source. for( int i = 0; i < 4; i++ ) { g_pColumnModifyTexture[i] = CreateTexture( ATLASMAP_SIZE, D3DFMT_A16B16G16R16F ); // Because 32 can not use BLEND function. V( g_pColumnModifyTexture[i]->GetSurfaceLevel( 0, &g_pColumnsModifySurface[i] ) ); } for( int i = 0; i < 5; i++ ) { g_pColumnLastTexture[i] = CreateTexture( ATLASMAP_SIZE, D3DFMT_A16B16G16R16F ); // Because 32 can not use BLEND function. V( g_pColumnLastTexture[i]->GetSurfaceLevel( 0, &g_pColumnsLastSurface[i] ) ); } D3DXLoadSurfaceFromFile( g_pColumnsLastSurface[4], NULL, NULL, L"Media\\Maps\\ColumnMap.png", NULL, D3DX_FILTER_NONE, 0xFFFFFFFF, NULL ); g_pShadowMapDepthStencilSSurface = CreateDepthStencilSurface( SHADOWMAP_SIZE ); g_pDepthStencilSurface = CreateDepthStencilSurface( ATLASMAP_SIZE ); g_pRoomCubeMapDepthStencilSurface = CreateDepthStencilSurface( CUBEMAP_SIZE ); // Creates Snippet Texture, and loads from file D3DXCreateTextureFromFile( pd3dDevice, L"Media\\Maps\\PowerOfSnippetTexel.dds", &g_pPowerOfSnippetTexelTexture); RenderSceneInitialization(); return S_OK; } //-------------------------------------------------------------------------------------- // LoadMesh from file //-------------------------------------------------------------------------------------- HRESULT LoadMesh( WCHAR* strFileName, ID3DXMesh** ppMesh, bool bComputeBoundingBox ) { ID3DXMesh* pMesh = NULL; WCHAR str[MAX_PATH]; D3DXVECTOR3 minPos, maxPos; HRESULT hr; // Load the mesh with D3DX and get back a ID3DXMesh*. For this // sample we'll ignore the X file's embedded materials since we know // exactly the model we're loading. See the mesh samples such as // "OptimizedMesh" for a more generic mesh loading example. V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) ); V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, g_pd3dDevice, NULL, NULL, NULL, NULL, &pMesh) ); if ( bComputeBoundingBox ) { // Lock the vertex buffer, to generate a simple bounding box IDirect3DVertexBuffer9* pMeshVB = NULL; void* pVertices; hr = pMesh->GetVertexBuffer( &pMeshVB ); if( SUCCEEDED( hr ) ) { hr = pMeshVB->Lock( 0, 0, &pVertices, D3DLOCK_NOSYSLOCK ); if( SUCCEEDED(hr) ) { D3DXComputeBoundingBox( ( D3DXVECTOR3*)pVertices, pMesh->GetNumVertices(), D3DXGetFVFVertexSize( pMesh->GetFVF() ), &minPos, &maxPos ); pMeshVB->Unlock(); } pMeshVB->Release(); // If an Object was previously loaded, it removes its offset from WorldCenterObject matrix. g_vCenterObjectPos += g_vCenterObjectPosInitial * g_fCenterObjectSize; // mesh: center-size .. center+size g_vCenterObjectPosInitial = ( minPos + maxPos ) / 2.0f; // The size of the Center Object D3DXVECTOR3 vCenterObjectSize = ( maxPos - minPos ) / 2.0f; // The diameter of the center object float fCenterObjectDiameter = sqrt( vCenterObjectSize.x * vCenterObjectSize.x + vCenterObjectSize.y * vCenterObjectSize.y + vCenterObjectSize.z * vCenterObjectSize.z ) / 1.732f; // Center Object size g_fCenterObjectSize = (float)CENTEROBJECTRADIUS / fCenterObjectDiameter; // Eliminate the offset defined by the X file //g_vCenterObjectPos = D3DXVECTOR3(0,0,0); g_vCenterObjectPos -= g_vCenterObjectPosInitial * g_fCenterObjectSize; // Center Object scale g_mWorldCenterObject = ScaleAndOffset(g_fCenterObjectSize, g_vCenterObjectPos); } } DWORD *rgdwAdjacency = NULL; // Make sure there are normals which are required for lighting if( !(pMesh->GetFVF() & D3DFVF_NORMAL) ) { ID3DXMesh* pTempMesh; V( pMesh->CloneMeshFVF( pMesh->GetOptions(), pMesh->GetFVF() | D3DFVF_NORMAL, g_pd3dDevice, &pTempMesh ) ); V( D3DXComputeNormals( pTempMesh, NULL ) ); SAFE_RELEASE( pMesh ); pMesh = pTempMesh; } // Optimize the mesh for this graphics card's vertex cache // so when rendering the mesh's triangle list the vertices will // cache hit more often so it won't have to re-execute the vertex shader // on those vertices so it will improve perf. rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3]; if( rgdwAdjacency == NULL ) return E_OUTOFMEMORY; V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) ); V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) ); delete []rgdwAdjacency; *ppMesh = pMesh; return S_OK; } //-------------------------------------------------------------------------------------- // Util function. // Creates an empty texture. These textures will be used as render targets, therefore // the Usage flag is set to D3DUSAGE_RENDERTARGET and consequently, the assigned // memory pool is D3DPOOL_DEFAULT. // Params: size and format (eg. D3DFMT_A32B32G32R32F) of the new texture. //-------------------------------------------------------------------------------------- IDirect3DTexture9* CreateTexture( int size, D3DFORMAT Format ) { HRESULT hr; IDirect3DTexture9* pTexture; V( g_pd3dDevice->CreateTexture( size, size, 1, D3DUSAGE_RENDERTARGET, Format, D3DPOOL_DEFAULT, &pTexture, NULL ) ); return pTexture; } //-------------------------------------------------------------------------------------- // Util function. // Creates an empty cubemap texture of the given resolution and format. //-------------------------------------------------------------------------------------- IDirect3DCubeTexture9* CreateCubeTexture( int size, D3DFORMAT Format ) { HRESULT hr; IDirect3DCubeTexture9* pCubeTexture; V( g_pd3dDevice->CreateCubeTexture( size, 1, D3DUSAGE_RENDERTARGET, Format, D3DPOOL_DEFAULT, &pCubeTexture, NULL ) ); return pCubeTexture; } //-------------------------------------------------------------------------------------- // Util function. // Creates a Depth stencil surface (DSS) of the given size. //-------------------------------------------------------------------------------------- IDirect3DSurface9* CreateDepthStencilSurface( int size ) { HRESULT hr; IDirect3DSurface9* pDSSurface; V( g_pd3dDevice->CreateDepthStencilSurface( size, size, DXUTGetDeviceSettings().pp.AutoDepthStencilFormat, D3DMULTISAMPLE_NONE, 0, TRUE, &pDSSurface, NULL ) ); return pDSSurface; } //-------------------------------------------------------------------------------------- // This callback function will be called immediately after the Direct3D device has been // reset, which will happen after a lost device scenario. This is the best location to // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever // the device is lost. Resources created here should be released in the OnLostDevice // callback. //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc ) { HRESULT hr; g_pd3dDevice = pd3dDevice; if( g_pFont ) V_RETURN( g_pFont->OnResetDevice() ); if( g_pEffect ) V_RETURN( g_pEffect->OnResetDevice() ); // Create a sprite to help batch calls when drawing many lines of text V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) ); // --- Vertex declarations ------------------------------------------------------------------ // Create vertex declaration for the snippets V_RETURN( pd3dDevice->CreateVertexDeclaration( g_aSnippetVertex, &g_pSnippetVertexDeclaration ) ); CreateVertexBuffer(); // Create vertex declaration for the fullscreen quad V( pd3dDevice->CreateVertexDeclaration( g_aFullScreneQuadVertex, &g_pFullScreenQuadVertexDeclaration ) ); V_RETURN( pd3dDevice->CreateVertexBuffer( 6 * sizeof( FullScreenQuadVertexStruct ), D3DUSAGE_WRITEONLY, D3DFVF_FULLSCREENQUADVERTEX, D3DPOOL_DEFAULT, &g_pFullScreenQuadVertexBuffer, NULL ) ); void* pVertices; V( g_pFullScreenQuadVertexBuffer->Lock( 0, sizeof( fullscreen ), (void**)&pVertices, 0 ) ); memcpy( pVertices, fullscreen, sizeof( fullscreen ) ); g_pFullScreenQuadVertexBuffer->Unlock(); // --- Vertex declarations ------------------------------------------------------------------ // Setup the camera's projection parameters float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height; g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f ); g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height ); g_Camera.SetButtonMasks( 0, MOUSE_WHEEL, MOUSE_LEFT_BUTTON ); g_HUD.SetLocation( 50, 0 ); g_HUD.SetSize( 250, 250 ); //DXUTDeviceSettings d3dSettings = DXUTGetDeviceSettings(); InitializeHUD(); RenderSceneInitialization(); return S_OK; } //-------------------------------------------------------------------------------------- // This callback function will be called once at the beginning of every frame. This is the // best location for your application to handle updates to the scene, but is not // intended to contain actual rendering calls, which should instead be placed in the // OnFrameRender callback. //-------------------------------------------------------------------------------------- void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime ) { // Update the camera's position based on user input g_Camera.FrameMove( fElapsedTime ); } //-------------------------------------------------------------------------------------- // This callback function will be called at the end of every frame to perform all the // rendering calls for the scene, and it will also be called if the window needs to be // repainted. After this function has returned, the sample framework will call // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain //-------------------------------------------------------------------------------------- void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime ) { HRESULT hr; D3DXMATRIXA16 mScaleLightObjSize, mWorldViewLight, mWorldViewCausticGenerator; g_pd3dDevice = pd3dDevice; //------------------------------------------------------------------------ // This is an initialization. This part of the code runs just once. // CubeMaps are created and basic setup is done here. //------------------------------------------------------------------------ if ( g_bInitialization ) { RenderSceneInitialization(); RenderScenePreProcessing(); g_bInitialization = false; } //------------------------------------------------------------------------ // This part of the code calculates whether the Caustics should be recalculated or not. // Calculate the size of movement between the last Caustics generation and the current position //------------------------------------------------------------------------ float fSumDist = ( abs( g_vLightPos.x - g_vLightPosLast.x ) + abs( g_vLightPos.y - g_vLightPosLast.y ) + abs( g_vLightPos.z - g_vLightPosLast.z ) + abs( g_vCenterObjectPos.x - g_vCenterObjectPosLast.x ) + abs( g_vCenterObjectPos.y - g_vCenterObjectPosLast.y ) + abs( g_vCenterObjectPos.z - g_vCenterObjectPosLast.z ) ); float fEpsilon = 0.01f; // Tolerance of the max move size between two Caustics generation step if ( fSumDist > fEpsilon || g_bRunGenerateCaustics ) { // If the movement is too big, or at least one property is changed // the Caustic effect is recalculated // Generate Caustics effect GenerateCaustics(); // Refreshes Position data g_vLightPosLast = g_vLightPos; g_vCenterObjectPosLast = g_vCenterObjectPos; // Turns off the Caustics Generation g_bRunGenerateCaustics = false; } //------------------------------------------------------------------------ // This part of the code renders the visible objects in the scene. //------------------------------------------------------------------------ D3DXMATRIXA16 mWorldCamera = *g_Camera.GetWorldMatrix(); D3DXMATRIXA16 mViewCamera = *g_Camera.GetViewMatrix(); D3DXMATRIXA16 mProjCamera = *g_Camera.GetProjMatrix(); D3DXMATRIXA16 mWorldLight = ScaleAndOffset(1, g_vLightPos); D3DXMATRIXA16 mWorldViewCamera; D3DXMatrixMultiply( &mWorldViewCamera, &mWorldCamera, &mViewCamera ); D3DXMatrixScaling( &mScaleLightObjSize, LIGHTRADIUS, LIGHTRADIUS, LIGHTRADIUS ); mWorldViewLight = mScaleLightObjSize * mWorldLight * mWorldViewCamera; mWorldViewCausticGenerator = g_mWorldCenterObject * mWorldViewCamera; V( pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0L ) ); if( SUCCEEDED( pd3dDevice->BeginScene() ) ) { // Renders Room and Columns objects RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_ROOM_AND_COLUMNS_SCREEN ); // Renders light source RenderScene( &mWorldViewLight, &mProjCamera, RENDER_LIGHT_SCREEN ); // Renders CenterObject (Caustic generator) RenderScene( &mWorldViewCausticGenerator, &mProjCamera, RENDER_REFRACT_OBJECT_SCREEN ); if( g_bShowPhotonMap ) { // Renders the PhotonMap into the screen RenderScene( &mWorldViewCausticGenerator, &mProjCamera, RENDER_PHOTON_MAP_SCREEN ); } // Renders stats and help text RenderText(); // Show HUD if( g_bShowHUD ) g_HUD.OnRender( fElapsedTime ); pd3dDevice->EndScene(); } } // The next part will run just once ( the initialization ) void RenderScenePreProcessing() { HRESULT hr; D3DXMATRIXA16 mProj_90_Degrees; // projection matrix D3DXMATRIXA16 mWorldView; // worldview matrix D3DXMATRIXA16 mViewCubeMap; LPDIRECT3DSURFACE9 pCubeMapDistSurf, pCubeMapUVSurf; D3DXMATRIXA16 g_mWorldCenterObjectMinus = ScaleAndOffset(1, -g_vCenterObjectPos); // The projection matrix has a FOV of 90 degrees and asp ratio of 1 D3DXMatrixPerspectiveFovLH( &mProj_90_Degrees, D3DX_PI * 0.5f, 1.0f, 0.001f, 1000.0f ); //---------------------------------------------------------------------------------------------- // Saves original settings //---------------------------------------------------------------------------------------------- V( g_pd3dDevice->GetRenderTarget( 0, &g_pRenderTargetSurfaceOld ) ); if( SUCCEEDED( g_pd3dDevice->GetDepthStencilSurface( &g_pDepthStencilSurfaceOld ) ) ) { // If the device has a depth-stencil buffer, use the depth stencil buffer created for the cube textures. V( g_pd3dDevice->SetDepthStencilSurface( g_pRoomCubeMapDepthStencilSurface ) ); } //---------------------------------------------------------------------------------------------- // creates: CubeMap from the position of the CenterObject (RoomCubeMapColorDistanceTexture) // stores: COLOR(x,y,z) + DISTANCE(w) //---------------------------------------------------------------------------------------------- for( int nFace = 0; nFace < 6; ++nFace ) { V( g_pRoomCubeMapColorDistTexture->GetCubeMapSurface( (D3DCUBEMAP_FACES)nFace, 0, &pCubeMapDistSurf ) ); V( g_pd3dDevice->SetRenderTarget( 0, pCubeMapDistSurf ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { mViewCubeMap = DXUTGetCubeMapViewMatrix( nFace ); mWorldView = g_mWorldCenterObjectMinus * mViewCubeMap; RenderScene( &mWorldView, &mProj_90_Degrees, RENDER_ROOM_COLOR_DISTANCE ); g_pd3dDevice->EndScene(); } SAFE_RELEASE( pCubeMapDistSurf ); } //---------------------------------------------------------------------------------------------- // creates: CubeMap from the position of the CenterObject (RoomCubeMapUVTexture) // stores: UV(x,y) + ObjectID(z) + 1 //---------------------------------------------------------------------------------------------- for( int nFace = 0; nFace < 6; ++nFace ) { V( g_pRoomCubeMapUVTexture->GetCubeMapSurface( (D3DCUBEMAP_FACES)nFace, 0, &pCubeMapUVSurf ) ); V( g_pd3dDevice->SetRenderTarget( 0, pCubeMapUVSurf ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { mViewCubeMap = DXUTGetCubeMapViewMatrix( nFace ); mWorldView = g_mWorldCenterObjectMinus * mViewCubeMap; RenderScene( &mWorldView, &mProj_90_Degrees, RENDER_ROOM_UV ); g_pd3dDevice->EndScene(); } SAFE_RELEASE( pCubeMapUVSurf ); } //---------------------------------------------------------------------------------------------- // Restores depth-stencil buffer and render target //---------------------------------------------------------------------------------------------- if( g_pDepthStencilSurfaceOld ) { V( g_pd3dDevice->SetDepthStencilSurface( g_pDepthStencilSurfaceOld ) ); SAFE_RELEASE( g_pDepthStencilSurfaceOld ); } V( g_pd3dDevice->SetRenderTarget( 0, g_pRenderTargetSurfaceOld ) ); SAFE_RELEASE( g_pRenderTargetSurfaceOld ); } void GenerateCaustics() { HRESULT hr; //---------------------------------------------------------------------------------------------- // save original settings //---------------------------------------------------------------------------------------------- V( g_pd3dDevice->GetRenderTarget( 0, &g_pRenderTargetSurfaceOld ) ); if( SUCCEEDED( g_pd3dDevice->GetDepthStencilSurface( &g_pDepthStencilSurfaceOld ) ) ) { // If the device has a depth-stencil buffer, use the depth stencil buffer created for the cube textures. V( g_pd3dDevice->SetDepthStencilSurface( g_pRoomCubeMapDepthStencilSurface ) ); } //---------------------------------------------------------------------------------------------- // creates: PhotonMap from light position // stores: UV(x,y) + ObjectID(z) + "1" //---------------------------------------------------------------------------------------------- // Calculate the light's worldview transformation and take picture from there D3DXVECTOR3 vUpPt( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_mWorldViewLight, &g_vLightPos, &g_vCenterObjectPos, &vUpPt ); // Calculate FOV of the light float radiusCenter = CENTEROBJECTRADIUS * 1.03f; // The radius of the CenterObject D3DXVECTOR3 vDiff = g_vLightPos - g_vCenterObjectPos; float dist = sqrt ( vDiff.x * vDiff.x + // The distance between vDiff.y * vDiff.y + // light source and CenterObject vDiff.z * vDiff.z ); float fovLight = atan ( radiusCenter / dist ) * 2; // fov[rad] D3DXMATRIXA16 mLightProj; // projection matrix for the light D3DXMatrixPerspectiveFovLH( &mLightProj, fovLight, 1.0f, 0.001f, 1000.0f ); // Skip this part of code if Caustic effect is not used if ( g_bCausticsON ) { V( g_pd3dDevice->SetDepthStencilSurface( g_pPhotonMapDepthStencilSurface ) ); V( g_pd3dDevice->SetRenderTarget( 0, g_pPhotonUVMapSurface ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { RenderScene( &g_mWorldViewLight, &mLightProj, RENDER_PHOTON_UV_MAP ); g_pd3dDevice->EndScene(); } } // -- DEBUG ---------------------------------------------------------------------------------------------- if( g_bSaveTexture ) { D3DXSaveSurfaceToFile( L"PhotonMap.png", D3DXIFF_PNG, g_pPhotonUVMapSurface, NULL,NULL); g_bSaveTexture = false; } // -- DEBUG END ---------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------- // creates: ShadowMap from light position // stores: Distance(x) //---------------------------------------------------------------------------------------------- // Skip this part of code if Shadow is not used if ( g_bShadowON ) { V( g_pd3dDevice->SetDepthStencilSurface( g_pShadowMapDepthStencilSSurface ) ); V( g_pd3dDevice->SetRenderTarget( 0, g_pShadowMapSurface ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); // Sets depth bias to a predefined value g_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, (DWORD)g_dDepthBias); g_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, (DWORD)g_dBiasSlope); // The projection of the ShadowMap is 80 degree. D3DXMatrixPerspectiveFovLH( &g_mProjLight, D3DXToRadian( 80.0f ), 1.0f, 1.0f, 20.0f ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { RenderScene( &g_mWorldViewLight, &g_mProjLight, RENDER_SHADOW ); g_pd3dDevice->EndScene(); } // Sets back the depth bias to "0" g_pd3dDevice->SetRenderState( D3DRS_DEPTHBIAS, (DWORD)0.0f ); g_pd3dDevice->SetRenderState( D3DRS_SLOPESCALEDEPTHBIAS, (DWORD)0.0f ); } //-------------------------------------------------------------------------------------------- // creates: RoomLastTexture, and ColumnTexture[0,1,2,3] // They will be used as source textures when the Room and Columns are rendered in the visible scene // stores: Color(r,g,b,a) //-------------------------------------------------------------------------------------------- D3DXMATRIXA16 mWorldViewCamera = *g_Camera.GetViewMatrix(); D3DXMATRIXA16 mProjCamera = *g_Camera.GetProjMatrix(); // Render Room with Shadow and Caustics V( g_pd3dDevice->SetRenderTarget( 0, g_pRoomModifySurface ) ); V( g_pd3dDevice->SetDepthStencilSurface( g_pDepthStencilSurface ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Renders Room with Shadow and Caustics g_iObjectID = -1; // The ID of the Room Object = -1 RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_UMBRA ); if ( g_bCausticsON ) RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_PHOTON_HIT ); g_pd3dDevice->EndScene(); } V( g_pd3dDevice->SetRenderTarget( 0, g_pRoomLastSurface ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Removes the black edges. Enlarges the usefull content of the atlas with one texel RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_FULLSCREENQUAD ); g_pd3dDevice->EndScene(); } // Renders Columns with Shadow and Caustics for (int i = 0; i < 4; i++) { // Renders one Column with Shadow and Caustics V( g_pd3dDevice->SetRenderTarget( 0, g_pColumnsModifySurface[i] ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { g_iObjectID = i; // The ID of a Column RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_UMBRA ); if ( g_bCausticsON ) RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_PHOTON_HIT ); g_pd3dDevice->EndScene(); } V( g_pd3dDevice->SetRenderTarget( 0, g_pColumnsLastSurface[i] ) ); V( g_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L ) ); if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Removes the black edges. Enlarges the usefull content of the atlas with one texel RenderScene( &mWorldViewCamera, &mProjCamera, RENDER_FULLSCREENQUAD ); g_pd3dDevice->EndScene(); } } /* // -- DEBUG ---------------------------------------------------------------------------------------------- if( g_bSaveTexture ) { D3DXSaveSurfaceToFile( L"RoomMod.png", D3DXIFF_PNG, g_pRoomModifySurface, NULL,NULL); D3DXSaveSurfaceToFile( L"RoomLast.png", D3DXIFF_PNG, g_pRoomLastSurface, NULL,NULL); D3DXSaveSurfaceToFile( L"ColumnMod0.png", D3DXIFF_PNG, g_pColumnsModifySurface[0], NULL,NULL); //D3DXSaveSurfaceToFile( L"ColumnMod1.png", D3DXIFF_PNG, g_pColumnsModifySurface[1], NULL,NULL); //D3DXSaveSurfaceToFile( L"ColumnMod2.png", D3DXIFF_PNG, g_pColumnsModifySurface[2], NULL,NULL); //D3DXSaveSurfaceToFile( L"ColumnMod3.png", D3DXIFF_PNG, g_pColumnsModifySurface[3], NULL,NULL); D3DXSaveSurfaceToFile( L"ColumnLast0.png", D3DXIFF_PNG, g_pColumnsLastSurface[0], NULL,NULL); //D3DXSaveSurfaceToFile( L"ColumnLast1.png", D3DXIFF_PNG, g_pColumnsLastSurface[1], NULL,NULL); //D3DXSaveSurfaceToFile( L"ColumnLast2.png", D3DXIFF_PNG, g_pColumnsLastSurface[2], NULL,NULL); //D3DXSaveSurfaceToFile( L"ColumnLast3.png", D3DXIFF_PNG, g_pColumnsLastSurface[3], NULL,NULL); g_bSaveTexture = false; } // -- DEBUG END ---------------------------------------------------------------------------------------------- */ //---------------------------------------------------------------------- // Restores depth-stencil buffer and render target //--------------------------------------------------------------------- if( g_pDepthStencilSurfaceOld ) { V( g_pd3dDevice->SetDepthStencilSurface( g_pDepthStencilSurfaceOld ) ); SAFE_RELEASE( g_pDepthStencilSurfaceOld ); } V( g_pd3dDevice->SetRenderTarget( 0, g_pRenderTargetSurfaceOld ) ); SAFE_RELEASE( g_pRenderTargetSurfaceOld ); } // Sends texture parameters to the GPU. void RenderSceneInitialization() { HRESULT hr; // Bind textures V( g_pEffect->SetTexture( "g_txRoomMap", g_pRoomTexture ) ); V( g_pEffect->SetTexture( "g_txRoomCubeMapColorDistanceMap", g_pRoomCubeMapColorDistTexture ) ); V( g_pEffect->SetTexture( "g_txRoomCubeMapUVMap", g_pRoomCubeMapUVTexture ) ); V( g_pEffect->SetTexture( "g_txRoomModifyMap", g_pRoomModifyTexture ) ); V( g_pEffect->SetTexture( "g_txRoomLastMap", g_pRoomLastTexture ) ); V( g_pEffect->SetTexture( "g_txPhotonUVMap", g_pPhotonUVTexture ) ); V( g_pEffect->SetTexture( "g_txPowerOfSnippetMap", g_pPowerOfSnippetTexelTexture ) ); V( g_pEffect->SetTexture( "g_txColumnModifyTexture0", g_pColumnModifyTexture[0] ) ); V( g_pEffect->SetTexture( "g_txColumnModifyTexture1", g_pColumnModifyTexture[1] ) ); V( g_pEffect->SetTexture( "g_txColumnModifyTexture2", g_pColumnModifyTexture[2] ) ); V( g_pEffect->SetTexture( "g_txColumnModifyTexture3", g_pColumnModifyTexture[3] ) ); V( g_pEffect->SetTexture( "g_txColumnLastTexture0", g_pColumnLastTexture[0] ) ); V( g_pEffect->SetTexture( "g_txColumnLastTexture1", g_pColumnLastTexture[1] ) ); V( g_pEffect->SetTexture( "g_txColumnLastTexture2", g_pColumnLastTexture[2] ) ); V( g_pEffect->SetTexture( "g_txColumnLastTexture3", g_pColumnLastTexture[3] ) ); V( g_pEffect->SetTexture( "g_txColumnOriginalTexture", g_pColumnLastTexture[4] ) ); V( g_pEffect->SetTexture( "g_txShadowMap", g_pShadowMapTexture ) ); } // This function renders the Room mesh. void RenderRoom(D3DXMATRIXA16 *mWorldView, D3DXMATRIXA16 *mProj) { HRESULT hr; D3DXMATRIXA16 mWorldViewProjection; V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ) ); D3DXMatrixMultiply( &mWorldViewProjection, mWorldView, mProj ); V( g_pEffect->SetMatrix( "g_mWorldView", mWorldView ) ); V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) ); V( g_pEffect->SetMatrix( "g_mLightViewTexBias", &mWorldViewProjection ) ); V( g_pEffect->SetInt( "g_iObjectID", -1 ) ); V( g_pEffect->CommitChanges() ); V( g_pRoomMesh->DrawSubset( 0 ) ); V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ) ); } // This function renders the Columns mesh. void RenderColumns(D3DXMATRIXA16 *mWorldView, D3DXMATRIXA16 *mProj) { HRESULT hr; D3DXMATRIXA16 mWorldOffset, mWorldViewProjection; for (int i = 0; i < 4; i++) { if (i==0) D3DXMatrixTranslation( &mWorldOffset, 3.75f ,0 , 3.75f ); if (i==1) D3DXMatrixTranslation( &mWorldOffset, -3.75f ,0 , 3.75f ); if (i==2) D3DXMatrixTranslation( &mWorldOffset, 3.75f ,0 ,-3.75f ); if (i==3) D3DXMatrixTranslation( &mWorldOffset, -3.75f ,0 ,-3.75f ); D3DXMatrixMultiply( &mWorldOffset, &mWorldOffset, mWorldView); D3DXMatrixMultiply( &mWorldViewProjection, &mWorldOffset, mProj); V( g_pEffect->SetMatrix( "g_mWorldView", &mWorldOffset ) ); V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) ); V( g_pEffect->SetMatrix( "g_mLightViewTexBias", &mWorldViewProjection ) ); V( g_pEffect->SetInt( "g_iObjectID", i ) ); V( g_pEffect->CommitChanges() ); V( g_pColumnMesh->DrawSubset( 0 ) ); } } // Sets the techniques. // Calculates and sends parameters to the GPU. void RenderScene(D3DXMATRIXA16 *mWorldView, D3DXMATRIXA16 *mProj, int method ) { HRESULT hr; UINT cPass; D3DXMATRIXA16 mWorldViewProjection, mWorldOffset; D3DXMatrixMultiply( &mWorldViewProjection, mWorldView, mProj ); V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) ); V( g_pEffect->SetMatrix( "g_mWorldView", mWorldView ) ); V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW ) ); //---------------------------------------------------------------------- // It renders Room and Columns from the CenterObject position // and stores them in a CubeMap: g_pRoomCubeMapColorDistTexture. // Contains: COLOR(x,y,z) + Distance(w) //---------------------------------------------------------------------- if ( method == RENDER_ROOM_COLOR_DISTANCE ) { V( g_pEffect->SetTechnique( "RenderRoomColorDistance" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); // Render Room RenderRoom( mWorldView, mProj ); // Render Columns RenderColumns( mWorldView, mProj ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders Room and Columns from the center object position // and stores them in a CubeMap: g_pRoomCubeMapUVTexture. // Contains: UV(x,y) + ObjectID(z) + "1" //---------------------------------------------------------------------- if ( method == RENDER_ROOM_UV ) { V( g_pEffect->SetTechnique( "RenderRoomUV" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); // Render Room RenderRoom( mWorldView, mProj ); // Render Columns RenderColumns( mWorldView, mProj ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders Room and Columns from the center object position // and stores them in their Atlases. // Contains: Color(r,g,b,a ) //---------------------------------------------------------------------- if ( method == RENDER_UMBRA ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ) ); V( g_pEffect->SetTechnique( "RenderUmbra" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); g_mLightViewTexBias = g_mWorldViewLight * g_mProjLight * g_mTexScaleBiasMat; V( g_pEffect->SetMatrix( "g_mLightViewTexBias", &g_mLightViewTexBias ) ); V( g_pEffect->SetBool( "g_bShadowON", g_bShadowON ) ); V( g_pEffect->SetBool( "g_bShowHelp", g_bShowHelp ) ); V( g_pEffect->SetFloatArray( "g_vLightPos3f", g_vLightPos, 3 ) ); V( g_pEffect->SetFloat( "g_fShadowIntensity", 1-g_fShadowIntensity )); V( g_pEffect->SetFloat( "g_fCausticsIntensity", g_fCausticsIntensity )); V( g_pEffect->BeginPass( 0 ) ); if (g_iObjectID == -1) { // Render Room V( g_pEffect->SetInt( "g_iObjectID", -1 ) ); V( g_pEffect->CommitChanges() ); V( g_pRoomMesh->DrawSubset( 0 ) ); } else { // Render Columns if (g_iObjectID==0) D3DXMatrixTranslation( &mWorldOffset, 3.75f ,0 , 3.75f ); if (g_iObjectID==1) D3DXMatrixTranslation( &mWorldOffset, -3.75f ,0 , 3.75f ); if (g_iObjectID==2) D3DXMatrixTranslation( &mWorldOffset, 3.75f ,0 ,-3.75f ); if (g_iObjectID==3) D3DXMatrixTranslation( &mWorldOffset, -3.75f ,0 ,-3.75f ); V( g_pEffect->SetMatrix( "g_mWorldView", &mWorldOffset ) ); V( g_pEffect->SetInt( "g_iObjectID", g_iObjectID ) ); V( g_pEffect->CommitChanges() ); V( g_pColumnMesh->DrawSubset( 0 ) ); } V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders Room and Columns from the camera position // and shows them on the screen. // Contains: Color(r,g,b,a) //---------------------------------------------------------------------- if ( method == RENDER_ROOM_AND_COLUMNS_SCREEN ) { V( g_pEffect->SetTechnique( "RenderRoomAndColumnsScreen" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); // Render Room RenderRoom( mWorldView, mProj ); // Render Columns RenderColumns( mWorldView, mProj ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders CenterObject from the light position // and stores it in g_pPhotonUVTexture. // Contains: UV(x,y) + ObjectID(1) + "1" or "-1" //---------------------------------------------------------------------- if ( method == RENDER_PHOTON_UV_MAP ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ) ); if( g_iAlgorithmMethod == 0 ) // Uses classic method V( g_pEffect->SetTechnique( "RenderPhotonUVMapClassic" ) ); if( g_iAlgorithmMethod == 1 ) // Uses distance impostor V( g_pEffect->SetTechnique( "RenderPhotonUVMap" ) ); D3DXMatrixMultiply( &mWorldViewProjection, mWorldView, mProj ); D3DXMatrixMultiply( &mWorldViewProjection, &g_mWorldCenterObject, &mWorldViewProjection ); V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) ); V( g_pEffect->SetMatrix( "g_mWorldCenterObject", &g_mWorldCenterObject ) ); V( g_pEffect->SetFloatArray( "g_vLightPos3f", g_vLightPos, 3 ) ); V( g_pEffect->SetInt( "g_iNumberOfIteration", g_iNumberOfIteration) ); V( g_pEffect->SetInt( "g_iPhotonMapSize", g_iPhotonMapSize) ); V( g_pEffect->SetFloat( "g_fRefractionIndex", g_fRefractionIndex ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); V( g_pEffect->CommitChanges() ); V( g_pCenterObjectMesh->DrawSubset( 0 ) ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders CenterObject from the camera position // and shows it on the screen. // Contains: Color(r,g,b,a) //---------------------------------------------------------------------- if ( method == RENDER_REFRACT_OBJECT_SCREEN ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ) ); if( g_bRenderCenterObjectWithBrdfON ) { if( g_iAlgorithmMethod == 0 ) // Uses classic method V( g_pEffect->SetTechnique( "RenderRefractObjectScreenClassic" ) ); if( g_iAlgorithmMethod == 1 ) // Uses distance impostor V( g_pEffect->SetTechnique( "RenderRefractObjectScreen" ) ); } else // Uses diffuse color V( g_pEffect->SetTechnique( "RenderLightScreen" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); D3DXVECTOR3 vWorldCameraEye = *g_Camera.GetEyePt(); V( g_pEffect->SetMatrix( "g_mWorldCenterObject", &g_mWorldCenterObject ) ); V( g_pEffect->SetFloatArray( "g_vCameraPos3f", vWorldCameraEye, 3 ) ); V( g_pEffect->SetInt( "g_iNumberOfIteration", g_iNumberOfIteration)); V( g_pEffect->SetFloat( "g_fFresnelFactor", g_fFresnelFactor)); V( g_pEffect->SetFloat( "g_fRefractionIndex", g_fRefractionIndex )); V( g_pEffect->BeginPass( 0 ) ); V( g_pEffect->CommitChanges() ); V( g_pCenterObjectMesh->DrawSubset( 0 ) ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders and blends impostors into the Atlases of Room and Columns // Contains: Color(r,g,b,a) //---------------------------------------------------------------------- if ( method == RENDER_PHOTON_HIT ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ) ); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, false); V( g_pEffect->SetTechnique( "RenderPhotonHit" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); float x = g_vLightPos.x - g_vCenterObjectPos.x; float y = g_vLightPos.y - g_vCenterObjectPos.y; float z = g_vLightPos.z - g_vCenterObjectPos.z; float gll2 = x * x + y * y + z * z; //float POWER = CENTEROBJECTRADIUS * CENTEROBJECTRADIUS / 10;//45 * CENTEROBJECTRADIUS * CENTEROBJECTRADIUS * 4 / (SNIPPET_SIZE * SNIPPET_SIZE); //float POWER = 45 * CENTEROBJECTRADIUS * CENTEROBJECTRADIUS * 4 / (g_iPhotonMapSize * g_iPhotonMapSize); //float POWER = 45 * CENTEROBJECTRADIUS * CENTEROBJECTRADIUS * 4 / g_iPhotonMapSize; // Determines the exponent of the PhotonMap size. // It is used as an index to look up from g_fIntensityOfSnippet array. int iPhotonMapSizeExponent = (int)( log( (float)g_iPhotonMapSize ) / log ( 2.0f ) + 0.5 ); // 0..8 // By default the fSnippetSize is not constant in world space float fSnippetIntensity = g_fIntensityOfSnippet[ iPhotonMapSizeExponent ]; if( g_bSnippetSizeIsConstant ) // if it is constant fSnippetIntensity = g_fIntensityOfSnippetWithIndependentSnippetSize[ iPhotonMapSizeExponent ]; // The intensity value of one snippet float POWER = 10 * CENTEROBJECTRADIUS * CENTEROBJECTRADIUS / ( g_fSnippetSize * g_fSnippetSize * fSnippetIntensity * fSnippetIntensity ); V( g_pEffect->BeginPass( 0 ) ); V( g_pEffect->SetInt( "g_iObjectID", g_iObjectID ) ); V( g_pEffect->SetFloat( "g_fPower", POWER / gll2 ) ); V( g_pEffect->SetFloat( "g_fCausticsIntensity", g_fCausticsIntensity ) ); V( g_pEffect->CommitChanges() ); V( g_pd3dDevice->SetVertexDeclaration( g_pSnippetVertexDeclaration ) ); V( g_pd3dDevice->SetStreamSource( 0, g_bSnippetVertexBuffer, 0, (sizeof(float)* 9 ) ) ); V( g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, ( g_iPhotonMapSize * g_iPhotonMapSize * 2 ) ) ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); } //---------------------------------------------------------------------- // It renders Light Object from the camera position // and shows it on the screen. // Contains: Color(r,g,b,a) //---------------------------------------------------------------------- if ( method == RENDER_LIGHT_SCREEN ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ) ); V( g_pEffect->SetTechnique( "RenderLightScreen" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); V( g_pEffect->CommitChanges() ); V( g_pLightMesh->DrawSubset( 0 ) ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders CenterObject, Columns and Room from light position // and stores them in g_pShadowMapTexture. // Contains: Depth(x) //---------------------------------------------------------------------- if ( method == RENDER_SHADOW ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ) ); V( g_pEffect->SetTechnique( "RenderShadow" ) ); D3DXMatrixMultiply( &mWorldViewProjection, &g_mWorldCenterObject, &mWorldViewProjection ); V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) ); V( g_pEffect->SetMatrix( "g_mLightViewTexBias", &mWorldViewProjection ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); // Render CenterObject V( g_pEffect->CommitChanges() ); V( g_pCenterObjectMesh->DrawSubset( 0 ) ); // Render Columns RenderColumns( mWorldView, mProj ); // Render Room RenderRoom( mWorldView, mProj ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } //---------------------------------------------------------------------- // It renders a fullscreen quad // and modifies the Room and Columns atlases. // Contains: Color(r,g,b,a) //---------------------------------------------------------------------- if ( method == RENDER_FULLSCREENQUAD ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ) ); V( g_pEffect->SetTechnique( "FullScreenQuad" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); V( g_pEffect->SetInt( "g_iObjectID", g_iObjectID ) ); V( g_pEffect->CommitChanges() ); V( g_pd3dDevice->SetVertexDeclaration( g_pFullScreenQuadVertexDeclaration ) ); V( g_pd3dDevice->SetStreamSource( 0, g_pFullScreenQuadVertexBuffer, 0, sizeof(FullScreenQuadVertexStruct) ) ); V( g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ) ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } if ( method == RENDER_PHOTON_MAP_SCREEN ) { V( g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ) ); V( g_pEffect->SetTechnique( "PhotonMapScreen" ) ); V( g_pEffect->Begin( &cPass, 0 ) ); V( g_pEffect->BeginPass( 0 ) ); V( g_pEffect->CommitChanges() ); V( g_pd3dDevice->SetVertexDeclaration( g_pFullScreenQuadVertexDeclaration ) ); V( g_pd3dDevice->SetStreamSource( 0, g_pFullScreenQuadVertexBuffer, 0, sizeof(FullScreenQuadVertexStruct) ) ); V( g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 ) ); V( g_pEffect->EndPass() ); V( g_pEffect->End() ); } } //-------------------------------------------------------------------------------------- // Render the help and statistics text. This function uses the ID3DXFont interface for // efficient text rendering. //-------------------------------------------------------------------------------------- void RenderText() { // The helper object simply helps keep track of text position, and color // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr ); // If NULL is passed in as the sprite object, then it will work however the // pFont->DrawText() will not be batched together. Batching calls will improves performance. const D3DSURFACE_DESC* pd3dsdBackBuffer = DXUTGetBackBufferSurfaceDesc(); CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 16 ); // Output statistics txtHelper.Begin(); txtHelper.SetInsertionPos( 10, 5 ); txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); /*TCHAR sz[50]; sz[49] = 0; _sntprintf( sz, 50, L"%.2f fps", DXUTGetFPS() ); txtHelper.DrawTextLine( sz );*/ txtHelper.DrawTextLine( DXUTGetFrameStats() ); //txtHelper.DrawTextLine( DXUTGetDeviceStats() ); if (!g_bShowHelp) txtHelper.DrawTextLine( L"Press F1 for help" ); // Show algorithm's parameters if ( g_bShowVariables ) { txtHelper.SetInsertionPos( 200, 50 ); txtHelper.DrawTextLine( L"Number of iteration" ); txtHelper.DrawTextLine( L"Fresnel factor" ); txtHelper.DrawTextLine( L"Refraction index" ); txtHelper.DrawTextLine( L"Shadow intensity" ); txtHelper.DrawTextLine( L"Caustics intensity" ); txtHelper.DrawTextLine( L"PhotonMap size" ); txtHelper.DrawTextLine( L"Snippet size" ); txtHelper.SetInsertionPos( 330, 50 ); TCHAR sz0[50], sz1[50], sz2[50], sz3[50], sz4[50], sz5[50], sz6[50]; sz0[49] = sz1[49] = sz2[49] = sz3[49] = sz4[49] = sz5[49] = sz6[49] = 0; _sntprintf( sz0, 50, L"%i", g_iNumberOfIteration ); _sntprintf( sz1, 50, L"%.2f", g_fFresnelFactor ); _sntprintf( sz2, 50, L"%.2f", g_fRefractionIndex ); _sntprintf( sz3, 50, L"%.2f", g_fShadowIntensity ); _sntprintf( sz4, 50, L"%.2f", g_fCausticsIntensity ); _sntprintf( sz5, 50, L"%i", g_iPhotonMapSize ); _sntprintf( sz6, 50, L"%.2f", g_fSnippetSize ); txtHelper.DrawTextLine( sz0 ); txtHelper.DrawTextLine( sz1 ); txtHelper.DrawTextLine( sz2 ); txtHelper.DrawTextLine( sz3 ); txtHelper.DrawTextLine( sz4 ); txtHelper.DrawTextLine( sz5 ); txtHelper.DrawTextLine( sz6 ); } // Draw help if ( g_bShowHelp ) { const D3DSURFACE_DESC* backBufferDesc = DXUTGetBackBufferSurfaceDesc(); txtHelper.SetInsertionPos( backBufferDesc->Width - 220, backBufferDesc->Height-24 * 16 ); txtHelper.DrawTextLine( L"Controls (F1 to hide):\n\n" L"____________________________\n" L" GENERAL CONTROLS\n" L"Left click drag: Rotate mesh\n" L"Mouse wheel: Zoom\n" L"Arrow keys: Move center object\n" L"Alt+Arrow keys: Move light object\n" L"F2: Settings\n" L"F3: Switch to REF device\n" L"F4: Show parameters ON/OFF\n" L"F5: Show HUD ON/OFF\n" L"F8: Switch to Wireframe mode\n" L"____________________________\n" L" ALGORITHM\n" L"1-5: Choose mesh\n" L"C: Caustics Effect ON/OFF\n" L"S: Shadow ON/OFF\n" L"X: Center Objectum render ON/OFF\n" L"D: Switch classic / dist. imp. meth.\n" L"Y: Reset parameters\n" L"V: Indep. Snippet size?\n" L"M: Show PhotonMap ON/OFF\n" L"____________________________\n" L" Quit: ESC"); if( g_bShowHUD ) txtHelper.SetInsertionPos( 540, 50 ); else txtHelper.SetInsertionPos( 370, 50 ); if ( g_bShowVariables ) { txtHelper.DrawTextLine( L"Key: +, -" ); txtHelper.DrawTextLine( L"Key: Q, W" ); txtHelper.DrawTextLine( L"Key: E, R" ); txtHelper.DrawTextLine( L"Key: T, Z" ); txtHelper.DrawTextLine( L"Key: U, I" ); txtHelper.DrawTextLine( L"Key: O, P" ); txtHelper.DrawTextLine( L"Key: K, L" ); txtHelper.DrawTextLine( L"+ 'Alt' key:"); txtHelper.DrawTextLine( L" quick change" ); } } // Draws the title of the PhotonMap if ( g_bShowPhotonMap ) { const D3DSURFACE_DESC* backBufferDesc = DXUTGetBackBufferSurfaceDesc(); txtHelper.SetInsertionPos( 65, backBufferDesc->Height - 180 ); txtHelper.DrawTextLine( L"PhotonMap" ); } txtHelper.End(); } //-------------------------------------------------------------------------------------- // Before handling window messages, the sample framework passes incoming windows // messages to the application through this callback function. If the application sets // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message. //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing ) { // Give the dialogs a chance to handle the message first *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; // Pass all remaining windows messages to camera so it can respond to user input g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); return 0; } //-------------------------------------------------------------------------------------- // As a convenience, the sample framework inspects the incoming windows messages for // keystroke messages and decodes the message parameters to pass relevant keyboard // messages to the application. The framework does not remove the underlying keystroke // messages, which are still passed to the application's MsgProc callback. //-------------------------------------------------------------------------------------- void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown ) { HRESULT hr; D3DXVECTOR3 movement(0,0,0); if( bKeyDown ) { switch( nChar ) { // Save Objects Last Texture Atlas case 'A': g_bSaveTexture = true; g_bRunGenerateCaustics = true; break; // Show Help case VK_F1: g_bShowHelp = !g_bShowHelp; if (!g_bShowVariablesUserSet) g_bShowVariables = g_bShowHelp || g_bShowHUD; g_bRunGenerateCaustics = true; break; // Show the values of the algorithm's variables case VK_F4: g_bShowVariables = !g_bShowVariables; g_bShowVariablesUserSet = !g_bShowVariablesUserSet; break; // Show HUD case VK_F5: g_bShowHUD = !g_bShowHUD; if (!g_bShowVariablesUserSet) g_bShowVariables = g_bShowHelp || g_bShowHUD; break; // Change the Mesh of CenterObject case '1': SAFE_RELEASE( g_pCenterObjectMesh ); V( LoadMesh( SPHERE, &g_pCenterObjectMesh, true ) ); g_bRunGenerateCaustics = true; break; case '2': SAFE_RELEASE( g_pCenterObjectMesh ); V( LoadMesh( SKULL, &g_pCenterObjectMesh, true ) ); g_bRunGenerateCaustics = true; break; case '3': SAFE_RELEASE( g_pCenterObjectMesh ); V( LoadMesh( BUNNY, &g_pCenterObjectMesh, true ) ); g_bRunGenerateCaustics = true; break; case '4': SAFE_RELEASE( g_pCenterObjectMesh ); V( LoadMesh( TEAPOT, &g_pCenterObjectMesh, true ) ); g_bRunGenerateCaustics = true; break; case '5': SAFE_RELEASE( g_pCenterObjectMesh ); V( LoadMesh( TIGER, &g_pCenterObjectMesh, true ) ); g_bRunGenerateCaustics = true; break; // Switch between the classical and our new distance impostor method case 'D': g_iAlgorithmMethod = 1 - g_iAlgorithmMethod; if ( g_iAlgorithmMethod == 0 ) g_HUD.GetRadioButton( IDC_CLASSIC_METHOD )->SetChecked( true ); else g_HUD.GetRadioButton( IDC_DISTANCE_IMPOSTOR_METHOD )->SetChecked( true ); g_bRunGenerateCaustics = true; break; // Change the number of iteration. case VK_ADD: if( g_iNumberOfIteration < 20 ) g_iNumberOfIteration++; g_HUD.GetSlider( IDC_NUMBER_OF_ITERATION_SLIDER )->SetValue( g_iNumberOfIteration ); g_bRunGenerateCaustics = true; break; case VK_SUBTRACT: if ( g_iNumberOfIteration > 0 ) g_iNumberOfIteration--; g_HUD.GetSlider( IDC_NUMBER_OF_ITERATION_SLIDER )->SetValue( g_iNumberOfIteration ); g_bRunGenerateCaustics = true; break; // Change the intensity of the shadow case 'Z': g_fShadowIntensity += bAltDown ? 0.1f : 0.01f; if ( g_fShadowIntensity > 1 ) g_fShadowIntensity = 1; g_HUD.GetSlider( IDC_SHADOW_INTENSITY_SLIDER )->SetValue( (int)g_fShadowIntensity * 100 ); g_bRunGenerateCaustics = true; break; case 'T': g_fShadowIntensity -= bAltDown ? 0.1f : 0.01f; if ( g_fShadowIntensity < 0 ) g_fShadowIntensity = 0; g_HUD.GetSlider( IDC_SHADOW_INTENSITY_SLIDER )->SetValue( (int)g_fShadowIntensity * 100 ); g_bRunGenerateCaustics = true; break; // Change the intensity of the caustics snippet case 'U': g_fCausticsIntensity -= bAltDown ? 0.1f : 0.01f; if ( g_fCausticsIntensity < 0 ) g_fCausticsIntensity = 0; //g_fCausticsIntensity = pow ( 2.0f, g_HUD.GetSlider( IDC_CAUSTICS_INTENSITY_SLIDER )->GetValue() / 100.0f ); g_HUD.GetSlider( IDC_CAUSTICS_INTENSITY_SLIDER )->SetValue( (int)( log( g_fCausticsIntensity ) / log ( 1.2f ) ) * 100 ); g_bRunGenerateCaustics = true; break; case 'I': g_fCausticsIntensity += bAltDown ? 0.1f : 0.01f; g_HUD.GetSlider( IDC_CAUSTICS_INTENSITY_SLIDER )->SetValue( (int)(log( g_fCausticsIntensity ) / log ( 1.2f ) ) * 100 ); g_bRunGenerateCaustics = true; break; // Change the refraction index case 'E': g_fRefractionIndex -= bAltDown ? 0.1f : 0.01f; if (g_fRefractionIndex < 0) g_fRefractionIndex = 0; g_HUD.GetSlider( IDC_REFRACTION_INDEX_SLIDER )->SetValue( (int)g_fRefractionIndex * 100 ); g_bRunGenerateCaustics = true; break; case 'R': g_fRefractionIndex += bAltDown ? 0.1f : 0.01f; if (g_fRefractionIndex > 1) g_fRefractionIndex = 1; g_HUD.GetSlider( IDC_REFRACTION_INDEX_SLIDER )->SetValue( (int)g_fRefractionIndex * 100 ); g_bRunGenerateCaustics = true; break; // Change Fresnel factor case 'Q': g_fFresnelFactor -= bAltDown ? 0.1f : 0.01f; if (g_fFresnelFactor < 0) g_fFresnelFactor = 0; g_HUD.GetSlider( IDC_FRESNEL_FACTOR_SLIDER )->SetValue( (int)g_fFresnelFactor * 100 ); g_bRunGenerateCaustics = true; break; case 'W': g_fFresnelFactor += bAltDown ? 0.1f : 0.01f; if (g_fFresnelFactor > 1) g_fFresnelFactor = 1; g_HUD.GetSlider( IDC_FRESNEL_FACTOR_SLIDER )->SetValue( (int)g_fFresnelFactor * 100 ); g_bRunGenerateCaustics = true; break; // Change PhotonMap size case 'O': if( g_iPhotonMapSize > 1 ) { g_iPhotonMapSize /= 2; g_HUD.GetSlider( IDC_PHOTON_MAP_SIZE_SLIDER )->SetValue( (int) ( log( (float)g_iPhotonMapSize ) / log( 2.0f ) ) ); CreateVertexBuffer(); g_bRunGenerateCaustics = true; } break; case 'P': if( g_iPhotonMapSize < PHOTONMAP_MAX_SIZE ) { g_iPhotonMapSize *= 2; g_HUD.GetSlider( IDC_PHOTON_MAP_SIZE_SLIDER )->SetValue( (int) ( log( (float)g_iPhotonMapSize ) / log( 2.0f ) ) ); CreateVertexBuffer(); g_bRunGenerateCaustics = true; } break; // Change the size of the snippet case 'K': g_fSnippetSize -= bAltDown ? 0.1f : 0.01f; if( g_fSnippetSize < 0 ) g_fSnippetSize = 0; g_HUD.GetSlider( IDC_SNIPPET_SIZE_SLIDER )->SetValue( (int)g_fSnippetSize * 100 ); CreateVertexBuffer(); g_bRunGenerateCaustics = true; break; case 'L': g_fSnippetSize += bAltDown ? 0.1f : 0.01f; if( (int)g_fSnippetSize > SNIPPET_MAX_SIZE ) g_fSnippetSize = SNIPPET_MAX_SIZE; g_HUD.GetSlider( IDC_SNIPPET_SIZE_SLIDER )->SetValue( (int)g_fSnippetSize * 100 ); CreateVertexBuffer(); g_bRunGenerateCaustics = true; break; // Move CenterObject / Light Source case VK_RIGHT: movement.x += STEP; break; case VK_LEFT: movement.x -= STEP; break; case VK_UP: movement.z += STEP; break; case VK_DOWN: movement.z -= STEP; break; case VK_PRIOR: movement.y += STEP; break; case VK_NEXT: movement.y -= STEP; break; } // Move Light Source if (bAltDown) { g_vLightPos += movement; } // Move CenterObject else { g_vCenterObjectPos += movement; // Refresh scaled World matrix of Center Mesh g_mWorldCenterObject = ScaleAndOffset(g_fCenterObjectSize, g_vCenterObjectPos); } } } //-------------------------------------------------------------------------------------- // Handles the GUI events //-------------------------------------------------------------------------------------- void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl ) { switch( nControlID ) { case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break; case IDC_TOGGLEREF: DXUTToggleREF(); break; case IDC_CHANGEDEVICE: DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break; case IDC_NUMBER_OF_ITERATION_SLIDER: g_iNumberOfIteration = g_HUD.GetSlider( IDC_NUMBER_OF_ITERATION_SLIDER )->GetValue(); break; case IDC_FRESNEL_FACTOR_SLIDER: g_fFresnelFactor = g_HUD.GetSlider( IDC_FRESNEL_FACTOR_SLIDER )->GetValue() / 100.0f; break; case IDC_REFRACTION_INDEX_SLIDER: g_fRefractionIndex = g_HUD.GetSlider( IDC_REFRACTION_INDEX_SLIDER )->GetValue() / 100.0f; break; case IDC_SHADOW_INTENSITY_SLIDER: g_fShadowIntensity = g_HUD.GetSlider( IDC_SHADOW_INTENSITY_SLIDER )->GetValue() / 100.0f; break; case IDC_CAUSTICS_INTENSITY_SLIDER: //g_fCausticsIntensity = g_HUD.GetSlider( IDC_CAUSTICS_INTENSITY_SLIDER )->GetValue() / 100.0f; g_fCausticsIntensity = pow ( 1.2f, g_HUD.GetSlider( IDC_CAUSTICS_INTENSITY_SLIDER )->GetValue() / 100.0f ); break; case IDC_SHADOW_CHECK_BOX: g_bShadowON = ( g_HUD.GetCheckBox( IDC_SHADOW_CHECK_BOX )->GetChecked() ); break; case IDC_CAUSTICS_CHECK_BOX: g_bCausticsON = (g_HUD.GetCheckBox( IDC_CAUSTICS_CHECK_BOX )->GetChecked() ); break; case IDC_CENTEROBJ_CHECK_BOX: g_bRenderCenterObjectWithBrdfON = ( g_HUD.GetCheckBox( IDC_CENTEROBJ_CHECK_BOX )->GetChecked() ); break; case IDC_SNIPPET_SIZE_IS_CONSTANT_CHECK_BOX: g_bSnippetSizeIsConstant = ( g_HUD.GetCheckBox( IDC_SNIPPET_SIZE_IS_CONSTANT_CHECK_BOX )->GetChecked() ); CreateVertexBuffer(); break; case IDC_SHOW_PHOTON_MAP_CHECK_BOX: g_bShowPhotonMap = ( g_HUD.GetCheckBox( IDC_SHOW_PHOTON_MAP_CHECK_BOX )->GetChecked() ); break; case IDC_CLASSIC_METHOD: case IDC_DISTANCE_IMPOSTOR_METHOD: if ( g_HUD.GetRadioButton( IDC_DISTANCE_IMPOSTOR_METHOD )->GetChecked() ) g_iAlgorithmMethod = 1; else g_iAlgorithmMethod = 0; break; case IDC_PHOTON_MAP_SIZE_SLIDER: g_iPhotonMapSize = (int)pow( 2.0f, g_HUD.GetSlider( IDC_PHOTON_MAP_SIZE_SLIDER )->GetValue() ); CreateVertexBuffer(); break; case IDC_SNIPPET_SIZE_SLIDER: g_fSnippetSize = g_HUD.GetSlider( IDC_SNIPPET_SIZE_SLIDER )->GetValue() / 100.0f; CreateVertexBuffer(); break; case IDC_RESET_PARAMETERS_BUTTON: // Reset the parameters of the algorithm g_bShadowON = true; g_bCausticsON = true; g_bRenderCenterObjectWithBrdfON = true; g_bShowPhotonMap = true; g_fFresnelFactor = 0.05f; g_fRefractionIndex = 0.9f; g_fShadowIntensity = 0.25f; g_fCausticsIntensity = 0.05f; g_fSnippetSize = 3.0f; g_iNumberOfIteration = 10; g_iAlgorithmMethod = 1; g_iPhotonMapSize = 64; // Reset the HUD g_HUD.GetCheckBox( IDC_SHADOW_CHECK_BOX )->SetChecked( g_bShadowON ); g_HUD.GetCheckBox( IDC_CAUSTICS_CHECK_BOX )->SetChecked( g_bCausticsON ); g_HUD.GetCheckBox( IDC_CENTEROBJ_CHECK_BOX )->SetChecked( g_bRenderCenterObjectWithBrdfON ); g_HUD.GetCheckBox( IDC_SNIPPET_SIZE_IS_CONSTANT_CHECK_BOX )->SetChecked( g_bSnippetSizeIsConstant ); g_HUD.GetCheckBox( IDC_SHOW_PHOTON_MAP_CHECK_BOX )->SetChecked( g_bShowPhotonMap ); g_HUD.GetRadioButton( IDC_DISTANCE_IMPOSTOR_METHOD )->SetChecked( true ); g_HUD.GetSlider( IDC_NUMBER_OF_ITERATION_SLIDER )->SetValue( g_iNumberOfIteration ); g_HUD.GetSlider( IDC_FRESNEL_FACTOR_SLIDER )->SetValue( (int)( g_fFresnelFactor * 100 ) ); g_HUD.GetSlider( IDC_REFRACTION_INDEX_SLIDER )->SetValue( (int)( g_fRefractionIndex * 100 + 1 ) ); g_HUD.GetSlider( IDC_SHADOW_INTENSITY_SLIDER )->SetValue( (int)( g_fShadowIntensity * 100 ) ); g_HUD.GetSlider( IDC_CAUSTICS_INTENSITY_SLIDER )->SetValue( (int)( ( log( g_fCausticsIntensity ) / log ( 1.2f ) ) * 100.0f ) ); g_HUD.GetSlider( IDC_SNIPPET_SIZE_SLIDER )->SetValue( (int)g_fSnippetSize * 100 ); g_HUD.GetSlider( IDC_PHOTON_MAP_SIZE_SLIDER )->SetValue( (int)( log( (float)g_iPhotonMapSize ) / log( 2.0f ) ) ); CreateVertexBuffer(); g_bRunGenerateCaustics = true; break; } // Regenerate caustics to show changes g_bRunGenerateCaustics = true; } //-------------------------------------------------------------------------------------- // This callback function will be called immediately after the Direct3D device has // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created // in the OnResetDevice callback should be released here, which generally includes all // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for // information about lost devices. //-------------------------------------------------------------------------------------- void CALLBACK OnLostDevice() { if( g_pFont ) g_pFont->OnLostDevice(); if( g_pEffect ) g_pEffect->OnLostDevice(); SAFE_RELEASE( g_pTextSprite ); SAFE_RELEASE( g_pRoomCubeMapColorDistTexture ); SAFE_RELEASE( g_pPowerOfSnippetTexelTexture ); SAFE_RELEASE( g_pRoomCubeMapUVTexture ); SAFE_RELEASE( g_pShadowMapTexture ); SAFE_RELEASE( g_pRoomLastTexture ); SAFE_RELEASE( g_pRoomModifyTexture ); SAFE_RELEASE( g_pPhotonUVTexture ); SAFE_RELEASE( g_pRoomTexture ); for(int i = 0; i < 4; i++) { SAFE_RELEASE( g_pColumnModifyTexture[i] ); } for(int i = 0; i < 5; i++) { SAFE_RELEASE( g_pColumnLastTexture[i] ); } SAFE_RELEASE( g_pDepthStencilSurface ); SAFE_RELEASE( g_pRoomCubeMapDepthStencilSurface ); SAFE_RELEASE( g_pShadowMapDepthStencilSSurface ); SAFE_RELEASE( g_pPhotonUVMapSurface ); SAFE_RELEASE( g_pShadowMapSurface ); SAFE_RELEASE( g_pPhotonMapDepthStencilSurface ); SAFE_RELEASE( g_pRoomLastSurface ); SAFE_RELEASE( g_pRoomModifySurface ); SAFE_RELEASE( g_pRoomSurface ); for(int i = 0; i < 4; i++) { SAFE_RELEASE( g_pColumnsModifySurface[i] ); } for(int i = 0; i < 5; i++) { SAFE_RELEASE( g_pColumnsLastSurface[i] ); } SAFE_RELEASE( g_pFullScreenQuadVertexDeclaration ); SAFE_RELEASE( g_pFullScreenQuadVertexBuffer ); SAFE_RELEASE( g_pSnippetVertexDeclaration ); SAFE_RELEASE( g_bSnippetVertexBuffer ); } //-------------------------------------------------------------------------------------- // This callback function will be called immediately after the Direct3D device has // been destroyed, which generally happens as a result of application termination or // windowed/full screen toggles. Resources created in the OnCreateDevice callback // should be released here, which generally includes all D3DPOOL_MANAGED resources. //-------------------------------------------------------------------------------------- void CALLBACK OnDestroyDevice() { SAFE_RELEASE( g_pFullScreenQuadVertexDeclaration ); SAFE_RELEASE( g_pFullScreenQuadVertexBuffer ); SAFE_RELEASE( g_pSnippetVertexDeclaration ); SAFE_RELEASE( g_bSnippetVertexBuffer ); SAFE_RELEASE( g_pCenterObjectMesh ); SAFE_RELEASE( g_pColumnMesh ); SAFE_RELEASE( g_pLightMesh ); SAFE_RELEASE( g_pRoomMesh ); SAFE_RELEASE( g_pEffect ); SAFE_RELEASE( g_pFont ); }