diff --git a/examples/controllers/hydra/gun.js b/examples/controllers/hydra/gun.js index 146f9daca3..7d024e2fd3 100644 --- a/examples/controllers/hydra/gun.js +++ b/examples/controllers/hydra/gun.js @@ -99,6 +99,13 @@ var NUM_BUTTONS = 3; var screenSize = Controller.getViewportDimensions(); var startX = screenSize.x / 2 - (NUM_BUTTONS * (BUTTON_SIZE + PADDING)) / 2; +Script.include(["../../libraries/toolBars.js"]); +const persistKey = "highfidelity.gun.toolbar.position"; +var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); +toolBar.save = function () { + Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); +}; +var old = JSON.parse(Settings.getValue(persistKey) || '0'); var reticle = Overlays.addOverlay("image", { x: screenSize.x / 2 - (BUTTON_SIZE / 2), y: screenSize.y / 2 - (BUTTON_SIZE / 2), @@ -108,9 +115,9 @@ var reticle = Overlays.addOverlay("image", { alpha: 1 }); -var offButton = Overlays.addOverlay("image", { - x: startX, - y: screenSize.y - (BUTTON_SIZE + PADDING), +var offButton = toolBar.addOverlay("image", { + x: old ? old[0] : startX, + y: old ? old[1] : (screenSize.y - (BUTTON_SIZE + PADDING)), width: BUTTON_SIZE, height: BUTTON_SIZE, imageURL: HIFI_PUBLIC_BUCKET + "images/gun/close.svg", @@ -118,7 +125,7 @@ var offButton = Overlays.addOverlay("image", { }); startX += BUTTON_SIZE + PADDING; -var platformButton = Overlays.addOverlay("image", { +var platformButton = toolBar.addOverlay("image", { x: startX, y: screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, @@ -128,7 +135,7 @@ var platformButton = Overlays.addOverlay("image", { }); startX += BUTTON_SIZE + PADDING; -var gridButton = Overlays.addOverlay("image", { +var gridButton = toolBar.addOverlay("image", { x: startX, y: screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, @@ -493,10 +500,8 @@ function mousePressEvent(event) { } function scriptEnding() { - Overlays.deleteOverlay(reticle); - Overlays.deleteOverlay(offButton); - Overlays.deleteOverlay(platformButton); - Overlays.deleteOverlay(gridButton); + Overlays.deleteOverlay(reticle); + toolBar.cleanup(); Overlays.deleteOverlay(pointer[0]); Overlays.deleteOverlay(pointer[1]); Overlays.deleteOverlay(text); diff --git a/examples/dice.js b/examples/dice.js index 515019e740..ac5d1b7426 100644 --- a/examples/dice.js +++ b/examples/dice.js @@ -3,6 +3,7 @@ // examples // // Created by Philip Rosedale on February 2, 2015 +// Persist toolbar by HRS 6/11/15. // Copyright 2015 High Fidelity, Inc. // // Press the dice button to throw some dice from the center of the screen. @@ -31,9 +32,16 @@ var screenSize = Controller.getViewportDimensions(); var BUTTON_SIZE = 32; var PADDING = 3; -var offButton = Overlays.addOverlay("image", { - x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, - y: screenSize.y - (BUTTON_SIZE + PADDING), +Script.include(["libraries/toolBars.js"]); +var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); +const persistKey = "highfidelity.dice.toolbar.position"; +toolBar.save = function () { + Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); +}; +var old = JSON.parse(Settings.getValue(persistKey) || '0'); +var offButton = toolBar.addOverlay("image", { + x: old ? old[0] : (screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING), + y: old ? old[1] : (screenSize.y - (BUTTON_SIZE + PADDING)), width: BUTTON_SIZE, height: BUTTON_SIZE, imageURL: HIFI_PUBLIC_BUCKET + "images/close.png", @@ -45,7 +53,7 @@ var offButton = Overlays.addOverlay("image", { alpha: 1 }); -var deleteButton = Overlays.addOverlay("image", { +var deleteButton = toolBar.addOverlay("image", { x: screenSize.x / 2 - BUTTON_SIZE, y: screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, @@ -59,7 +67,7 @@ var deleteButton = Overlays.addOverlay("image", { alpha: 1 }); -var diceButton = Overlays.addOverlay("image", { +var diceButton = toolBar.addOverlay("image", { x: screenSize.x / 2 + PADDING, y: screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, @@ -140,10 +148,8 @@ function mousePressEvent(event) { } function scriptEnding() { - Overlays.deleteOverlay(offButton); - Overlays.deleteOverlay(diceButton); - Overlays.deleteOverlay(deleteButton); + toolBar.cleanup(); } Controller.mousePressEvent.connect(mousePressEvent); -Script.scriptEnding.connect(scriptEnding); \ No newline at end of file +Script.scriptEnding.connect(scriptEnding); diff --git a/examples/edit.js b/examples/edit.js index 6055400289..2974397cde 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -2,6 +2,7 @@ // examples // // Created by Brad Hefta-Gaub on 10/2/14. +// Persist toolbar by HRS 6/11/15. // Copyright 2014 High Fidelity, Inc. // // This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing @@ -320,6 +321,7 @@ var toolBar = (function () { } } + const persistKey = "highfidelity.edit.toolbar.position"; that.move = function () { var newViewPort, toolsX, @@ -330,6 +332,15 @@ var toolBar = (function () { if (toolBar === undefined) { initialize(); + toolBar.save = function () { + Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); + }; + var old = JSON.parse(Settings.getValue(persistKey) || '0'); + if (old) { + windowDimensions = newViewPort; + toolBar.move(old[0], old[1]); + return; + } } else if (windowDimensions.x === newViewPort.x && windowDimensions.y === newViewPort.y) { return; diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index 670a69dec7..6e72795ea5 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -3,6 +3,7 @@ // examples // // Created by Clément Brisset on 5/7/14. +// Persistable drag position by HRS 6/11/15. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -236,6 +237,7 @@ ToolBar = function(x, y, direction) { y: y - ToolBar.SPACING }); } + this.save(); } this.setAlpha = function(alpha, tool) { @@ -313,9 +315,8 @@ ToolBar = function(x, y, direction) { this.cleanup = function() { for(var tool in this.tools) { this.tools[tool].cleanup(); - delete this.tools[tool]; } - + if (this.back != null) { Overlays.deleteOverlay(this.back); this.back = null; @@ -327,7 +328,71 @@ ToolBar = function(x, y, direction) { this.width = 0; this.height = 0; } + + var that = this; + this.contains = function (xOrPoint, optionalY) { + var x = (optionalY === undefined) ? xOrPoint.x : xOrPoint, + y = (optionalY === undefined) ? xOrPoint.y : optionalY; + return (that.x <= x) && (x <= (that.x + that.width)) && + (that.y <= y) && (y <= (that.y + that.height)); + } + that.hover = function (enable) { + that.isHovering = enable; + if (that.back) { + if (enable) { + that.oldAlpha = Overlays.getProperty(that.back, 'backgroundAlpha'); + } + Overlays.editOverlay(this.back, { + visible: enable, + backgroundAlpha: enable ? 0.5 : that.oldAlpha + }); + } + }; + // These are currently only doing that which is necessary for toolbar hover and toolbar drag. + // They have not yet been extended to tool hover/click/release, etc. + this.mousePressEvent = function (event) { + if (!that.contains(event)) { + that.mightBeDragging = false; + return; + } + that.mightBeDragging = true; + that.dragOffsetX = that.x - event.x; + that.dragOffsetY = that.y - event.y; + }; + this.mouseMove = function (event) { + if (!that.mightBeDragging || !event.isLeftButton) { + that.mightBeDragging = false; + if (!that.contains(event)) { + if (that.isHovering) { + that.hover(false); + } + return; + } + if (!that.isHovering) { + that.hover(true); + } + return; + } + that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y); + }; + Controller.mousePressEvent.connect(this.mousePressEvent); + Controller.mouseMoveEvent.connect(this.mouseMove); + // Called on move. A different approach would be to have all this on the prototype, + // and let apps extend where needed. Ex. app defines its toolbar.move() to call this.__proto__.move and then save. + this.save = function () { }; + // This compatability hack breaks the model, but makes converting existing scripts easier: + this.addOverlay = function (ignored, oldSchoolProperties) { + var properties = JSON.parse(JSON.stringify(oldSchoolProperties)); // a copy + if (that.numberOfTools() === 0) { + that.move(properties.x, properties.y); + } + delete properties.x; + delete properties.y; + var index = that.addTool(properties); + var id = that.tools[index].overlay(); + return id; + } } ToolBar.SPACING = 4; ToolBar.VERTICAL = 0; -ToolBar.HORIZONTAL = 1; \ No newline at end of file +ToolBar.HORIZONTAL = 1; diff --git a/examples/paint.js b/examples/paint.js index 8bba4e2571..c0cc93afc7 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -12,8 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // Script.include('lineRider.js') -var MAX_POINTS_PER_LINE = 80; - +var MAX_POINTS_PER_LINE = 30; +var LINE_LIFETIME = 60 * 5 //5 minute lifetime var colorPalette = [{ red: 236, @@ -120,10 +120,12 @@ function MousePaint() { y: 10, z: 10 }, - lineWidth: LINE_WIDTH + lineWidth: LINE_WIDTH, + lifetime: LINE_LIFETIME }); points = []; if (point) { + points.push(point); path.push(point); } @@ -133,22 +135,22 @@ function MousePaint() { function mouseMoveEvent(event) { + if (!isDrawing) { + return; + } var pickRay = Camera.computePickRay(event.x, event.y); var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); var point = Vec3.sum(Camera.getPosition(), addVector); + points.push(point); + path.push(point); Entities.editEntity(line, { linePoints: points }); Entities.editEntity(brush, { position: point }); - if (!isDrawing) { - return; - } - points.push(point); - path.push(point); if (points.length === MAX_POINTS_PER_LINE) { //We need to start a new line! @@ -253,7 +255,6 @@ function HydraPaint() { var maxLineWidth = 10; var currentLineWidth = minLineWidth; var MIN_PAINT_TRIGGER_THRESHOLD = .01; - var LINE_LIFETIME = 20; var COLOR_CHANGE_TIME_FACTOR = 0.1; var RIGHT_BUTTON_1 = 7 @@ -330,7 +331,7 @@ function HydraPaint() { z: 10 }, lineWidth: 5, - // lifetime: LINE_LIFETIME + lifetime: LINE_LIFETIME }); this.points = []; if (point) { diff --git a/examples/pointer.js b/examples/pointer.js index cca46709ee..ea6b0c233f 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -3,6 +3,7 @@ // // Created by Seth Alves on May 15th // Modified by Eric Levin on June 4 +// Persist toolbar by HRS 6/11/15. // Copyright 2015 High Fidelity, Inc. // // Provides a pointer with option to draw on surfaces @@ -31,9 +32,16 @@ HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; var screenSize = Controller.getViewportDimensions(); var userCanPoint = false; -var pointerButton = Overlays.addOverlay("image", { - x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, - y: screenSize.y - (BUTTON_SIZE + PADDING), +Script.include(["libraries/toolBars.js"]); +const persistKey = "highfidelity.pointer.toolbar.position"; +var toolBar = new ToolBar(0, 0, ToolBar.HORIZONTAL); +toolBar.save = function () { + Settings.setValue(persistKey, JSON.stringify([toolBar.x, toolBar.y])); +}; +var old = JSON.parse(Settings.getValue(persistKey) || '0'); +var pointerButton = toolBar.addOverlay("image", { + x: old ? old[0] : screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, + y: old ? old[1] : screenSize.y - (BUTTON_SIZE + PADDING), width: BUTTON_SIZE, height: BUTTON_SIZE, imageURL: HIFI_PUBLIC_BUCKET + "images/laser.png", @@ -150,4 +158,4 @@ Script.scriptEnding.connect(cleanup); Controller.mouseMoveEvent.connect(mouseMoveEvent); Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); \ No newline at end of file +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 28365f3dd8..79aa6528e2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -989,14 +989,18 @@ void Application::paintGL() { finalFbo = DependencyManager::get()->render(&renderArgs); } - glPopMatrix(); #if 0 + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { _rearMirrorTools->render(&renderArgs, true, _glWidget->mapFromGlobal(QCursor::pos())); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { renderRearViewMirror(&renderArgs, _mirrorViewRect); } + renderArgs._renderMode = RenderArgs::NORMAL_RENDER_MODE; + + auto finalFbo = DependencyManager::get()->render(&renderArgs); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y, @@ -3383,7 +3387,6 @@ void Application::displaySide(RenderArgs* renderArgs, const Camera& theCamera, b "Application::displaySide() ... entities..."); RenderArgs::DebugFlags renderDebugFlags = RenderArgs::RENDER_DEBUG_NONE; - RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE; if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) { renderDebugFlags = (RenderArgs::DebugFlags) (renderDebugFlags | (int) RenderArgs::RENDER_DEBUG_HULLS); @@ -3392,10 +3395,6 @@ void Application::displaySide(RenderArgs* renderArgs, const Camera& theCamera, b renderDebugFlags = (RenderArgs::DebugFlags) (renderDebugFlags | (int) RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP); } - if (theCamera.getMode() == CAMERA_MODE_MIRROR) { - renderMode = RenderArgs::MIRROR_RENDER_MODE; - } - renderArgs->_renderMode = renderMode; renderArgs->_debugFlags = renderDebugFlags; _entities.render(renderArgs); } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 8d098b4dc8..8359480b03 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -464,7 +464,7 @@ void Stats::display( verticalOffset = STATS_PELS_INITIALOFFSET; horizontalOffset = _lastHorizontalOffset + _generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3; - lines = _expanded ? 10 : 2; + lines = _expanded ? 10 : 3; drawBackground(backgroundColor, horizontalOffset, 0, canvasSize.x - horizontalOffset, (lines + 1) * STATS_PELS_PER_LINE); @@ -612,12 +612,10 @@ void Stats::display( } // LOD Details - if (_expanded) { - octreeStats.str(""); - QString displayLODDetails = DependencyManager::get()->getLODFeedbackText(); - octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - } + octreeStats.str(""); + QString displayLODDetails = DependencyManager::get()->getLODFeedbackText(); + octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 5a59636fe7..80333a44e5 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -392,17 +392,20 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData // If we wrote fewer entities than we expected, update the number of entities in our packet bool successUpdateEntityCount = true; - if (!noEntitiesFit && numberOfEntities != actualNumberOfEntities) { + if (numberOfEntities != actualNumberOfEntities) { successUpdateEntityCount = packetData->updatePriorBytes(numberOfEntitiesOffset, (const unsigned char*)&actualNumberOfEntities, sizeof(actualNumberOfEntities)); } // If we weren't able to update our entity count, or we couldn't fit any entities, then // we should discard our element and return a result of NONE - if (!successUpdateEntityCount || noEntitiesFit) { + if (!successUpdateEntityCount) { packetData->discardLevel(elementLevel); appendElementState = OctreeElement::NONE; } else { + if (noEntitiesFit) { + appendElementState = OctreeElement::PARTIAL; + } packetData->endLevel(elementLevel); } return appendElementState; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 865c225445..71178070c6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1761,7 +1761,7 @@ void Model::setupBatchTransform(gpu::Batch& batch, RenderArgs* args) { } AABox Model::getPartBounds(int meshIndex, int partIndex) { - if (!_calculatedMeshPartBoxesValid) { + if (!_calculatedMeshPartBoxesValid || !_calculatedMeshBoxesValid) { recalculateMeshBoxes(true); } @@ -1802,7 +1802,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // we always need these properly calculated before we can render, this will likely already have been done // since the engine will call our getPartBounds() before rendering us. - if (!_calculatedMeshPartBoxesValid) { + if (!_calculatedMeshPartBoxesValid || !_calculatedMeshBoxesValid) { recalculateMeshBoxes(true); } auto textureCache = DependencyManager::get(); @@ -2082,6 +2082,9 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f Locations*& locations) { RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, isWireframe); + if (mode == RenderArgs::MIRROR_RENDER_MODE) { + key = RenderKey(key.getRaw() | RenderKey::IS_MIRROR); + } auto pipeline = _renderPipelineLib.find(key.getRaw()); if (pipeline == _renderPipelineLib.end()) { qDebug() << "No good, couldn't find a pipeline from the key ?" << key.getRaw(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 3fd7d05666..d9dda279e0 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -136,10 +136,12 @@ template <> void render::jobRun(const DrawOpaqueDeferred& job, const SceneContex Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; { GLenum buffers[3]; int bufferCount = 0; @@ -204,11 +206,12 @@ template <> void render::jobRun(const DrawTransparentDeferred& job, const SceneC Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; - const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; { diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 53964ac1db..bb4ba00cee 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -263,7 +263,6 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer renderContext->_numDrawnOpaqueItems = renderedItems.size(); - ItemIDsBounds sortedItems; sortedItems.reserve(culledItems.size()); if (renderContext->_sortOpaque) { @@ -280,10 +279,12 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderContext->args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; { GLenum buffers[3]; int bufferCount = 0; @@ -347,11 +348,12 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - args->_renderMode = RenderArgs::NORMAL_RENDER_MODE; - const float MOSTLY_OPAQUE_THRESHOLD = 0.75f; const float TRANSPARENT_ALPHA_THRESHOLD = 0.0f; @@ -434,6 +436,9 @@ template <> void render::jobRun(const DrawBackground& job, const SceneContextPoi Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); @@ -475,6 +480,9 @@ template <> void render::jobRun(const DrawPostLayered& job, const SceneContextPo Transform viewMat; args->_viewFrustum->evalProjectionMatrix(projMat); args->_viewFrustum->evalViewTransform(viewMat); + if (args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + viewMat.postScale(glm::vec3(-1.0f, 1.0f, 1.0f)); + } batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat);