#Bugfix: Shadows appeared to be rendered one frame too late

close #141

The problem was that the shadow matrices were setup in BeginFrame, but
GraphicsView calls SetCamera after BeginFrame. The solution was to move
the shadow matrix setup into CRenderer::SetCamera.

This caused a second problem because RenderReflections/RenderRefractions
used SetCamera to change the OpenGL matrices. Solved this problem by
distinguishing explicitly between the camera used for the scene as a
whole and the camera used to configure OpenGL. The latter can be a
virtual camera for shadow or reflection rendering and similar
render-to-texture effects.

This was SVN commit r4330.
This commit is contained in:
prefect 2006-09-14 20:06:21 +00:00
parent 1767fe0304
commit 09b87e84ec
5 changed files with 47 additions and 29 deletions

View File

@ -38,7 +38,8 @@ class CCamera
void SetProjection (CMatrix3D *proj) { m_ProjMat = *proj; }
void SetProjection (float nearp, float farp, float fov);
void SetProjectionTile (int tiles, int tile_x, int tile_y);
CMatrix3D GetProjection () { return m_ProjMat; }
CMatrix3D& GetProjection () { return m_ProjMat; }
const CMatrix3D& GetProjection () const { return m_ProjMat; }
// Updates the frustum planes. Should be called
// everytime the view or projection matrices are
@ -47,7 +48,7 @@ class CCamera
CFrustum GetFrustum () { return m_ViewFrustum; }
void SetViewPort (SViewPort *viewport);
SViewPort GetViewPort () { return m_ViewPort; }
const SViewPort& GetViewPort () const { return m_ViewPort; }
// getters
float GetNearPlane() const { return m_NearPlane; }

View File

@ -83,7 +83,7 @@ CGameView::CGameView(CGame *pGame):
m_ViewCamera.m_Orientation.RotateY(DEGTORAD(0));
m_ViewCamera.m_Orientation.Translate (100, 150, -100);
m_CullCamera = m_ViewCamera;
g_Renderer.SetCamera(m_ViewCamera, m_CullCamera);
g_Renderer.SetSceneCamera(m_ViewCamera, m_CullCamera);
m_UnitView=NULL;
m_UnitAttach=NULL;
@ -151,7 +151,7 @@ void CGameView::Render()
{
if (m_LockCullCamera == false)
m_CullCamera = m_ViewCamera;
g_Renderer.SetCamera(m_ViewCamera, m_CullCamera);
g_Renderer.SetSceneCamera(m_ViewCamera, m_CullCamera);
CheckLightEnv();

View File

@ -312,6 +312,26 @@ struct CRendererInternals
return true;
}
/**
* Load the OpenGL projection and modelview matrices and the viewport according
* to the given camera.
*/
void SetOpenGLCamera(const CCamera& camera)
{
CMatrix3D view;
camera.m_Orientation.GetInverse(view);
const CMatrix3D& proj = camera.GetProjection();
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(&proj._11);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&view._11);
const SViewPort &vp = camera.GetViewPort();
glViewport(vp.m_X,vp.m_Y,vp.m_Width,vp.m_Height);
}
};
///////////////////////////////////////////////////////////////////////////////////
@ -716,9 +736,6 @@ void CRenderer::BeginFrame()
// zero out all the per-frame stats
m_Stats.Reset();
// init per frame stuff
m->shadow->SetupFrame(m_CullCamera, m_LightEnv->GetSunDir());
// choose model renderers for this frame
int vertexType;
@ -959,7 +976,6 @@ void CRenderer::SetObliqueFrustumClipping(const CVector4D& cp, int sign)
CVector4D q;
// First, we'll convert the given clip plane to camera space, then we'll
// Get the view matrix and normal matrix (top 3x3 part of view matrix)
CMatrix3D viewMatrix;
m_ViewCamera.m_Orientation.GetInverse(viewMatrix);
@ -1046,7 +1062,8 @@ void CRenderer::RenderReflections()
CMatrix3D scaleMat;
scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
m_ViewCamera.m_ProjMat = scaleMat * m_ViewCamera.m_ProjMat;
SetCamera(m_ViewCamera, m_CullCamera);
m->SetOpenGLCamera(m_ViewCamera);
CVector4D camPlane(0, 1, 0, -wm.m_WaterHeight);
SetObliqueFrustumClipping(camPlane, -1);
@ -1082,7 +1099,9 @@ void CRenderer::RenderReflections()
wm.m_ReflectionTextureSize, wm.m_ReflectionTextureSize);
//Reset old camera and re-enable backface culling
SetCamera(normalCamera, m_CullCamera);
m_ViewCamera = normalCamera;
m->SetOpenGLCamera(m_ViewCamera);
glEnable(GL_CULL_FACE);
//glClearDepth(1);
//glClear(GL_DEPTH_BUFFER_BIT);
@ -1115,7 +1134,7 @@ void CRenderer::RenderRefractions()
CMatrix3D scaleMat;
scaleMat.SetScaling(m_Height/float(std::max(1, m_Width)), 1.0f, 1.0f);
m_ViewCamera.m_ProjMat = scaleMat * m_ViewCamera.m_ProjMat;
SetCamera(m_ViewCamera, m_CullCamera);
m->SetOpenGLCamera(m_ViewCamera);
CVector4D camPlane(0, 1, 0, -wm.m_WaterHeight);
SetObliqueFrustumClipping(camPlane, -1);
@ -1146,7 +1165,9 @@ void CRenderer::RenderRefractions()
wm.m_RefractionTextureSize, wm.m_RefractionTextureSize);
//Reset old camera and re-enable backface culling
SetCamera(normalCamera, m_CullCamera);
m_ViewCamera = normalCamera;
m->SetOpenGLCamera(m_ViewCamera);
glEnable(GL_CULL_FACE);
glClearDepth(1);
glDepthFunc(GL_LEQUAL);
@ -1159,6 +1180,9 @@ void CRenderer::FlushFrame()
{
oglCheck();
// Set the camera
m->SetOpenGLCamera(m_ViewCamera);
// Prepare model renderers
PROFILE_START("prepare models");
m->Model.Normal->PrepareModels();
@ -1319,25 +1343,18 @@ void CRenderer::DisplayFrustum()
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// SetCamera: setup projection and transform of camera and adjust viewport to current view
void CRenderer::SetCamera(const CCamera& viewCamera, const CCamera& cullCamera)
// SetSceneCamera: setup projection and transform of camera and adjust viewport to current view
// The camera always represents the actual camera used to render a scene, not any virtual camera
// used for shadow rendering or reflections.
void CRenderer::SetSceneCamera(const CCamera& viewCamera, const CCamera& cullCamera)
{
m_ViewCamera = viewCamera;
m_CullCamera = cullCamera;
CMatrix3D view;
m_ViewCamera.m_Orientation.GetInverse(view);
const CMatrix3D& proj = m_ViewCamera.GetProjection();
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(&proj._11);
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(&view._11);
SetViewport(m_ViewCamera.GetViewPort());
m->shadow->SetupFrame(m_CullCamera, m_LightEnv->GetSunDir());
}
void CRenderer::SetViewport(const SViewPort &vp)
{
glViewport(vp.m_X,vp.m_Y,vp.m_Width,vp.m_Height);

View File

@ -190,14 +190,14 @@ public:
int GetFrameCounter() const { return m_FrameCounter; }
/**
* SetCamera: Set up the camera used for subsequent rendering operations; this includes
* SetSceneCamera: Set up the camera used for the scene in this frame; this includes
* setting OpenGL state like viewport, projection and modelview matrices.
*
* @param viewCamera this camera determines the eye position for rendering
* @param culLCamera this camera determines the frustum for culling in the renderer and
* @param cullCamera this camera determines the frustum for culling in the renderer and
* for shadow calculations
*/
void SetCamera(const CCamera& viewCamera, const CCamera& cullCamera);
void SetSceneCamera(const CCamera& viewCamera, const CCamera& cullCamera);
// set the viewport
void SetViewport(const SViewPort &);

View File

@ -155,7 +155,7 @@ void ActorViewer::Render()
camera.m_Orientation.Translate(centre.X, centre.Y, centre.Z);
camera.UpdateFrustum();
g_Renderer.SetCamera(camera, camera);
g_Renderer.SetSceneCamera(camera, camera);
g_Renderer.Submit(m.Terrain.GetPatch(0, 0));