From 8e4933f9e97db9443d047b39db39c2e4f778bcb1 Mon Sep 17 00:00:00 2001 From: Porteries Tristan Date: Tue, 25 Jul 2017 20:34:14 +0200 Subject: [PATCH] UPBGE: Remove influence of stereo rasterizer member in matrix compute. Previously the members m_stereomode and m_curreye were used when computing the view and projection matrix. But as these settings are not used to change in game a lot of render loop for texture renderer or shadow were copying the current stereo mode, change it to avoid its effect in matrix computation and then restore the stereo mode after. This behaviour is to avoid and to replace by a send of the stereo mode to the function needing it. These functions are: GetRenderArea GetViewMatrix GetFrustumMatrix DrawStereoOffScreen Even if the members are not used in computation, they are left to have a place to store the global stereo mode to us. Ketsji engine is a candidate but as these values are only for rendering the rasterizer is a good place. --- source/gameengine/Ketsji/KX_CubeMap.cpp | 3 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 72 +++++++++++-------- source/gameengine/Ketsji/KX_KetsjiEngine.h | 21 ++++-- .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 3 +- source/gameengine/Ketsji/KX_PlanarMap.cpp | 5 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 5 +- .../Ketsji/KX_TextureRendererManager.cpp | 8 --- .../RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp | 4 -- .../gameengine/Rasterizer/RAS_Rasterizer.cpp | 46 +++++------- source/gameengine/Rasterizer/RAS_Rasterizer.h | 35 +++++---- .../gameengine/VideoTexture/ImageRender.cpp | 24 +------ 11 files changed, 106 insertions(+), 120 deletions(-) diff --git a/source/gameengine/Ketsji/KX_CubeMap.cpp b/source/gameengine/Ketsji/KX_CubeMap.cpp index 9631e0fae2ba..94ac7e597110 100644 --- a/source/gameengine/Ketsji/KX_CubeMap.cpp +++ b/source/gameengine/Ketsji/KX_CubeMap.cpp @@ -96,8 +96,7 @@ const MT_Matrix4x4& KX_CubeMap::GetProjectionMatrix(RAS_Rasterizer *rasty, KX_Sc const RAS_Rect& UNUSED(viewport), const RAS_Rect& UNUSED(area)) { if (m_invalidProjection) { - m_projection = rasty->GetFrustumMatrix(RAS_Rasterizer::RAS_STEREO_LEFTEYE, -m_clipStart, m_clipStart, -m_clipStart, m_clipStart, - m_clipStart, m_clipEnd, 1.0f, true); + m_projection = rasty->GetFrustumMatrix(-m_clipStart, m_clipStart, -m_clipStart, m_clipStart, m_clipStart, m_clipEnd); m_invalidProjection = false; } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 539aaed63e40..266d46f8c69e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -78,12 +78,13 @@ #define DEFAULT_LOGIC_TIC_RATE 60.0 -KX_KetsjiEngine::CameraRenderData::CameraRenderData(KX_Camera *rendercam, KX_Camera *cullingcam, const RAS_Rect& area, const RAS_Rect& viewport, - RAS_Rasterizer::StereoEye eye) +KX_KetsjiEngine::CameraRenderData::CameraRenderData(KX_Camera *rendercam, KX_Camera *cullingcam, const RAS_Rect& area, + const RAS_Rect& viewport, RAS_Rasterizer::StereoMode stereoMode, RAS_Rasterizer::StereoEye eye) :m_renderCamera(rendercam), m_cullingCamera(cullingcam), m_area(area), m_viewport(viewport), + m_stereoMode(stereoMode), m_eye(eye) { m_renderCamera->AddRef(); @@ -112,6 +113,13 @@ KX_KetsjiEngine::FrameRenderData::FrameRenderData(RAS_Rasterizer::OffScreenType { } +KX_KetsjiEngine::RenderData::RenderData(RAS_Rasterizer::StereoMode stereoMode, bool renderPerEye) + :m_stereoMode(stereoMode), + m_renderPerEye(renderPerEye) +{ +} + + const std::string KX_KetsjiEngine::m_profileLabels[tc_numCategories] = { "Physics:", // tc_physics "Logic:", // tc_logic @@ -466,13 +474,14 @@ void KX_KetsjiEngine::UpdateSuspendedScenes(double framestep) } KX_KetsjiEngine::CameraRenderData KX_KetsjiEngine::GetCameraRenderData(KX_Scene *scene, KX_Camera *camera, KX_Camera *overrideCullingCam, - const RAS_Rect& displayArea, RAS_Rasterizer::StereoEye eye, bool usestereo) + const RAS_Rect& displayArea, RAS_Rasterizer::StereoMode stereoMode, RAS_Rasterizer::StereoEye eye) { KX_Camera *rendercam; /* In case of stereo we must copy the camera because it is used twice with different settings * (modelview matrix). This copy use the same transform settings that the original camera * and its name is based on with the eye number in addition. */ + const bool usestereo = (stereoMode != RAS_Rasterizer::RAS_STEREO_NOSTEREO); if (usestereo) { rendercam = new KX_Camera(scene, scene->m_callbacks, *camera->GetCameraData(), true, true); rendercam->SetName("__stereo_" + camera->GetName() + "_" + std::to_string(eye) + "__"); @@ -498,12 +507,12 @@ KX_KetsjiEngine::CameraRenderData KX_KetsjiEngine::GetCameraRenderData(KX_Scene // Compute the area and the viewport based on the current display area and the optional camera viewport. GetSceneViewport(scene, rendercam, displayArea, area, viewport); // Compute the camera matrices: modelview and projection. - const MT_Matrix4x4 viewmat = m_rasterizer->GetViewMatrix(eye, rendercam->GetWorldToCamera(), rendercam->GetCameraData()->m_perspective); - const MT_Matrix4x4 projmat = GetCameraProjectionMatrix(scene, rendercam, eye, viewport, area); + const MT_Matrix4x4 viewmat = m_rasterizer->GetViewMatrix(stereoMode, eye, rendercam->GetWorldToCamera(), rendercam->GetCameraData()->m_perspective); + const MT_Matrix4x4 projmat = GetCameraProjectionMatrix(scene, rendercam, stereoMode, eye, viewport, area); rendercam->SetModelviewMatrix(viewmat); rendercam->SetProjectionMatrix(projmat); - CameraRenderData cameraData(rendercam, cullingcam, area, viewport, eye); + CameraRenderData cameraData(rendercam, cullingcam, area, viewport, stereoMode, eye); if (usestereo) { rendercam->Release(); @@ -512,7 +521,7 @@ KX_KetsjiEngine::CameraRenderData KX_KetsjiEngine::GetCameraRenderData(KX_Scene return cameraData; } -bool KX_KetsjiEngine::GetFrameRenderData(std::vector& frameDataList) +KX_KetsjiEngine::RenderData KX_KetsjiEngine::GetRenderData() { const RAS_Rasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); const bool usestereo = (stereomode != RAS_Rasterizer::RAS_STEREO_NOSTEREO); @@ -521,6 +530,8 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector& frameData stereomode == RAS_Rasterizer::RAS_STEREO_VINTERLACE || stereomode == RAS_Rasterizer::RAS_STEREO_ANAGLYPH; + RenderData renderData(stereomode, renderpereye); + // The number of eyes to manage in case of stereo. const unsigned short numeyes = (usestereo) ? 2 : 1; // The number of frames in case of stereo, could be multiple for interlaced or anaglyph stereo. @@ -535,7 +546,7 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector& frameData // Pre-compute the display area used for stereo or normal rendering. std::vector displayAreas; for (unsigned short eye = 0; eye < numeyes; ++eye) { - displayAreas.push_back(m_rasterizer->GetRenderArea(m_canvas, (RAS_Rasterizer::StereoEye)eye)); + displayAreas.push_back(m_rasterizer->GetRenderArea(m_canvas, stereomode, (RAS_Rasterizer::StereoEye)eye)); } // Prepare override culling camera of each scenes, we don't manage stereo currently. @@ -548,17 +559,18 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector& frameData // Compute the area and the viewport based on the current display area and the optional camera viewport. GetSceneViewport(scene, overrideCullingCam, displayAreas[RAS_Rasterizer::RAS_STEREO_LEFTEYE], area, viewport); // Compute the camera matrices: modelview and projection. - const MT_Matrix4x4 viewmat = m_rasterizer->GetViewMatrix(RAS_Rasterizer::RAS_STEREO_LEFTEYE, overrideCullingCam->GetWorldToCamera(), - overrideCullingCam->GetCameraData()->m_perspective); - const MT_Matrix4x4 projmat = GetCameraProjectionMatrix(scene, overrideCullingCam, RAS_Rasterizer::RAS_STEREO_LEFTEYE, viewport, area); + const MT_Matrix4x4 viewmat = m_rasterizer->GetViewMatrix(stereomode, RAS_Rasterizer::RAS_STEREO_LEFTEYE, + overrideCullingCam->GetWorldToCamera(), overrideCullingCam->GetCameraData()->m_perspective); + const MT_Matrix4x4 projmat = GetCameraProjectionMatrix(scene, overrideCullingCam, stereomode, + RAS_Rasterizer::RAS_STEREO_LEFTEYE, viewport, area); overrideCullingCam->SetModelviewMatrix(viewmat); overrideCullingCam->SetProjectionMatrix(projmat); } } for (unsigned short frame = 0; frame < numframes; ++frame) { - frameDataList.emplace_back(ofsType[frame]); - FrameRenderData& frameData = frameDataList.back(); + renderData.m_frameDataList.emplace_back(ofsType[frame]); + FrameRenderData& frameData = renderData.m_frameDataList.back(); // Get the eyes managed per frame. std::vector eyes; @@ -587,13 +599,14 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector& frameData } for (RAS_Rasterizer::StereoEye eye : eyes) { - sceneFrameData.m_cameraDataList.push_back(GetCameraRenderData(scene, cam, overrideCullingCam, displayAreas[eye], eye, usestereo)); + sceneFrameData.m_cameraDataList.push_back(GetCameraRenderData(scene, cam, overrideCullingCam, displayAreas[eye], + stereomode, eye)); } } } } - return renderpereye; + return renderData; } void KX_KetsjiEngine::Render() @@ -609,8 +622,7 @@ void KX_KetsjiEngine::Render() scene->RenderTextureRenderers(KX_TextureRendererManager::VIEWPORT_INDEPENDENT, m_rasterizer, nullptr, nullptr, RAS_Rect(), RAS_Rect()); } - std::vector frameDataList; - const bool renderpereye = GetFrameRenderData(frameDataList); + RenderData renderData = GetRenderData(); // Update all off screen to the current canvas size. m_rasterizer->UpdateOffScreens(m_canvas); @@ -630,7 +642,7 @@ void KX_KetsjiEngine::Render() // Used to detect when a camera is the first rendered an then doesn't request a depth clear. unsigned short pass = 0; - for (FrameRenderData& frameData : frameDataList) { + for (FrameRenderData& frameData : renderData.m_frameDataList) { // Current bound off screen. RAS_OffScreen *offScreen = m_rasterizer->GetOffScreen(frameData.m_ofsType); offScreen->Bind(); @@ -686,14 +698,14 @@ void KX_KetsjiEngine::Render() m_canvas->SetViewPort(0, 0, width, height); // Compositing per eye off screens to screen. - if (renderpereye) { - RAS_OffScreen *leftofs = m_rasterizer->GetOffScreen(frameDataList[0].m_ofsType); - RAS_OffScreen *rightofs = m_rasterizer->GetOffScreen(frameDataList[1].m_ofsType); - m_rasterizer->DrawStereoOffScreen(m_canvas, leftofs, rightofs); + if (renderData.m_renderPerEye) { + RAS_OffScreen *leftofs = m_rasterizer->GetOffScreen(renderData.m_frameDataList[0].m_ofsType); + RAS_OffScreen *rightofs = m_rasterizer->GetOffScreen(renderData.m_frameDataList[1].m_ofsType); + m_rasterizer->DrawStereoOffScreen(m_canvas, leftofs, rightofs, renderData.m_stereoMode); } // Else simply draw the off screen to screen. else { - m_rasterizer->DrawOffScreen(m_canvas, m_rasterizer->GetOffScreen(frameDataList[0].m_ofsType)); + m_rasterizer->DrawOffScreen(m_canvas, m_rasterizer->GetOffScreen(renderData.m_frameDataList[0].m_ofsType)); } EndFrame(); @@ -872,8 +884,8 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) } } -MT_Matrix4x4 KX_KetsjiEngine::GetCameraProjectionMatrix(KX_Scene *scene, KX_Camera *cam, RAS_Rasterizer::StereoEye eye, - const RAS_Rect& viewport, const RAS_Rect& area) const +MT_Matrix4x4 KX_KetsjiEngine::GetCameraProjectionMatrix(KX_Scene *scene, KX_Camera *cam, RAS_Rasterizer::StereoMode stereoMode, + RAS_Rasterizer::StereoEye eye, const RAS_Rect& viewport, const RAS_Rect& area) const { if (cam->hasValidProjectionMatrix()) { return cam->GetProjectionMatrix(); @@ -940,8 +952,8 @@ MT_Matrix4x4 KX_KetsjiEngine::GetCameraProjectionMatrix(KX_Scene *scene, KX_Came frustum.y1 *= camzoom; frustum.y2 *= camzoom; } - projmat = m_rasterizer->GetFrustumMatrix( - eye, frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength); + projmat = m_rasterizer->GetFrustumMatrix(stereoMode, eye, focallength, + frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); } } @@ -1222,8 +1234,10 @@ void KX_KetsjiEngine::DrawDebugCameraFrustum(KX_Scene *scene, RAS_DebugDraw& deb for (KX_Camera *cam : scene->GetCameraList()) { if (cam != cameraFrameData.m_renderCamera && (m_showCameraFrustum == KX_DebugOption::FORCE || cam->GetShowCameraFrustum())) { - const MT_Matrix4x4 viewmat = m_rasterizer->GetViewMatrix(cameraFrameData.m_eye, cam->GetWorldToCamera(), cam->GetCameraData()->m_perspective); - const MT_Matrix4x4 projmat = GetCameraProjectionMatrix(scene, cam, cameraFrameData.m_eye, cameraFrameData.m_viewport, cameraFrameData.m_area); + const MT_Matrix4x4 viewmat = m_rasterizer->GetViewMatrix(cameraFrameData.m_stereoMode, cameraFrameData.m_eye, + cam->GetWorldToCamera(), cam->GetCameraData()->m_perspective); + const MT_Matrix4x4 projmat = GetCameraProjectionMatrix(scene, cam, cameraFrameData.m_stereoMode, cameraFrameData.m_eye, + cameraFrameData.m_viewport, cameraFrameData.m_area); debugDraw.DrawCameraFrustum(projmat, viewmat); } } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index b1326bf1e23e..7488ababc662 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -105,7 +105,8 @@ class KX_KetsjiEngine private: struct CameraRenderData { - CameraRenderData(KX_Camera *rendercam, KX_Camera *cullingcam, const RAS_Rect& area, const RAS_Rect& viewport, RAS_Rasterizer::StereoEye eye); + CameraRenderData(KX_Camera *rendercam, KX_Camera *cullingcam, const RAS_Rect& area, const RAS_Rect& viewport, + RAS_Rasterizer::StereoMode stereoMode, RAS_Rasterizer::StereoEye eye); CameraRenderData(const CameraRenderData& other); ~CameraRenderData(); @@ -114,6 +115,7 @@ class KX_KetsjiEngine KX_Camera *m_cullingCamera; RAS_Rect m_area; RAS_Rect m_viewport; + RAS_Rasterizer::StereoMode m_stereoMode; RAS_Rasterizer::StereoEye m_eye; }; @@ -134,6 +136,15 @@ class KX_KetsjiEngine std::vector m_sceneDataList; }; + struct RenderData + { + RenderData(RAS_Rasterizer::StereoMode stereoMode, bool renderPerEye); + + RAS_Rasterizer::StereoMode m_stereoMode; + bool m_renderPerEye; + std::vector m_frameDataList; + }; + /// 2D Canvas (2D Rendering Device Context) RAS_ICanvas *m_canvas; /// 3D Rasterizer (3D Rendering) @@ -252,12 +263,12 @@ class KX_KetsjiEngine void UpdateSuspendedScenes(double framestep); /// Update and return the projection matrix of a camera depending on the viewport. - MT_Matrix4x4 GetCameraProjectionMatrix(KX_Scene *scene, KX_Camera *cam, RAS_Rasterizer::StereoEye eye, - const RAS_Rect& viewport, const RAS_Rect& area) const; + MT_Matrix4x4 GetCameraProjectionMatrix(KX_Scene *scene, KX_Camera *cam, RAS_Rasterizer::StereoMode stereoMode, + RAS_Rasterizer::StereoEye eye, const RAS_Rect& viewport, const RAS_Rect& area) const; CameraRenderData GetCameraRenderData(KX_Scene *scene, KX_Camera *camera, KX_Camera *overrideCullingCam, const RAS_Rect& displayArea, - RAS_Rasterizer::StereoEye eye, bool usestereo); + RAS_Rasterizer::StereoMode stereoMode, RAS_Rasterizer::StereoEye eye); /// Compute frame render data per eyes (in case of stereo), scenes and camera. - bool GetFrameRenderData(std::vector& frameDataList); + RenderData GetRenderData(); void RenderCamera(KX_Scene *scene, const CameraRenderData& cameraFrameData, RAS_OffScreen *offScreen, unsigned short pass, bool isFirstScene); RAS_OffScreen *PostRenderScene(KX_Scene *scene, RAS_OffScreen *inputofs, RAS_OffScreen *targetofs); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 64d4d11cb36a..6f621773d02f 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -287,7 +287,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) RAS_ICanvas *canvas = m_kxengine->GetCanvas(); short m_y_inv = canvas->GetHeight()-m_y; - const RAS_Rect displayArea = m_kxengine->GetRasterizer()->GetRenderArea(canvas, RAS_Rasterizer::RAS_STEREO_LEFTEYE); + RAS_Rasterizer *rasty = m_kxengine->GetRasterizer(); + const RAS_Rect displayArea = rasty->GetRenderArea(canvas, rasty->GetStereoMode(), RAS_Rasterizer::RAS_STEREO_LEFTEYE); m_kxengine->GetSceneViewport(m_kxscene, cam, displayArea, area, viewport); /* Check if the mouse is in the viewport */ diff --git a/source/gameengine/Ketsji/KX_PlanarMap.cpp b/source/gameengine/Ketsji/KX_PlanarMap.cpp index f3d98fa06aac..07c512e4c20d 100644 --- a/source/gameengine/Ketsji/KX_PlanarMap.cpp +++ b/source/gameengine/Ketsji/KX_PlanarMap.cpp @@ -135,10 +135,7 @@ const MT_Matrix4x4& KX_PlanarMap::GetProjectionMatrix(RAS_Rasterizer *rasty, KX_ frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); } else { - const float focallength = sceneCamera->GetFocalLength(); - - projection = rasty->GetFrustumMatrix(RAS_Rasterizer::RAS_STEREO_LEFTEYE, - frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength); + projection = rasty->GetFrustumMatrix(frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); } return projection; diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 988bba50c366..3b9e951521cd 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -981,8 +981,6 @@ static PyObject *gPyGetFocalLength(PyObject *, PyObject *, PyObject *) static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *) { - int flag = RAS_Rasterizer::RAS_STEREO_LEFTEYE; - RAS_Rasterizer *rasterizer = KX_GetActiveEngine()->GetRasterizer(); if (!rasterizer) { @@ -990,8 +988,7 @@ static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *) return nullptr; } - if (rasterizer->Stereo()) - flag = rasterizer->GetEye(); + int flag = rasterizer->GetEye(); return PyLong_FromLong(flag); } diff --git a/source/gameengine/Ketsji/KX_TextureRendererManager.cpp b/source/gameengine/Ketsji/KX_TextureRendererManager.cpp index c7c2c66b3826..c09857022c94 100644 --- a/source/gameengine/Ketsji/KX_TextureRendererManager.cpp +++ b/source/gameengine/Ketsji/KX_TextureRendererManager.cpp @@ -202,20 +202,12 @@ void KX_TextureRendererManager::Render(RendererCategory category, RAS_Rasterizer // Disable scissor to not bother with scissor box. rasty->Disable(RAS_Rasterizer::RAS_SCISSOR_TEST); - // Copy current stereo mode. - const RAS_Rasterizer::StereoMode steremode = rasty->GetStereoMode(); - // Disable stereo for realtime renderer. - rasty->SetStereoMode(RAS_Rasterizer::RAS_STEREO_NOSTEREO); - // Check if at least one renderer was rendered. bool rendered = false; for (KX_TextureRenderer *renderer : renderers) { rendered |= RenderRenderer(rasty, renderer, sceneCamera, viewport, area); } - // Restore previous stereo mode. - rasty->SetStereoMode(steremode); - rasty->Enable(RAS_Rasterizer::RAS_SCISSOR_TEST); rasty->SetDrawingMode(drawmode); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp index 45a9e627f13a..8cac62c58730 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp @@ -257,12 +257,8 @@ void RAS_OpenGLLight::BindShadowBuffer(RAS_ICanvas *canvas, KX_Camera *cam, MT_T cam->NodeUpdateGS(0); /* setup rasterizer transformations */ - /* SetViewMatrix may use stereomode which we temporarily disable here */ - RAS_Rasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); - m_rasterizer->SetStereoMode(RAS_Rasterizer::RAS_STEREO_NOSTEREO); m_rasterizer->SetProjectionMatrix(projectionmat); m_rasterizer->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(), cam->NodeGetLocalScaling()); - m_rasterizer->SetStereoMode(stereomode); } void RAS_OpenGLLight::UnbindShadowBuffer() diff --git a/source/gameengine/Rasterizer/RAS_Rasterizer.cpp b/source/gameengine/Rasterizer/RAS_Rasterizer.cpp index d40d961ae808..aa86e3bade8e 100644 --- a/source/gameengine/Rasterizer/RAS_Rasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_Rasterizer.cpp @@ -490,7 +490,8 @@ void RAS_Rasterizer::DrawOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *offScreen Enable(RAS_CULL_FACE); } -void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen) +void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen, + StereoMode stereoMode) { if (leftOffScreen->GetSamples() > 0) { // Then leftOffScreen == RAS_OFFSCREEN_EYE_LEFT0. @@ -511,7 +512,7 @@ void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *lef RAS_OffScreen::RestoreScreen(); - if (m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED) { + if (stereoMode == RAS_STEREO_VINTERLACE || stereoMode == RAS_STEREO_INTERLACED) { GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_STIPPLE); GPU_shader_bind(shader); @@ -522,7 +523,7 @@ void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *lef GPU_shader_uniform_int(shader, interface->leftEyeTexLoc, 0); GPU_shader_uniform_int(shader, interface->rightEyeTexLoc, 1); - GPU_shader_uniform_int(shader, interface->stippleIdLoc, (m_stereomode == RAS_STEREO_INTERLACED) ? 1 : 0); + GPU_shader_uniform_int(shader, interface->stippleIdLoc, (stereoMode == RAS_STEREO_INTERLACED) ? 1 : 0); DrawOverlayPlane(); @@ -531,7 +532,7 @@ void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *lef leftOffScreen->UnbindColorTexture(); rightOffScreen->UnbindColorTexture(); } - else if (m_stereomode == RAS_STEREO_ANAGLYPH) { + else if (stereoMode == RAS_STEREO_ANAGLYPH) { GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_STEREO_ANAGLYPH); GPU_shader_bind(shader); @@ -555,11 +556,11 @@ void RAS_Rasterizer::DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *lef Enable(RAS_CULL_FACE); } -RAS_Rect RAS_Rasterizer::GetRenderArea(RAS_ICanvas *canvas, StereoEye eye) +RAS_Rect RAS_Rasterizer::GetRenderArea(RAS_ICanvas *canvas, StereoMode stereoMode, StereoEye eye) { RAS_Rect area; // only above/below stereo method needs viewport adjustment - switch (m_stereomode) + switch (stereoMode) { case RAS_STEREO_ABOVEBELOW: { @@ -662,14 +663,6 @@ RAS_Rasterizer::StereoMode RAS_Rasterizer::GetStereoMode() return m_stereomode; } -bool RAS_Rasterizer::Stereo() -{ - if (m_stereomode > RAS_STEREO_NOSTEREO) // > 0 - return true; - else - return false; -} - void RAS_Rasterizer::SetEye(const StereoEye eye) { m_curreye = eye; @@ -824,19 +817,11 @@ void RAS_Rasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) m_camortho = (mat[3][3] != 0.0f); } -MT_Matrix4x4 RAS_Rasterizer::GetFrustumMatrix( - StereoEye eye, - float left, - float right, - float bottom, - float top, - float frustnear, - float frustfar, - float focallength, - bool perspective) +MT_Matrix4x4 RAS_Rasterizer::GetFrustumMatrix(StereoMode stereoMode, StereoEye eye, float focallength, + float left, float right, float bottom, float top, float frustnear, float frustfar) { // correction for stereo - if (Stereo()) { + if (stereoMode > RAS_STEREO_NOSTEREO) { // if Rasterizer.setFocalLength is not called we use the camera focallength if (!m_setfocallength) { // if focallength is null we use a value known to be reasonable @@ -861,7 +846,7 @@ MT_Matrix4x4 RAS_Rasterizer::GetFrustumMatrix( } } // leave bottom and top untouched - if (m_stereomode == RAS_STEREO_3DTVTOPBOTTOM) { + if (stereoMode == RAS_STEREO_3DTVTOPBOTTOM) { // restore the vertical frustum because the 3DTV will // expand the top and bottom part to the full size of the screen bottom *= 2.0f; @@ -869,6 +854,11 @@ MT_Matrix4x4 RAS_Rasterizer::GetFrustumMatrix( } } + return GetFrustumMatrix(left, right, bottom, top, frustnear, frustfar); +} + +MT_Matrix4x4 RAS_Rasterizer::GetFrustumMatrix(float left, float right, float bottom, float top, float frustnear, float frustfar) +{ float mat[4][4]; perspective_m4(mat, left, right, bottom, top, frustnear, frustfar); @@ -890,10 +880,10 @@ MT_Matrix4x4 RAS_Rasterizer::GetOrthoMatrix( } // next arguments probably contain redundant info, for later... -MT_Matrix4x4 RAS_Rasterizer::GetViewMatrix(StereoEye eye, const MT_Transform &camtrans, bool perspective) +MT_Matrix4x4 RAS_Rasterizer::GetViewMatrix(StereoMode stereoMode, StereoEye eye, const MT_Transform &camtrans, bool perspective) { // correction for stereo - if (Stereo() && perspective) { + if ((stereoMode != RAS_STEREO_NOSTEREO) && perspective) { static const MT_Vector3 unitViewDir(0.0f, -1.0f, 0.0f); // minus y direction, Blender convention static const MT_Vector3 unitViewupVec(0.0f, 0.0f, 1.0f); diff --git a/source/gameengine/Rasterizer/RAS_Rasterizer.h b/source/gameengine/Rasterizer/RAS_Rasterizer.h index 649588c0ef8b..cc46d895a822 100644 --- a/source/gameengine/Rasterizer/RAS_Rasterizer.h +++ b/source/gameengine/Rasterizer/RAS_Rasterizer.h @@ -485,13 +485,14 @@ class RAS_Rasterizer * \param canvas The canvas containing the screen viewport. * \param lefteyeindex The left off screen index. * \param righteyeindex The right off screen index. + * \param stereoMode The stereo category. */ - void DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen); + void DrawStereoOffScreen(RAS_ICanvas *canvas, RAS_OffScreen *leftOffScreen, RAS_OffScreen *rightOffScreen, StereoMode stereoMode); /** * GetRenderArea computes the render area from the 2d canvas. */ - RAS_Rect GetRenderArea(RAS_ICanvas *canvas, StereoEye eye); + RAS_Rect GetRenderArea(RAS_ICanvas *canvas, StereoMode stereoMode, StereoEye eye); // Stereo Functions /** @@ -499,11 +500,6 @@ class RAS_Rasterizer */ void SetStereoMode(const StereoMode stereomode); - /** - * Stereo can be used to query if the rasterizer is in stereo mode. - * \return true if stereo mode is enabled. - */ - bool Stereo(); StereoMode GetStereoMode(); /** @@ -568,7 +564,7 @@ class RAS_Rasterizer void SetProjectionMatrix(const MT_Matrix4x4 &mat); /// Get the modelview matrix according to the stereo settings. - MT_Matrix4x4 GetViewMatrix(StereoEye eye, const MT_Transform &camtrans, bool perspective); + MT_Matrix4x4 GetViewMatrix(StereoMode stereoMode, StereoEye eye, const MT_Transform &camtrans, bool perspective); /** * Sets the modelview matrix. */ @@ -632,6 +628,22 @@ class RAS_Rasterizer */ double GetTime(); + /** + * Generates a projection matrix from the specified frustum and stereomode. + * \param eye The stereo eye. + * \param stereoMode The stereo category. + * \param focallength The stereo eye focal length. + * \param left the left clipping plane + * \param right the right clipping plane + * \param bottom the bottom clipping plane + * \param top the top clipping plane + * \param frustnear the near clipping plane + * \param frustfar the far clipping plane + * \return a 4x4 matrix representing the projection transform. + */ + MT_Matrix4x4 GetFrustumMatrix(StereoMode stereoMode, StereoEye eye, float focallength, + float left, float right, float bottom, float top, float frustnear, float frustfar); + /** * Generates a projection matrix from the specified frustum. * \param left the left clipping plane @@ -642,11 +654,8 @@ class RAS_Rasterizer * \param frustfar the far clipping plane * \return a 4x4 matrix representing the projection transform. */ - MT_Matrix4x4 GetFrustumMatrix( - StereoEye eye, - float left, float right, float bottom, float top, - float frustnear, float frustfar, - float focallength = 0.0f, bool perspective = true); + MT_Matrix4x4 GetFrustumMatrix(float left, float right, float bottom, float top, float frustnear, float frustfar); + /** * Generates a orthographic projection matrix from the specified frustum. diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 3b3b7a99505b..1fcae8e1bfc9 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -299,9 +299,6 @@ bool ImageRender::Render() frustum.camnear = -mirrorOffset[2]; frustum.camfar = -mirrorOffset[2]+m_clip; } - // Store settings to be restored later - const RAS_Rasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); - RAS_Rect area = m_canvas->GetWindowArea(); // The screen area that ImageViewport will copy is also the rendering zone // bind the fbo and set the viewport to full size @@ -317,15 +314,12 @@ bool ImageRender::Render() m_scene->GetWorldInfo()->UpdateWorldSettings(m_rasterizer); m_rasterizer->SetAuxilaryClientInfo(m_scene); m_rasterizer->DisplayFog(); - // matrix calculation, don't apply any of the stereo mode - m_rasterizer->SetStereoMode(RAS_Rasterizer::RAS_STEREO_NOSTEREO); if (m_mirror) { // frustum was computed above // get frustum matrix and set projection matrix - MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(RAS_Rasterizer::RAS_STEREO_LEFTEYE, - frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); + MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix(frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); m_camera->SetProjectionMatrix(projmat); } @@ -376,8 +370,7 @@ bool ImageRender::Render() aspect_ratio, frustum); - projmat = m_rasterizer->GetFrustumMatrix(RAS_Rasterizer::RAS_STEREO_LEFTEYE, - frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); + projmat = m_rasterizer->GetFrustumMatrix(frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); } m_camera->SetProjectionMatrix(projmat); } @@ -390,17 +383,6 @@ bool ImageRender::Render() m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldPosition(), m_camera->NodeGetLocalScaling()); m_camera->SetModelviewMatrix(viewmat); - // restore the stereo mode now that the matrix is computed - m_rasterizer->SetStereoMode(stereomode); - - if (m_rasterizer->Stereo()) { - // stereo mode change render settings that disturb this render, cancel them all - // we don't need to restore them as they are set before each frame render. - glDrawBuffer(GL_BACK_LEFT); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDisable(GL_POLYGON_STIPPLE); - } - // Render Background if (m_scene->GetWorldInfo()) { const MT_Vector4 hor = m_scene->GetWorldInfo()->m_horizoncolor; @@ -420,8 +402,6 @@ bool ImageRender::Render() m_scene->RenderBuckets(nodes, camtrans, m_rasterizer, m_offScreen.get()); - // restore the canvas area now that the render is completed - m_canvas->GetWindowArea() = area; m_canvas->EndFrame(); // In case multisample is active, blit the FBO