#include "Main.h" ShadowMap::ShadowMap() { _DepthStencil = NULL; } ShadowMap::~ShadowMap() { FreeMemory(); } void ShadowMap::FreeMemory() { for(UINT Index = 0; Index < ShadowMapCount; Index++) { _DepthMapTextures[Index].FreeMemory(); } _DepthMapBlurTexture.FreeMemory(); if(_DepthStencil != NULL) { _DepthStencil->Release(); _DepthStencil = NULL; } _VShaderCreate.FreeMemory(); _PShaderCreate.FreeMemory(); _VShaderRender.FreeMemory(); _PShaderRender.FreeMemory(); _VShaderGaussian.FreeMemory(); _PShaderGaussianX.FreeMemory(); _PShaderGaussianY.FreeMemory(); } void ShadowMap::SetAsRenderTarget(UINT ShadowMapIndex, IDirect3DDevice9 *Device) { _DepthMapTextures[ShadowMapIndex].SetAsRenderTarget(0); Device->SetDepthStencilSurface(_DepthStencil); Device->Clear( 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 255, 0, 0), 1.0f, 0 ); _VShaderCreate.Set(); _PShaderCreate.Set(); } void ShadowMap::SetAsTextures(IDirect3DDevice9 *Device) { for(UINT ShadowMapIndex = 0; ShadowMapIndex < ShadowMapCount; ShadowMapIndex++) { _DepthMapTextures[ShadowMapIndex].Set(ShadowMapIndex + 1); } _VShaderRender.Set(); _PShaderRender.Set(); } void ShadowMap::SetCameraMatrices(const MatrixController &MC, ShadowMapShaderType Shader) { if(Shader == ShadowMapShaderCreate) { Matrix4 WorldView = MC.World * MC.View; Matrix4 WorldViewProj = WorldView * MC.Perspective; _VShaderCreate.SetMatrix("WorldView", WorldView); _VShaderCreate.SetMatrix("WorldViewProj", WorldViewProj); } else if(Shader == ShadowMapShaderRender) { _VShaderRender.SetMatrix("World", MC.World); _VShaderRender.SetMatrix("WorldViewProj", MC.TotalMatrix()); } } void ShadowMap::SetLightMatrices(UINT LightIndex, const Camera &LightCamera, const Matrix4 &Perspective) { Matrix4 View = LightCamera.Matrix(); Matrix4 ViewProj = View * Perspective; _StringLightView[_StringLightView.Length() - 1] = '0' + LightIndex; _StringLightViewProj[_StringLightViewProj.Length() - 1] = '0' + LightIndex; _StringLightDir[_StringLightDir.Length() - 1] = '0' + LightIndex; _VShaderRender.SetMatrix(_StringLightView.CString(), View); _VShaderRender.SetMatrix(_StringLightViewProj.CString(), ViewProj); _PShaderRender.SetVec3(_StringLightDir.CString(), LightCamera.VecLookDir()); if(LightIndex == 0) { _PShaderRender.SetVec3("LightPos", LightCamera.VecEye()); } } void ShadowMap::Init(D3D9GraphicsDevice &GD, UINT Resolution) { FreeMemory(); _StringLightDir = "LightDir0"; _StringLightView = "LightView0"; _StringLightViewProj = "LightViewProj0"; for(UINT Index = 0; Index < ShadowMapCount; Index++) { _DepthMapTextures[Index].Init(GD); _DepthMapTextures[Index].Allocate(D3DFMT_G32R32F, Resolution, Resolution, true, 1); } _DepthMapBlurTexture.Init(GD); _DepthMapBlurTexture.Allocate(D3DFMT_G32R32F, Resolution, Resolution, true, 1); D3DAlwaysValidate( GD.GetDevice()->CreateDepthStencilSurface(Resolution, Resolution, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, TRUE, &_DepthStencil, NULL), "CreateDepthStencilSurface" ); _VShaderCreate.Init(GD, "Assets\\ShadowMapCreate.vs"); _PShaderCreate.Init(GD, "Assets\\ShadowMapCreate.ps"); _VShaderRender.Init(GD, "Assets\\ShadowMapRender.vs"); _PShaderRender.Init(GD, "Assets\\ShadowMapRender.ps"); _VShaderGaussian.Init(GD, "Assets\\GaussianBlur.vs"); _PShaderGaussianX.Init(GD, "Assets\\GaussianBlurX.ps"); _PShaderGaussianY.Init(GD, "Assets\\GaussianBlurY.ps"); _SimpleQuadMesh.SetGD(GD); _SimpleQuadMesh.CreateCanonicalRenderPlane(); } void LoadChannel(const Grid &Input, Grid &Output) { Output.Allocate(Input.Rows(), Input.Cols()); for(UINT Row = 0; Row < Input.Rows(); Row++) { for(UINT Col = 0; Col < Input.Cols(); Col++) { Output(Row, Col) = Input(Row, Col).x; } } } void ShadowMap::SaveTextureToFile(D3D9Texture &T, const String &Filename) { Grid Data; Grid SingleChannel; Bitmap Bmp; T.ReadData(Data); LoadChannel(Data, SingleChannel); Bmp.LoadGrid(SingleChannel); Bmp.SavePNG(Filename); } void ShadowMap::BlurAllShadowMaps(IDirect3DDevice9 *Device) { const bool DumpShadowMap = false; const UINT DumpShadowMapIndex = 1; D3D9ProtectRenderTarget Protector(Device, true, true); if(DumpShadowMap) { SaveTextureToFile(_DepthMapTextures[DumpShadowMapIndex], "Input.png"); } Device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); for(UINT Index = 0; Index < ShadowMapCount; Index++) { _DepthMapTextures[Index].Set(0); _DepthMapBlurTexture.SetAsRenderTarget(0); Device->SetDepthStencilSurface(_DepthStencil); _VShaderGaussian.Set(); _PShaderGaussianX.Set(); _SimpleQuadMesh.Render(); if(DumpShadowMap && Index == DumpShadowMapIndex) { SaveTextureToFile(_DepthMapBlurTexture, "Intermediate.png"); } _DepthMapTextures[Index].SetAsRenderTarget(0); _DepthMapBlurTexture.Set(0); _PShaderGaussianY.Set(); _SimpleQuadMesh.Render(); if(DumpShadowMap && Index == DumpShadowMapIndex) { SaveTextureToFile(_DepthMapTextures[DumpShadowMapIndex], "Output.png"); } Device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); } /*Console::File() << "Start\n"; for(UINT Row = 0; Row < Data0.Rows(); Row++) { for(UINT Col = 0; Col < Data0.Cols(); Col++) { if(Data0.GetElement(Row, Col).x - Data1.GetElement(Row, Col).x != 0.0f) { Console::File() << Data0.GetElement(Row, Col).x << '\t' << Data1.GetElement(Row, Col).x << endl; } } } Console::File() << "End\n";*/ } void ShadowMap::SaveDebugBitmap(const String &Filename) { Grid Data; Bitmap Bmp; _DepthMapTextures[0].ReadData(Data); Bmp.LoadGrid(Data); Bmp.SavePNG(Filename); }