I have been implementing soft shadows into my game engine and it all looks ok in the beginning, but when I rotate the camera I get this...
https://puu.sh/rQ7yG/8cd692aaab.png
When I move around I also see that the shadow is offset from the model...
https://puu.sh/rQ7B9/6f988749d9.png
Has anyone seen this before or would be able to find out what the issue is? I think it has something to do with the view matrix of the camera or something like that?
For my soft shadows I do 5 passes:
- Render the scene from the cameras POV to a texture
- Render that texture as black and white
- Downscale the black and white texture to half its size
- Blur the downscaled texture (blurring the shadows edges)
- Upscale the blurred texture back to normal size
I have checked back and all the matrices get updated per frame
Please ask to see any code and I will gladly edit this post with it.
EDIT: Added code
Render Light To Texture
bool CGraphics::RenderToTexture()
{
D3DXMATRIX worldMatrix,lightViewMatrix,lightProjMatrix;
bool result;
CMesh* tempMesh = nullptr;
m_ToTexture->SetRenderTarget(m_Device->GetDeviceContext());
m_ToTexture->ClearRenderTarget(m_Device->GetDeviceContext(), 0.0f,0.0f,1.0f,1.0f);
m_PointLights[0]->GenerateViewMatrix();
m_Device->GetWorldMatrix(worldMatrix);
m_PointLights[0]->GetViewMatrix(lightViewMatrix);
m_PointLights[0]->GetProjMatrix(lightProjMatrix);
for(int i = 0;i<m_NumModels;i++)
{
D3DXVECTOR3 tempPos = m_Models[i]->GetPosition();
D3DXMatrixTranslation(&worldMatrix,tempPos.x,tempPos.y,tempPos.z);
result = true;//m_Frustrum->CheckSphere(position.x,position.y,position.z,2.0f);
if(result)
{
m_Models[i]->GetMatrix(worldMatrix);
tempMesh = m_Models[i]->GetMesh();
tempMesh->Render(m_Device->GetDeviceContext());
result = m_DepthShader->Render(m_Device->GetDeviceContext(),tempMesh->GetIndexCount(),
worldMatrix,lightViewMatrix,lightProjMatrix);
if(!result) return false;
m_Device->GetWorldMatrix(worldMatrix);
}
}
m_Device->SetBackBufferTarget();
m_Device->ResetViewport();
return true;
}
Render the shadows in black and white
bool CGraphics::RenderBW()
{
D3DXMATRIX worldMatrix,viewMatrix,projMatrix,lightViewMatrix,lightProjMatrix;
bool result;
CMesh* tempMesh = nullptr;
m_BWTexture->SetRenderTarget(m_Device->GetDeviceContext());
m_BWTexture->ClearRenderTarget(m_Device->GetDeviceContext(),0.0f,0.0f,1.0f,1.0f);
m_Cameras[0]->Update();
m_PointLights[0]->GenerateViewMatrix();
m_Cameras[0]->GetViewMatrix(viewMatrix);
m_Device->GetWorldMatrix(worldMatrix);
m_Device->GetProjMatrix(projMatrix);
m_PointLights[0]->GetViewMatrix(lightViewMatrix);
m_PointLights[0]->GetProjMatrix(lightProjMatrix);
for(int i = 0;i<m_NumModels;i++)
{
D3DXVECTOR3 tempPos = m_Models[i]->GetPosition();
D3DXMatrixTranslation(&worldMatrix,tempPos.x,tempPos.y,tempPos.z);
result = true;//m_Frustrum->CheckSphere(position.x,position.y,position.z,2.0f);
if(result)
{
m_Models[i]->GetMatrix(worldMatrix);
tempMesh = m_Models[i]->GetMesh();
tempMesh->Render(m_Device->GetDeviceContext());
result = m_ShadowShader->Render(m_Device->GetDeviceContext(),tempMesh->GetIndexCount(),
worldMatrix,viewMatrix,projMatrix,lightViewMatrix,lightProjMatrix,
m_ToTexture->GetShaderResourceView(),m_PointLights[0]->GetPosition());
if(!result) return false;
m_Device->GetWorldMatrix(worldMatrix);
}
}
m_Device->SetBackBufferTarget();
m_Device->ResetViewport();
return true;
}
Downscale the texture to half
bool CGraphics::DownScale()
{
D3DXMATRIX worldMatrix,baseViewMatrix,orthoMatrix;
bool result;
m_DownScale->SetRenderTarget(m_Device->GetDeviceContext());
m_DownScale->ClearRenderTarget(m_Device->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f);
m_Cameras[0]->Update();
m_Device->GetWorldMatrix(worldMatrix);
m_Cameras[0]->GetBaseViewMatrix(baseViewMatrix);
// Get the ortho matrix from the render to texture since texture has different dimensions being that it is smaller.
m_DownScale->GetOrthoMatrix(orthoMatrix);
m_Device->ZBufferOff();
m_DownSampleWindow->Render(m_Device->GetDeviceContext());
result = m_TextureShader->Render(m_Device->GetDeviceContext(),m_DownSampleWindow->GetIndexCount(),
worldMatrix,baseViewMatrix,orthoMatrix,m_BWTexture->GetShaderResourceView());
m_Device->ZBufferOn();
m_Device->SetBackBufferTarget();
m_Device->ResetViewport();
return true;
}
Blur Width
bool CGraphics::BlurTextureX()
{
D3DXMATRIX worldMatrix,baseViewMatrix,orthoMatrix;
float screenX;
bool result;
screenX = (float)(SHADOWMAP_WIDTH / 2);
m_BlurTextureX->SetRenderTarget(m_Device->GetDeviceContext());
m_BlurTextureX->ClearRenderTarget(m_Device->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f);
m_Cameras[0]->Update();
m_Cameras[0]->GetBaseViewMatrix(baseViewMatrix);
m_Device->GetWorldMatrix(worldMatrix);
m_BlurTextureX->GetOrthoMatrix(orthoMatrix);
m_Device->ZBufferOff();
m_DownSampleWindow->Render(m_Device->GetDeviceContext());
// Render the small ortho window using the horizontal blur shader and the down sampled render to texture resource.
result = m_BlurShaderX->Render(m_Device->GetDeviceContext(),m_DownSampleWindow->GetIndexCount(),worldMatrix,baseViewMatrix,orthoMatrix,
m_DownScale->GetShaderResourceView(),screenX);
if(!result) return false;
m_Device->ZBufferOn();
m_Device->SetBackBufferTarget();
m_Device->ResetViewport();
return true;
}
Blur Height
bool CGraphics::BlurTextureY()
{
D3DXMATRIX worldMatrix,baseViewMatrix,orthoMatrix;
float screenY;
bool result;
screenY = (float)(SHADOWMAP_HEIGHT / 2);
m_BlurTextureY->SetRenderTarget(m_Device->GetDeviceContext());
m_BlurTextureY->ClearRenderTarget(m_Device->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f);
m_Cameras[0]->Update();
m_Cameras[0]->GetBaseViewMatrix(baseViewMatrix);
m_Device->GetWorldMatrix(worldMatrix);
m_BlurTextureY->GetOrthoMatrix(orthoMatrix);
m_Device->ZBufferOff();
m_DownSampleWindow->Render(m_Device->GetDeviceContext());
// Render the small ortho window using the horizontal blur shader and the down sampled render to texture resource.
result = m_BlurShaderY->Render(m_Device->GetDeviceContext(),m_DownSampleWindow->GetIndexCount(),worldMatrix,baseViewMatrix,orthoMatrix,
m_BlurTextureX->GetShaderResourceView(),screenY);
if(!result) return false;
m_Device->ZBufferOn();
m_Device->SetBackBufferTarget();
m_Device->ResetViewport();
return true;
}
Rescale to full size
bool CGraphics::UpScale()
{
D3DXMATRIX worldMatrix,baseViewMatrix,orthoMatrix;
bool result;
m_UpScale->SetRenderTarget(m_Device->GetDeviceContext());
m_UpScale->ClearRenderTarget(m_Device->GetDeviceContext(),0.0f,0.0f,0.0f,1.0f);
m_Cameras[0]->GetBaseViewMatrix(baseViewMatrix);
m_Device->GetWorldMatrix(worldMatrix);
// Get the ortho matrix from the render to texture since texture has different dimensions.
m_UpScale->GetOrthoMatrix(orthoMatrix);
m_Device->ZBufferOff();
m_FullScreenWindow->Render(m_Device->GetDeviceContext());
// Render the full screen ortho window using the texture shader and the small sized final blurred render to texture resource.
result = m_TextureShader->Render(m_Device->GetDeviceContext(),m_FullScreenWindow->GetIndexCount(),
worldMatrix,baseViewMatrix,orthoMatrix,m_BlurTextureY->GetShaderResourceView());
if(!result) return false;
m_Device->ZBufferOn();
m_Device->SetBackBufferTarget();
m_Device->ResetViewport();
return true;
}
Here is also the camera functions
void CCamera::Update()
{
D3DXVECTOR3 up, pos, lookAt;
float yaw, pitch, roll;
D3DXMATRIX rotationMatrix;
//Setup upward vector
up.x = 0.0f;
up.y = 1.0f;
up.z = 0.0f;
//Set position
pos.x = m_Pos.x;
pos.y = m_Pos.y;
pos.z = m_Pos.z;
//Set default look direction
lookAt.x = 0.0f;
lookAt.y = 0.0f;
lookAt.z = 1.0f;
//Set rotations
pitch = m_Rot.x * 0.0174532925f;
yaw = m_Rot.y * 0.0174532925f;
roll = m_Rot.z * 0.0174532925f;
//Create rotation matrix
D3DXMatrixRotationYawPitchRoll(&rotationMatrix, yaw, pitch, roll);
//Transform into rotation matrix
D3DXVec3TransformCoord(&up, &up, &rotationMatrix);
D3DXVec3TransformCoord(&lookAt, &lookAt, &rotationMatrix);
//Translate rotated camera to location of the viewer
lookAt = pos + lookAt;
//Create the view matrix
D3DXMatrixLookAtLH(&m_ViewMatrix, &pos, &lookAt, &up);
}
void CCamera::RenderBaseViewMatrix()
{
D3DXVECTOR3 up,position,lookAt;
float radians;
// Setup the vector that points upwards.
up.x = 0.0f;
up.y = 1.0f;
up.z = 0.0f;
// Setup the position of the camera in the world.
position.x = m_Pos.x;
position.y = m_Pos.y;
position.z = m_Pos.z;
// Calculate the rotation in radians.
radians = m_Rot.y * 0.0174532925f;
// Setup where the camera is looking.
lookAt.x = sinf(radians) + m_Pos.x;
lookAt.y = m_Pos.y;
lookAt.z = cosf(radians) + m_Pos.z;
// Create the base view matrix from the three vectors.
D3DXMatrixLookAtLH(&m_BaseViewMatrix,&position,&lookAt,&up);
}
Anything else?