206 lines
6.8 KiB
C++
206 lines
6.8 KiB
C++
#ifndef ShadowMapManager_h__
|
|
#define ShadowMapManager_h__
|
|
|
|
#include "render/IRenderer.h"
|
|
#include <vector>
|
|
#include "math/Vector4D.h"
|
|
#include "math/Vector2D.h"
|
|
#include "Rectangle2D.h"
|
|
#include "math/Matrix4x4.h"
|
|
#include "Light.h"
|
|
#include "Globals.h"
|
|
#include <float.h>
|
|
|
|
namespace LifeGraphics
|
|
{
|
|
struct SHADOW_DATA
|
|
{
|
|
LifeMath::float4 uvOffset_uvScale;
|
|
LifeMath::float4 shadowMapTexelSize_dummy;
|
|
};
|
|
|
|
class ShadowMapManager
|
|
{
|
|
private:
|
|
IRenderer* renderer;
|
|
int shadowMapResolution;
|
|
std::vector<LifeMath::float4> texRegions;
|
|
std::vector<LifeMath::Rect2i> 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__
|