1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
LPDIRECT3DSURFACE9 oldDepthSurface = NULL;
LPDIRECT3DSURFACE9 oldRenderTarget = NULL;
ShadowMap::ShadowMap(void)
{
//Create our Light
Vector3D lightPosition(20.0f, 2.9f, 10.0f);
Vector3D lightDirection;
Vector3DNormalize(&lightDirection,&lightPosition);
LightingManager::GetInstance()->AddSpotLight("Test",lightPosition, -lightDirection,Vector3D(0,0.5f,0.1f),10.0f,(D3DX_PI * 2) / 2,1.0f,1.0f,1,1,1,1);
}
ShadowMap::~ShadowMap(void)
{
//release the texture and surface
m_shadowMap->Release();
m_shadowMapSurface->Release();
oldDepthSurface = NULL;
oldRenderTarget = NULL;
}
void
ShadowMap::Create()
{
HRESULT hr;
//create our shadow map texture to the size of SHADOWMAP_SIZE, the texture contains one 32-bit channel within the default memory pool,
//the texture is stored within m_shadowMap
hr = m_D3DDevice->CreateTexture(SHADOWMAP_SIZE,SHADOWMAP_SIZE,1,D3DUSAGE_RENDERTARGET,D3DFMT_R32F,D3DPOOL_DEFAULT,&m_shadowMap,NULL);
//error checking
if(hr != S_OK)
{
ErrorMessage("Did not create shadow map texture");
}
//create the depth Stencil surface to the size of SHADOWMAP_SIZE to a 24bit depth, and no multisampling,
//the surface is stored in m_shadowMapSurface;
hr = m_D3DDevice->CreateDepthStencilSurface(SHADOWMAP_SIZE,SHADOWMAP_SIZE,D3DFMT_D24X8,D3DMULTISAMPLE_NONE,0,TRUE,&m_shadowMapSurface,NULL);
if(hr != S_OK)
{
ErrorMessage("Did not create shadow map surface");
}
//calculate the max projection of the scene
float maxProjection = D3DXVec3LengthSq(&LightingManager::GetInstance()->GetLight("Test")->GetPosition()) ;
//create the shadow projection matrix
D3DXMatrixPerspectiveFovLH( &m_shadowMatrix, D3DX_PI / 2, 1, 1.5f, maxProjection);
}
void
ShadowMap::RenderScene(bool renderShadow,const Matrix* view, const Matrix* Proj)
{
//Set the theta of the light to that of our spot light
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetFloat("m_CosTheta", cosf((D3DX_PI * 2) / 2));
//Set our Light Position
Vector3D lightPos = LightingManager::GetInstance()->GetLight("Test")->GetPosition();
//Create a Tempory Vector4D Variable
Vector4D tempVector4;
//Set the View And Projection matrices within the shader
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetMatrix("m_View", *view );
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetMatrix("m_Proj", *Proj);
m_view = *view;
m_proj = *Proj;
//Transform our light vector by our view matrix, place the result in tempVector4
D3DXVec3Transform( &tempVector4, &lightPos, view);
//Set our light position within our shader
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetVector4("m_LightPosition",tempVector4);
//Set our TempVector4 to our light direction
*(D3DXVECTOR3*)&tempVector4 = LightingManager::GetInstance()->GetLight("Test")->GetDirection();
//set our tempVector4.w to 0 as this will clear any tesserlation issues
tempVector4.w =0;
//transform the value within tempVector4 with our view
D3DXVec4Transform( &tempVector4, &tempVector4, view);
//Normalize it
Vector3DNormalize((D3DXVECTOR3*)&tempVector4,(D3DXVECTOR3*)&tempVector4);
//And place it within our shader
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetVector4("m_LightDirection",tempVector4);
//If we are rendering the Shadow, set our shaders technique to that
//else we set it to our scene render technique
if(renderShadow)
{
m_D3DDevice->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(255,0,255),1.0f,0);
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetTechnique("mTech1");
}
if(!renderShadow)
{
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetTechnique("mTech");
}
}
void
ShadowMap::SetUpDepthRender()
{
//Create a temp Render Target
//Get the current RenderTarget and place it within our temp Render Target
m_D3DDevice->GetRenderTarget( 0, &oldRenderTarget );
//Create a temp ShadowSurface
LPDIRECT3DSURFACE9 tempShadowSurface;
//The Texture takes a reference of the surface level of the tempShadowSurface
if( SUCCEEDED( m_shadowMap->GetSurfaceLevel( 0, &tempShadowSurface ) ) )
{
//it is set to target and released
m_D3DDevice->SetRenderTarget( 0, tempShadowSurface );
tempShadowSurface->Release() ;
}
//Store the current depth surface to the temp variable and set the stencil surface
//to our member surface
if( SUCCEEDED( m_D3DDevice->GetDepthStencilSurface( &oldDepthSurface ) ) )
m_D3DDevice->SetDepthStencilSurface( m_shadowMapSurface );
RenderScene( true, &LightingManager::GetInstance()->GetLight("Test")->GetView() ,&m_shadowMatrix);
}
void
ShadowMap::SetUpSceneRender()
{
//Set the now generated texture to our shader
EffectManager::GetInstance()->GetEffect("ShadowMap")->GetEffect()->SetTexture(EffectManager::GetInstance()->GetEffect("ShadowMap")->GetHandle("m_ShadowMap")->m_handle,m_shadowMap);
//if there is an old surface, set it back
if( oldDepthSurface )
{
m_D3DDevice->SetDepthStencilSurface( oldDepthSurface );
oldDepthSurface->Release();
}
//set the render target back to how it was before this process
m_D3DDevice->SetRenderTarget( 0, oldRenderTarget );
oldRenderTarget->Release();
//generate a view to light projection matrix to generate how the shadow will appear
Matrix viewToLightProj ;
//set our matrix to our camera view
viewToLightProj = CameraController::GetInstance()->GetView() ;
//Inverse it
MatrixInverse(&viewToLightProj,NULL,&viewToLightProj);
//Multiply it with out light view matrix
MatrixMultiply(&viewToLightProj,&viewToLightProj,&LightingManager::GetInstance()->GetLight("Test")->GetView());
//then our shadow matrix
MatrixMultiply(&viewToLightProj,&viewToLightProj,&m_shadowMatrix);
//apply to effect
EffectManager::GetInstance()->GetEffect("ShadowMap")->SetMatrix("m_VTLP",viewToLightProj);
//render scene, to render the environment this time
RenderScene(false, &CameraController::GetInstance()->GetView(),&CameraController::GetInstance()->GetProjection());
}
| |