软阴影会产生graphics错误

我已经在我的游戏引擎中实现了软阴影,并且一开始看起来都不错,但是当我旋转相机时,我得到了这个…
https://puu.sh/rQ7yG/8cd692aaab.png
当我四处走动的时候,我也看到阴影偏离了模型… https://puu.sh/rQ7B9/6f988749d9.png

有没有人看过这个,或者能够找出问题是什么? 我认为这与相机的视图matrix或类似的东西有关?

为了我的软阴影,我做了5遍:

  1. 将相机POV中的场景渲染为纹理
  2. 呈现黑色和白色的纹理
  3. 将黑白纹理缩减至其一半的大小
  4. 模糊缩小的纹理(模糊阴影边缘)
  5. 将模糊的纹理高级缩放到正常大小

我已经检查过,所有的matrix每帧更新

请查看任何代码,我很乐意编辑这个post。

编辑:添加代码

回报轻的纹理

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; } 

以黑色和白色渲染阴影

 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; } 

将纹理缩小至一半

 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; } 

模糊宽度

 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; } 

模糊高度

 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; } 

重新调整到全尺寸

 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; } 

这里也是相机function

 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); } 

还要别的吗?

目前还不清楚在第3步中是否缩放了阴影图或阴影场景。

软阴影的一般过程:

  1. 从光的角度渲染场景到一个纹理(称为阴影贴图)

  2. 将“阴影场景”渲染成纹理(现在你有硬阴影)

  3. 缩小在步骤2)中创建的纹理,

  4. 应用模糊

  5. 高级模糊的图像,并使用模糊的纹理渲染最终的图像

你可以在gamedev.netfind更好/更长的描述。 你也可以使用不同的PCF函数来产生可接受的结果。 ( 另一篇文章有一些提示和技巧)。

编辑

无论如何,根据你的图片,这似乎是一个下调/高档问题。 除了DirectX之外,还必须在着色器中使用半像素偏移量。