#ifndef ShadowMapManager_h__ #define ShadowMapManager_h__ #include "render/IRenderer.h" #include #include "math/Vector4D.h" #include "math/Vector2D.h" #include "Rectangle2D.h" #include "math/Matrix4x4.h" #include "Light.h" #include "Globals.h" #include namespace LifeGraphics { struct SHADOW_DATA { LifeMath::float4 uvOffset_uvScale; LifeMath::float4 shadowMapTexelSize_dummy; }; class ShadowMapManager { private: IRenderer* renderer; int shadowMapResolution; std::vector texRegions; std::vector viewRegions; ITexture2D* depthBuffer; ITexture2D* shadowBuffer; IBlendState* restoreBlendState; LifeMath::float4x4 lightMatrices[4]; int curLightIndex; IBlendState* shadowBlendState; void ComputeDepthRegionDistribution(int lightCount) { texRegions.clear(); viewRegions.clear(); printf("SHOULD FIX RECTANGLES!!!!!!!!!!!!!!!!!!!!! NOT COORD! WIDTH!!!!!!!!!!!!!!! ComputeDepthRegionDistribution\n"); switch (lightCount) { case 1: //----------| //| | //| 1 | //| | //| | //----------| texRegions.push_back(LifeMath::float4(0.0f, 0.0f, 1.0f, 1.0f)); viewRegions.push_back(LifeMath::Rect2i(0, 0, shadowMapResolution, shadowMapResolution)); break; case 2: //----------| //| 1 | //| | //----------- //| | //| 2 | //----------| /*texRegions.push_back(LifeMath::float4(0.0f, 0.0f, 1.0f, 0.5f)); viewRegions.push_back(Rectangle2D(0.0f, 0.0f, shadowMapResolution2, shadowMapResolution2 / 2)); texRegions.push_back(LifeMath::float4(0.0f, 0.5f, 1.0f, 0.5f)); viewRegions.push_back(Rectangle2D(0.0f, shadowMapResolution2 / 2, shadowMapResolution2, shadowMapResolution2 / 2));*/ texRegions.push_back(LifeMath::float4(0.0f, 0.0f, 1.0f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(0, 0, shadowMapResolution, shadowMapResolution / 2)); texRegions.push_back(LifeMath::float4(0.0f, 0.5f, 1.0f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(0, shadowMapResolution / 2, shadowMapResolution, shadowMapResolution)); break; case 3: texRegions.push_back(LifeMath::float4(0.0f, 0.0f, 1.0f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(0, 0, shadowMapResolution, shadowMapResolution / 2)); texRegions.push_back(LifeMath::float4(0.0f, 0.5f, 0.5f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(0, shadowMapResolution / 2, shadowMapResolution / 2, shadowMapResolution)); texRegions.push_back(LifeMath::float4(0.5f, 0.5f, 0.5f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(shadowMapResolution / 2, shadowMapResolution / 2, shadowMapResolution, shadowMapResolution)); break; case 4: texRegions.push_back(LifeMath::float4(0.0f, 0.0f, 0.5f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(0, 0, shadowMapResolution / 2, shadowMapResolution / 2)); texRegions.push_back(LifeMath::float4(0.5f, 0.0f, 0.5f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(shadowMapResolution / 2, 0, shadowMapResolution / 2, shadowMapResolution / 2)); texRegions.push_back(LifeMath::float4(0.0f, 0.5f, 0.5f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(0, shadowMapResolution / 2, shadowMapResolution / 2, shadowMapResolution / 2)); texRegions.push_back(LifeMath::float4(0.5f, 0.5f, 0.5f, 0.5f)); viewRegions.push_back(LifeMath::Rect2i(shadowMapResolution / 2, shadowMapResolution / 2, shadowMapResolution / 2, shadowMapResolution / 2)); break; } } public: IDepthStencilState* depthState; IShader* rtdPs; IShader* rtdPsAT; IShader* rtdCubePs; IShader* rtdCubePsAT; ITextureSampler* samplerPCF; ShadowMapManager() :shadowMapResolution(1024) { for(int i = 0; i<4; i++) { texRegions.push_back(LifeMath::float4(1.0f, 1.0f, 1.0f, 1.0f)); } } ~ShadowMapManager() { SAFE_DELETE(depthBuffer); SAFE_DELETE(rtdPs); SAFE_DELETE(shadowBlendState); SAFE_DELETE(depthState); } SHADOW_DATA getShadowInfo(int id) { SHADOW_DATA data; data.uvOffset_uvScale = texRegions[id]; data.shadowMapTexelSize_dummy.X = (float)shadowMapResolution; data.shadowMapTexelSize_dummy.Y = (float)shadowMapResolution; return data; } void beginShadowRendering(int lightCount) { renderer->SetScissorRectangle(LifeMath::Rect2i(0, 0, shadowMapResolution, shadowMapResolution)); curLightIndex = 0; if (lightCount > 0) { if (lightCount > 4) lightCount = 4; ComputeDepthRegionDistribution(lightCount); } renderer->UnbindResourcesPS(); renderer->SetTargets(shadowBuffer, depthBuffer); LifeMath::float4 color = LifeMath::float4(1.0f, 1.0f, 1.0f, 1.0f); renderer->ClearDepthStencil(depthBuffer, 1.0f, 0); //renderer->ClearBuffers(CF_DEPTH_BUFFER, 0x00000000, 1.0f, 0); // renderer->ClearRenderTarget(shadowBuffer, &color); //renderer->SetBlendState(shadowBlendState); renderer->SetDepthStencilState(depthState); renderer->SetPSTextureSampler(samplerPCF, 2); //renderer->SetPixelShader(rtdPs); } void beginLightRender(Light* light) { lightMatrices[curLightIndex] = light->getMatrix(); // renderer->ClearBuffers(CF_DEPTH_BUFFER, 0x00000000, 1.0f, 0); renderer->SetViewport(viewRegions[curLightIndex]); //renderer->SetViewport(viewRegions[curLightIndex], 0, 100000000.0f); } void endLightRender() { curLightIndex++; } ITexture2D* getShadowMap() { return shadowBuffer; } void Init(IRenderer* _renderer) { renderer = _renderer; #define MAX_LINEAR_DEPTH 1.e30f /* ComparisonFunc = LESS; Filter = COMPARISON_MIN_MAG_LINEAR_MIP_POINT; AddressU = Border; AddressV = Border; BorderColor = float4(MAX_LINEAR_DEPTH, 0, 0, 0);*/ ISamplerDescription desc(Border, Border, Border, ComparisonMinMagLinearMipPoint, COMPARISON_LESS); samplerPCF = renderer->CreateTextureSampler(&desc); depthBuffer = CG::me()->GetRenderer()->CreateDepthTarget(shadowMapResolution, shadowMapResolution, FORMAT_R32_TYPELESS); shadowBuffer = CG::me()->GetRenderer()->CreateRenderTarget(shadowMapResolution, shadowMapResolution, FORMAT_R32_FLOAT); rtdPs = ResourceManager::me()->CompileUserShaderPS(String(_text("RTD_PCF.psh"))); rtdPsAT = ResourceManager::me()->CompileUserShaderPS(String(_text("RTD_PCF_AT.psh"))); rtdCubePs = ResourceManager::me()->CompileUserShaderPS(String(_text("RTD_PCF_CUBE.psh"))); rtdCubePsAT = ResourceManager::me()->CompileUserShaderPS(String(_text("RTD_PCF_AT.psh"))); shadowBlendState = CG::me()->GetRenderer()->CreateBlendState(false, false, BLEND_OP_ADD, BLEND_ZERO, BLEND_ONE, 0); restoreBlendState = CG::me()->GetRenderer()->CreateBlendState(true, false, BLEND_OP_ADD, BLEND_ONE, BLEND_ZERO, 1 | 2 | 4 | 8); depthState = renderer->CreateDSState(true, true, COMPARISON_LESS); } }; } #endif // ShadowMapManager_h__