Skip to content

Commit

Permalink
UPBGE: Remove influence of stereo rasterizer member in matrix compute.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
panzergame committed Jul 25, 2017
1 parent b0cf6c7 commit 8e4933f
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 120 deletions.
3 changes: 1 addition & 2 deletions source/gameengine/Ketsji/KX_CubeMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
72 changes: 43 additions & 29 deletions source/gameengine/Ketsji/KX_KetsjiEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) + "__");
Expand All @@ -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();
Expand All @@ -512,7 +521,7 @@ KX_KetsjiEngine::CameraRenderData KX_KetsjiEngine::GetCameraRenderData(KX_Scene
return cameraData;
}

bool KX_KetsjiEngine::GetFrameRenderData(std::vector<FrameRenderData>& frameDataList)
KX_KetsjiEngine::RenderData KX_KetsjiEngine::GetRenderData()
{
const RAS_Rasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode();
const bool usestereo = (stereomode != RAS_Rasterizer::RAS_STEREO_NOSTEREO);
Expand All @@ -521,6 +530,8 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector<FrameRenderData>& 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.
Expand All @@ -535,7 +546,7 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector<FrameRenderData>& frameData
// Pre-compute the display area used for stereo or normal rendering.
std::vector<RAS_Rect> 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.
Expand All @@ -548,17 +559,18 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector<FrameRenderData>& 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<RAS_Rasterizer::StereoEye> eyes;
Expand Down Expand Up @@ -587,13 +599,14 @@ bool KX_KetsjiEngine::GetFrameRenderData(std::vector<FrameRenderData>& 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()
Expand All @@ -609,8 +622,7 @@ void KX_KetsjiEngine::Render()
scene->RenderTextureRenderers(KX_TextureRendererManager::VIEWPORT_INDEPENDENT, m_rasterizer, nullptr, nullptr, RAS_Rect(), RAS_Rect());
}

std::vector<FrameRenderData> frameDataList;
const bool renderpereye = GetFrameRenderData(frameDataList);
RenderData renderData = GetRenderData();

// Update all off screen to the current canvas size.
m_rasterizer->UpdateOffScreens(m_canvas);
Expand All @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
}
}
Expand Down
21 changes: 16 additions & 5 deletions source/gameengine/Ketsji/KX_KetsjiEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
};

Expand All @@ -134,6 +136,15 @@ class KX_KetsjiEngine
std::vector<SceneRenderData> m_sceneDataList;
};

struct RenderData
{
RenderData(RAS_Rasterizer::StereoMode stereoMode, bool renderPerEye);

RAS_Rasterizer::StereoMode m_stereoMode;
bool m_renderPerEye;
std::vector<FrameRenderData> m_frameDataList;
};

/// 2D Canvas (2D Rendering Device Context)
RAS_ICanvas *m_canvas;
/// 3D Rasterizer (3D Rendering)
Expand Down Expand Up @@ -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<FrameRenderData>& 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);
Expand Down
3 changes: 2 additions & 1 deletion source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
5 changes: 1 addition & 4 deletions source/gameengine/Ketsji/KX_PlanarMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 1 addition & 4 deletions source/gameengine/Ketsji/KX_PythonInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,17 +981,14 @@ 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) {
PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getStereoEye(), Rasterizer not available");
return nullptr;
}

if (rasterizer->Stereo())
flag = rasterizer->GetEye();
int flag = rasterizer->GetEye();

return PyLong_FromLong(flag);
}
Expand Down
8 changes: 0 additions & 8 deletions source/gameengine/Ketsji/KX_TextureRendererManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Loading

0 comments on commit 8e4933f

Please sign in to comment.