diff --git a/examples/defaultScripts.js b/examples/defaultScripts.js index f06af70fb3..443e4b3bf8 100644 --- a/examples/defaultScripts.js +++ b/examples/defaultScripts.js @@ -11,6 +11,7 @@ Script.load("away.js"); Script.load("progress.js"); Script.load("edit.js"); +Script.load("marketplace.js"); Script.load("selectAudioDevice.js"); Script.load("inspect.js"); Script.load("notifications.js"); diff --git a/examples/directory.js b/examples/directory.js index 8d9993ffda..a18442747f 100644 --- a/examples/directory.js +++ b/examples/directory.js @@ -9,89 +9,118 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -Script.include("libraries/globals.js"); +Script.include([ + "libraries/toolBars.js", +]); -var directory = (function () { +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; - var DIRECTORY_URL = "https://metaverse.highfidelity.com/directory", - directoryWindow, - DIRECTORY_BUTTON_URL = HIFI_PUBLIC_BUCKET + "images/tools/directory.svg", - BUTTON_WIDTH = 50, - BUTTON_HEIGHT = 50, - BUTTON_ALPHA = 0.9, - BUTTON_MARGIN = 8, - directoryButton, - EDIT_TOOLBAR_BUTTONS = 10, // Number of buttons in edit.js toolbar - viewport; +var DIRECTORY_WINDOW_URL = "https://metaverse.highfidelity.com/directory"; +var directoryWindow = new OverlayWebWindow({ + title: 'directory', + source: "about:blank", + width: 900, + height: 700, + visible: false +}); - function updateButtonPosition() { - Overlays.editOverlay(directoryButton, { - x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN, - y: (viewport.y - (EDIT_TOOLBAR_BUTTONS + 1) * (BUTTON_HEIGHT + BUTTON_MARGIN) - BUTTON_MARGIN) / 2 - 1 +var toolHeight = 50; +var toolWidth = 50; + + +function showDirectory() { + directoryWindow.setURL(DIRECTORY_WINDOW_URL); + directoryWindow.setVisible(true); +} + +function hideDirectory() { + directoryWindow.setVisible(false); + directoryWindow.setURL("about:blank"); +} + +function toggleDirectory() { + if (directoryWindow.visible) { + hideDirectory(); + } else { + showDirectory(); + } +} + +var toolBar = (function() { + var that = {}, + toolBar, + browseDirectoryButton; + + function initialize() { + ToolBar.SPACING = 16; + toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.directory.toolbar", function(windowDimensions, toolbar) { + return { + x: windowDimensions.x - 8 - toolbar.width, + y: 50 + }; }); + browseDirectoryButton = toolBar.addTool({ + imageURL: toolIconUrl + "directory.svg", + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: true, + }); + + toolBar.showTool(browseDirectoryButton, true); } - function onMousePressEvent(event) { - var clickedOverlay; + var browseDirectoryButtonDown = false; + that.mousePressEvent = function(event) { + var clickedOverlay, + url, + file; - clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - - if (clickedOverlay === directoryButton) { - if (directoryWindow.url !== DIRECTORY_URL) { - directoryWindow.setURL(DIRECTORY_URL); - } - directoryWindow.setVisible(true); - directoryWindow.raise(); + if (!event.isLeftButton) { + // if another mouse button than left is pressed ignore it + return false; } - } - function onDomainChanged() { - directoryWindow.setVisible(false); - } + clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); - function onScriptUpdate() { - var oldViewport = viewport; - viewport = Controller.getViewportDimensions(); - if (viewport.x !== oldViewport.x || viewport.y !== oldViewport.y) { - updateButtonPosition(); + if (browseDirectoryButton === toolBar.clicked(clickedOverlay)) { + toggleDirectory(); + return true; } + + return false; + }; + + that.mouseReleaseEvent = function(event) { + var handled = false; + + + if (browseDirectoryButtonDown) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + } + + newModelButtonDown = false; + browseDirectoryButtonDown = false; + + return handled; } - function setUp() { - viewport = Controller.getViewportDimensions(); + that.cleanup = function() { + toolBar.cleanup(); + }; - directoryWindow = new OverlayWebWindow({ - title: 'Directory', - source: DIRECTORY_URL, - width: 900, - height: 700, - visible: false - }); + initialize(); + return that; +}()); - directoryButton = Overlays.addOverlay("image", { - imageURL: DIRECTORY_BUTTON_URL, - width: BUTTON_WIDTH, - height: BUTTON_HEIGHT, - x: viewport.x - BUTTON_WIDTH - BUTTON_MARGIN, - y: BUTTON_MARGIN, - alpha: BUTTON_ALPHA, - visible: true - }); - - updateButtonPosition(); - - Controller.mousePressEvent.connect(onMousePressEvent); - Window.domainChanged.connect(onDomainChanged); - - Script.update.connect(onScriptUpdate); - } - - function tearDown() { - Overlays.deleteOverlay(directoryButton); - } - - setUp(); - Script.scriptEnding.connect(tearDown); -}()); \ No newline at end of file +Controller.mousePressEvent.connect(toolBar.mousePressEvent) +Script.scriptEnding.connect(toolBar.cleanup); diff --git a/examples/edit.js b/examples/edit.js index 990e99b32d..6d77aa2f11 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -183,8 +183,7 @@ var toolBar = (function() { newTextButton, newWebButton, newZoneButton, - newPolyVoxButton, - browseMarketplaceButton; + newPolyVoxButton; function initialize() { toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.edit.toolbar", function(windowDimensions, toolbar) { @@ -194,13 +193,7 @@ var toolBar = (function() { }; }); - browseMarketplaceButton = toolBar.addTool({ - imageURL: toolIconUrl + "marketplace.svg", - width: toolWidth, - height: toolHeight, - alpha: 0.9, - visible: true, - }); + activeButton = toolBar.addTool({ imageURL: toolIconUrl + "edit-status.svg", @@ -415,7 +408,6 @@ var toolBar = (function() { } var newModelButtonDown = false; - var browseMarketplaceButtonDown = false; that.mousePressEvent = function(event) { var clickedOverlay, url, @@ -443,11 +435,7 @@ var toolBar = (function() { return true; } - if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) { - toggleMarketplace(); - return true; - } - + if (newCubeButton === toolBar.clicked(clickedOverlay)) { createNewEntity({ type: "Box", @@ -652,22 +640,10 @@ var toolBar = (function() { } handled = true; } - } else if (browseMarketplaceButtonDown) { - var clickedOverlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) { - url = Window.s3Browse(".*(fbx|FBX|obj|OBJ)"); - if (url !== null && url !== "") { - addModel(url); - } - handled = true; - } } newModelButtonDown = false; - browseMarketplaceButtonDown = false; + return handled; } diff --git a/examples/marketplace.js b/examples/marketplace.js new file mode 100644 index 0000000000..83f1287ed8 --- /dev/null +++ b/examples/marketplace.js @@ -0,0 +1,131 @@ +// +// marketplace.js +// examples +// +// Created by Eric Levin on 8 Jan 2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Script.include([ + "libraries/toolBars.js", +]); + +HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/"; + +var MARKETPLACE_URL = "https://metaverse.highfidelity.com/marketplace"; +var marketplaceWindow = new OverlayWebWindow({ + title: 'Marketplace', + source: "about:blank", + width: 900, + height: 700, + visible: false +}); + +var toolHeight = 50; +var toolWidth = 50; + + +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + print("setting marketplace URL to " + url); + marketplaceWindow.setURL(url); + marketplaceWindow.setVisible(true); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); + marketplaceWindow.setURL("about:blank"); +} + +function toggleMarketplace() { + if (marketplaceWindow.visible) { + hideMarketplace(); + } else { + showMarketplace(); + } +} + +var toolBar = (function() { + var that = {}, + toolBar, + browseMarketplaceButton; + + function initialize() { + ToolBar.SPACING = 16; + toolBar = new ToolBar(0, 0, ToolBar.VERTICAL, "highfidelity.marketplace.toolbar", function(windowDimensions, toolbar) { + return { + x: windowDimensions.x - 8 - toolbar.width, + y: 135 + }; + }); + browseMarketplaceButton = toolBar.addTool({ + imageURL: toolIconUrl + "marketplace.svg", + width: toolWidth, + height: toolHeight, + alpha: 0.9, + visible: true, + }); + + toolBar.showTool(browseMarketplaceButton, true); + } + + var browseMarketplaceButtonDown = false; + that.mousePressEvent = function(event) { + var clickedOverlay, + url, + file; + + if (!event.isLeftButton) { + // if another mouse button than left is pressed ignore it + return false; + } + + clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + + + if (browseMarketplaceButton === toolBar.clicked(clickedOverlay)) { + toggleMarketplace(); + return true; + } + + return false; + }; + + that.mouseReleaseEvent = function(event) { + var handled = false; + + + if (browseMarketplaceButtonDown) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + } + + newModelButtonDown = false; + browseMarketplaceButtonDown = false; + + return handled; + } + + that.cleanup = function() { + toolBar.cleanup(); + }; + + initialize(); + return that; +}()); + +Controller.mousePressEvent.connect(toolBar.mousePressEvent) +Script.scriptEnding.connect(toolBar.cleanup); diff --git a/interface/resources/html/interface-welcome.html b/interface/resources/html/interface-welcome.html index 1fc719ed72..113de7f2a0 100644 --- a/interface/resources/html/interface-welcome.html +++ b/interface/resources/html/interface-welcome.html @@ -1,4 +1,4 @@ - + @@ -14,7 +14,7 @@ body { background: white; - width: 839px; + width: 100%; overflow-x: hidden; } @@ -181,7 +181,7 @@ function overrideBodyWidth() { document.body.style.width = "100%"; - container.style.width = "0"; + } //]]> diff --git a/interface/resources/qml/VrMenu.qml b/interface/resources/qml/VrMenu.qml index 738ec34a02..689171f9e9 100644 --- a/interface/resources/qml/VrMenu.qml +++ b/interface/resources/qml/VrMenu.qml @@ -51,6 +51,16 @@ Hifi.VrMenu { VrMenuView { property int menuDepth: root.models.length - 1 model: root.models[menuDepth] + + function fit(position, size, maxposition) { + var padding = 8; + if (position < padding) { + position = padding; + } else if (position + size + padding > maxposition) { + position = maxposition - (size + padding); + } + return position; + } Component.onCompleted: { if (menuDepth === 0) { @@ -61,6 +71,8 @@ Hifi.VrMenu { x = lastColumn.x + 64; y = lastMousePosition.y - height / 2; } + x = fit(x, width, parent.width); + y = fit(y, height, parent.height); } onSelected: { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b142b6cb71..2fdd778339 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5062,8 +5062,23 @@ const DisplayPlugin* Application::getActiveDisplayPlugin() const { static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { auto menu = Menu::getInstance(); QString name = displayPlugin->getName(); + auto grouping = displayPlugin->getGrouping(); + QString groupingMenu { "" }; Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); + // assign the meny grouping based on plugin grouping + switch (grouping) { + case Plugin::ADVANCED: + groupingMenu = "Advanced"; + break; + case Plugin::DEVELOPER: + groupingMenu = "Developer"; + break; + default: + groupingMenu = "Standard"; + break; + } + static QActionGroup* displayPluginGroup = nullptr; if (!displayPluginGroup) { displayPluginGroup = new QActionGroup(menu); @@ -5072,7 +5087,9 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti auto parent = menu->getMenu(MenuOption::OutputMenu); auto action = menu->addActionToQMenuAndActionHash(parent, name, 0, qApp, - SLOT(updateDisplayMode())); + SLOT(updateDisplayMode()), + QAction::NoRole, UNSPECIFIED_POSITION, groupingMenu); + action->setCheckable(true); action->setChecked(active); displayPluginGroup->addAction(action); @@ -5086,7 +5103,31 @@ void Application::updateDisplayMode() { static std::once_flag once; std::call_once(once, [&] { bool first = true; + + // first sort the plugins into groupings: standard, advanced, developer + DisplayPluginList standard; + DisplayPluginList advanced; + DisplayPluginList developer; foreach(auto displayPlugin, displayPlugins) { + auto grouping = displayPlugin->getGrouping(); + switch (grouping) { + case Plugin::ADVANCED: + advanced.push_back(displayPlugin); + break; + case Plugin::DEVELOPER: + developer.push_back(displayPlugin); + break; + default: + standard.push_back(displayPlugin); + break; + } + } + + // concactonate the groupings into a single list in the order: standard, advanced, developer + standard.insert(std::end(standard), std::begin(advanced), std::end(advanced)); + standard.insert(std::end(standard), std::begin(developer), std::end(developer)); + + foreach(auto displayPlugin, standard) { addDisplayPluginToMenu(displayPlugin, first); // This must be a queued connection to avoid a deadlock QObject::connect(displayPlugin.get(), &DisplayPlugin::requestRender, @@ -5098,6 +5139,11 @@ void Application::updateDisplayMode() { first = false; } + + // after all plugins have been added to the menu, add a seperator to the menu + auto menu = Menu::getInstance(); + auto parent = menu->getMenu(MenuOption::OutputMenu); + parent->addSeparator(); }); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 085b349b8f..6a544f31c9 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -243,7 +243,7 @@ namespace MenuOption { const QString OctreeStats = "Entity Statistics"; const QString OnePointCalibration = "1 Point Calibration"; const QString OnlyDisplayTopTen = "Only Display Top Ten"; - const QString OutputMenu = "Display>Mode"; + const QString OutputMenu = "Display"; const QString PackageModel = "Package Model..."; const QString Pair = "Pair"; const QString PhysicsShowOwned = "Highlight Simulation Ownership"; diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 290e2e4f79..fb6e9c3b65 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -15,14 +15,10 @@ #include -const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display"); +const QString Basic2DWindowOpenGLDisplayPlugin::NAME("Desktop"); static const QString FULLSCREEN = "Fullscreen"; -const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const { - return NAME; -} - void Basic2DWindowOpenGLDisplayPlugin::activate() { WindowOpenGLDisplayPlugin::activate(); diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index e3633b5fe8..6523b58914 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -18,7 +18,7 @@ class Basic2DWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { Q_OBJECT public: - virtual const QString & getName() const override; + virtual const QString& getName() const override { return NAME; } virtual float getTargetFrameRate() override { return _framerateTarget ? (float) _framerateTarget : TARGET_FRAMERATE_Basic2DWindowOpenGL; } diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index f780534bc9..e8145db900 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -14,10 +14,6 @@ const QString NullDisplayPlugin::NAME("NullDisplayPlugin"); -const QString & NullDisplayPlugin::getName() const { - return NAME; -} - glm::uvec2 NullDisplayPlugin::getRecommendedRenderSize() const { return glm::uvec2(100, 100); } diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 23e23e2c4e..14b5529a29 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -13,7 +13,8 @@ class NullDisplayPlugin : public DisplayPlugin { public: virtual ~NullDisplayPlugin() final {} - virtual const QString & getName() const override; + virtual const QString& getName() const override { return NAME; } + virtual grouping getGrouping() const override { return DEVELOPER; } void stop() override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp index ffaf005533..40c6e6306b 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp @@ -44,11 +44,7 @@ void main() { )FS"; -const QString InterleavedStereoDisplayPlugin::NAME("Interleaved Stereo Display"); - -const QString & InterleavedStereoDisplayPlugin::getName() const { - return NAME; -} +const QString InterleavedStereoDisplayPlugin::NAME("3D TV - Interleaved"); InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h index 7116363e44..df2a9f4800 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -13,7 +13,9 @@ class InterleavedStereoDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT public: InterleavedStereoDisplayPlugin(); - virtual const QString & getName() const override; + + virtual const QString& getName() const override { return NAME; } + virtual grouping getGrouping() const override { return ADVANCED; } // initialize OpenGL context settings needed by the plugin virtual void customizeContext() override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp index 12865cf4cd..e8a83d2b08 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp @@ -11,10 +11,6 @@ const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo"); -const QString & SideBySideStereoDisplayPlugin::getName() const { - return NAME; -} - SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h index 9f8440227f..70f69ba4cb 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h @@ -15,7 +15,8 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT public: SideBySideStereoDisplayPlugin(); - virtual const QString& getName() const override; + virtual const QString& getName() const override { return NAME; } + virtual grouping getGrouping() const override { return ADVANCED; } virtual glm::uvec2 getRecommendedRenderSize() const override; private: static const QString NAME; diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h index b31c59d11a..6acb2bf041 100644 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.h @@ -67,7 +67,7 @@ public: // Plugin functions virtual bool isSupported() const override { return true; } virtual bool isJointController() const override { return false; } - const QString& getName() const override { return NAME; } + virtual const QString& getName() const override { return NAME; } virtual void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); } virtual void pluginUpdate(float deltaTime, bool jointsCaptured) override; diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index c030b1073f..ee10ce331c 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -19,6 +19,11 @@ public: /// \return human-readable name virtual const QString& getName() const = 0; + typedef enum { STANDARD, ADVANCED, DEVELOPER } grouping; + + /// \return human-readable grouping for the plugin, STANDARD, ADVANCED, or DEVELOPER + virtual grouping getGrouping() const { return STANDARD; } + /// \return string ID (not necessarily human-readable) virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; } diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 5e03f74e8b..accc8cdb6c 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -22,15 +22,16 @@ public: AmbientOcclusionEffect(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; - + void setRadius(float radius); float getRadius() const { return _parametersBuffer.get()._radiusInfo.x; } // Obscurance level which intensify or dim down the obscurance effect void setLevel(float level); float getLevel() const { return _parametersBuffer.get()._radiusInfo.w; } - + + using JobModel = render::Task::Job::Model; + private: void setDepthInfo(float nearZ, float farZ); diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index c7cce4cb15..51a8e3a1de 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -22,7 +22,7 @@ public: Antialiasing(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; const gpu::PipelinePointer& getAntialiasingPipeline(); const gpu::PipelinePointer& getBlendPipeline(); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 4575c6ac05..20e43593ea 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -18,7 +18,7 @@ class DebugDeferredBuffer { public: - using JobModel = render::Job::Model; + using JobModel = render::Task::Job::Model; DebugDeferredBuffer(); diff --git a/libraries/render-utils/src/HitEffect.h b/libraries/render-utils/src/HitEffect.h index 0a96a5300d..a83fb36693 100644 --- a/libraries/render-utils/src/HitEffect.h +++ b/libraries/render-utils/src/HitEffect.h @@ -17,7 +17,7 @@ public: HitEffect(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; const gpu::PipelinePointer& getHitEffectPipeline(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 2574f22a8c..98cfc35bd8 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -24,6 +24,7 @@ #include "HitEffect.h" #include "TextureCache.h" +#include "render/DrawTask.h" #include "render/DrawStatus.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" @@ -51,63 +52,61 @@ void ToneMappingDeferred::run(const SceneContextPointer& sceneContext, const Ren RenderDeferredTask::RenderDeferredTask() : Task() { // CPU only, create the list of renderedOpaques items - _jobs.push_back(Job(new FetchItems::JobModel("FetchOpaque", - FetchItems([](const RenderContextPointer& context, int count) { - context->getItemsConfig().opaque.numFeed = count; - }) - ))); - _jobs.push_back(Job(new CullItemsOpaque::JobModel("CullOpaque", _jobs.back().getOutput()))); - _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortOpaque", _jobs.back().getOutput()))); + addJob("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { + context->getItemsConfig().opaque.numFeed = count; + })); + addJob("CullOpaque", _jobs.back().getOutput()); + addJob("DepthSortOpaque", _jobs.back().getOutput()); auto& renderedOpaques = _jobs.back().getOutput(); // CPU only, create the list of renderedTransparents items - _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", - FetchItems(ItemFilter::Builder::transparentShape().withoutLayered(), - [](const RenderContextPointer& context, int count) { - context->getItemsConfig().transparent.numFeed = count; - }) - ))); - _jobs.push_back(Job(new CullItemsTransparent::JobModel("CullTransparent", _jobs.back().getOutput()))); - _jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)))); + addJob("FetchTransparent", FetchItems( + ItemFilter::Builder::transparentShape().withoutLayered(), + [](const RenderContextPointer& context, int count) { + context->getItemsConfig().transparent.numFeed = count; + } + )); + addJob("CullTransparent", _jobs.back().getOutput()); + addJob("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)); auto& renderedTransparents = _jobs.back().getOutput(); // GPU Jobs: Start preparing the deferred and lighting buffer - _jobs.push_back(Job(new PrepareDeferred::JobModel("PrepareDeferred"))); + addJob("PrepareDeferred"); // Render opaque objects in DeferredBuffer - _jobs.push_back(Job(new DrawOpaqueDeferred::JobModel("DrawOpaqueDeferred", renderedOpaques))); + addJob("DrawOpaqueDeferred", renderedOpaques); // Once opaque is all rendered create stencil background - _jobs.push_back(Job(new DrawStencilDeferred::JobModel("DrawOpaqueStencil"))); + addJob("DrawOpaqueStencil"); // Use Stencil and start drawing background in Lighting buffer - _jobs.push_back(Job(new DrawBackgroundDeferred::JobModel("DrawBackgroundDeferred"))); + addJob("DrawBackgroundDeferred"); - // AO job, to be revisited - _jobs.push_back(Job(new AmbientOcclusionEffect::JobModel("AmbientOcclusion"))); + // AO job + addJob("AmbientOcclusion"); _jobs.back().setEnabled(false); _occlusionJobIndex = (int)_jobs.size() - 1; // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. - _jobs.push_back(Job(new DrawLight::JobModel("DrawLight"))); + addJob("DrawLight"); // DeferredBuffer is complete, now let's shade it into the LightingBuffer - _jobs.push_back(Job(new RenderDeferred::JobModel("RenderDeferred"))); + addJob("RenderDeferred"); // AA job to be revisited - _jobs.push_back(Job(new Antialiasing::JobModel("Antialiasing"))); + addJob("Antialiasing"); _jobs.back().setEnabled(false); _antialiasingJobIndex = (int)_jobs.size() - 1; // Render transparent objects forward in LigthingBuffer - _jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", renderedTransparents))); + addJob("TransparentDeferred", renderedTransparents); // Lighting Buffer ready for tone mapping - _jobs.push_back(Job(new ToneMappingDeferred::JobModel("ToneMapping"))); + addJob("ToneMapping"); _toneMappingJobIndex = (int)_jobs.size() - 1; // Debugging Deferred buffer job - _jobs.push_back(Job(new DebugDeferredBuffer::JobModel("DebugDeferredBuffer"))); + addJob("DebugDeferredBuffer"); _jobs.back().setEnabled(false); _drawDebugDeferredBufferIndex = (int)_jobs.size() - 1; @@ -116,21 +115,18 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); - _jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)))); + addJob("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)); _jobs.back().setEnabled(false); _drawStatusJobIndex = (int)_jobs.size() - 1; } - _jobs.push_back(Job(new DrawOverlay3D::JobModel("DrawOverlay3D"))); + addJob("DrawOverlay3D"); - _jobs.push_back(Job(new HitEffect::JobModel("HitEffect"))); + addJob("HitEffect"); _jobs.back().setEnabled(false); _drawHitEffectJobIndex = (int)_jobs.size() -1; - _jobs.push_back(Job(new Blit::JobModel("Blit"))); -} - -RenderDeferredTask::~RenderDeferredTask() { + addJob("Blit"); } void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 051faa3238..b4e926ddb9 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -12,7 +12,7 @@ #ifndef hifi_RenderDeferredTask_h #define hifi_RenderDeferredTask_h -#include "render/DrawTask.h" +#include "render/Engine.h" #include "gpu/Pipeline.h" @@ -22,14 +22,14 @@ class SetupDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; class PrepareDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; @@ -37,7 +37,7 @@ class RenderDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; class ToneMappingDeferred { @@ -46,21 +46,21 @@ public: ToneMappingEffect _toneMappingEffect; - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; class DrawOpaqueDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); - typedef render::Job::ModelI JobModel; + using JobModel = render::Task::Job::ModelI; }; class DrawTransparentDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemIDsBounds& inItems); - typedef render::Job::ModelI JobModel; + using JobModel = render::Task::Job::ModelI; }; class DrawStencilDeferred { @@ -70,14 +70,14 @@ public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; class DrawBackgroundDeferred { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; class DrawOverlay3D { @@ -86,25 +86,22 @@ public: static const gpu::PipelinePointer& getOpaquePipeline(); void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - - typedef render::Job::Model JobModel; + + using JobModel = render::Task::Job::Model; }; class Blit { public: void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + using JobModel = render::Task::Job::Model; }; class RenderDeferredTask : public render::Task { public: RenderDeferredTask(); - ~RenderDeferredTask(); - render::Jobs _jobs; - int _drawDebugDeferredBufferIndex = -1; int _drawStatusJobIndex = -1; int _drawHitEffectJobIndex = -1; diff --git a/libraries/render/src/render/Context.cpp b/libraries/render/src/render/Context.cpp new file mode 100644 index 0000000000..14e6ebd9c7 --- /dev/null +++ b/libraries/render/src/render/Context.cpp @@ -0,0 +1,30 @@ +// +// Context.cpp +// render/src/render +// +// Created by Zach Pomerantz on 1/6/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "Context.h" + +using namespace render; + +RenderContext::RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode) + : _deferredDebugMode{ deferredDebugMode }, _deferredDebugSize{ deferredDebugSize }, + _args{ nullptr }, + _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect }, + _items{ items }, _tone{ tone }, _ambientOcclusion{ ao } {} + +void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned) { + _occlusionStatus = occlusion; + _fxaaStatus = fxaa; + + if (showOwned) { + _drawStatus |= render::showNetworkStatusFlag; + } +}; + diff --git a/libraries/render/src/render/Context.h b/libraries/render/src/render/Context.h new file mode 100644 index 0000000000..934cb0f07e --- /dev/null +++ b/libraries/render/src/render/Context.h @@ -0,0 +1,117 @@ +// +// Context.h +// render/src/render +// +// Created by Zach Pomerantz on 1/6/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_Context_h +#define hifi_render_Context_h + +#include "Scene.h" + +namespace render { + +class SceneContext { +public: + ScenePointer _scene; + + SceneContext() {} +}; +using SceneContextPointer = std::shared_ptr; + +// see examples/utilities/tools/renderEngineDebug.js +const int showDisplayStatusFlag = 1; +const int showNetworkStatusFlag = 2; + +class RenderContext { +public: + class ItemsConfig { + public: + class Counter { + public: + Counter() {} + Counter(const Counter& counter) : maxDrawn { counter.maxDrawn } {} + + void setCounts(const Counter& counter) { + numFeed = counter.numFeed; + numDrawn = counter.numDrawn; + }; + + int numFeed { 0 }; + int numDrawn { 0 }; + int maxDrawn { -1 }; + }; + + class State : public Counter { + public: + bool render { true }; + bool cull { true }; + bool sort { true }; + + Counter counter{}; + }; + + ItemsConfig(State opaqueState, State transparentState, Counter overlay3DCounter) + : opaque{ opaqueState }, transparent{ transparentState }, overlay3D{ overlay3DCounter } {} + ItemsConfig() : ItemsConfig{ {}, {}, {} } {} + + // TODO: If member count increases, store counters in a map instead of multiple members + State opaque{}; + State transparent{}; + Counter overlay3D{}; + }; + + class Tone { + public: + int toneCurve = 1; // Means just Gamma 2.2 correction + float exposure = 0.0; + }; + + class AmbientOcclusion { + public: + float radius = 0.5f; // radius in meters of the AO effect + float level = 0.5f; // Level of the obscrance value + }; + + RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode); + RenderContext() {}; + + void setArgs(RenderArgs* args) { _args = args; } + RenderArgs* getArgs() { return _args; } + ItemsConfig& getItemsConfig() { return _items; } + Tone& getTone() { return _tone; } + AmbientOcclusion& getAmbientOcclusion() { return _ambientOcclusion; } + int getDrawStatus() { return _drawStatus; } + bool getDrawHitEffect() { return _drawHitEffect; } + bool getOcclusionStatus() { return _occlusionStatus; } + bool getFxaaStatus() { return _fxaaStatus; } + void setOptions(bool occlusion, bool fxaa, bool showOwned); + + // Debugging + int _deferredDebugMode; + glm::vec4 _deferredDebugSize; + +protected: + RenderArgs* _args; + + // Options + int _drawStatus; // bitflag + bool _drawHitEffect; + bool _occlusionStatus { false }; + bool _fxaaStatus = { false }; + + ItemsConfig _items; + Tone _tone; + AmbientOcclusion _ambientOcclusion; +}; +typedef std::shared_ptr RenderContextPointer; + +} + +#endif // hifi_render_Context_h + diff --git a/libraries/render/src/render/DrawStatus.h b/libraries/render/src/render/DrawStatus.h index 1239819911..c9cf16c0cb 100644 --- a/libraries/render/src/render/DrawStatus.h +++ b/libraries/render/src/render/DrawStatus.h @@ -38,7 +38,7 @@ namespace render { void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); - typedef Job::ModelI JobModel; + using JobModel = Task::Job::ModelI; const gpu::PipelinePointer getDrawItemBoundsPipeline(); const gpu::PipelinePointer getDrawItemStatusPipeline(); diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 44ba57143f..d9fbc79d1e 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -15,44 +15,12 @@ #include #include -#include #include #include using namespace render; -DrawSceneTask::DrawSceneTask() : Task() { -} - -DrawSceneTask::~DrawSceneTask() { -} - -void DrawSceneTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - // sanity checks - assert(sceneContext); - if (!sceneContext->_scene) { - return; - } - - - // Is it possible that we render without a viewFrustum ? - if (!(renderContext->getArgs() && renderContext->getArgs()->_viewFrustum)) { - return; - } - - for (auto job : _jobs) { - job.run(sceneContext, renderContext); - } -}; - -Job::~Job() { -} - - - - - void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { assert(renderContext->getArgs()); assert(renderContext->getArgs()->_viewFrustum); @@ -263,50 +231,3 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext }); args->_batch = nullptr; } - -void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - assert(renderContext->getArgs()); - assert(renderContext->getArgs()->_viewFrustum); - - // render backgrounds - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background()); - - - ItemIDsBounds inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.emplace_back(id); - } - RenderArgs* args = renderContext->getArgs(); - doInBatch(args->_context, [=](gpu::Batch& batch) { - args->_batch = &batch; - batch.enableSkybox(true); - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - renderItems(sceneContext, renderContext, inItems); - }); - args->_batch = nullptr; -} - -void ItemMaterialBucketMap::insert(const ItemID& id, const model::MaterialKey& key) { - // Insert the itemID in every bucket where it filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(key)) { - bucket.second.push_back(id); - } - } -} - -void ItemMaterialBucketMap::allocateStandardMaterialBuckets() { - (*this)[model::MaterialFilter::Builder::opaqueDiffuse()]; -} diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index ab102e32a7..3efb06871a 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -9,217 +9,15 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_render_Task_h -#define hifi_render_Task_h +#ifndef hifi_render_DrawTask_h +#define hifi_render_DrawTask_h #include "Engine.h" #include "gpu/Batch.h" -#include namespace render { -template void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - jobModel.run(sceneContext, renderContext); -} -template void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { - jobModel.run(sceneContext, renderContext, input); -} -template void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { - jobModel.run(sceneContext, renderContext, output); -} -template void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { - jobModel.run(sceneContext, renderContext, input, output); -} - -class Job { -public: - - // Varying represent a varying piece of data - class Varying { - public: - - Varying(const Varying& var): _concept(var._concept) {} - - Varying() {} - template - Varying(const T& data) : _concept(std::make_shared>(data)) {} - - // Access the _data contained win the concept explicitely - template T& edit() { return std::static_pointer_cast>(_concept)->_data; } - template const T& get() const { return std::static_pointer_cast>(_concept)->_data; } - - protected: - friend class Job; - - std::vector> _consumerJobs; - - void addJobConsumer(const std::shared_ptr& job) { - _consumerJobs.push_back(job); - } - - class Concept { - public: - virtual ~Concept() = default; - }; - template class Model : public Concept { - public: - typedef T Data; - Data _data; - Model(const Model& source): _data(source.data) {} - Model(const Data& data): _data(data) {} - virtual ~Model() {} - }; - - std::shared_ptr _concept; - }; - - Job(const Job& other) : _concept(other._concept) {} - ~Job(); - - bool isEnabled() const { return _concept->isEnabled(); } - void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } - - const std::string& getName() const { return _concept->getName(); } - const Varying getInput() const { return _concept->getInput(); } - const Varying getOutput() const { return _concept->getOutput(); } - - template T& edit() { - auto theConcept = std::dynamic_pointer_cast(_concept); - assert(theConcept); - return theConcept->_data; - } - template const T& get() const { - auto theConcept = std::dynamic_pointer_cast(_concept); - assert(theConcept); - return theConcept->_data; - } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - PerformanceTimer perfTimer(getName().c_str()); - PROFILE_RANGE(getName().c_str()); - _concept->run(sceneContext, renderContext); - } - -protected: -public: - - class Concept { - std::string _name; - bool _isEnabled = true; - public: - Concept() : _name() {} - Concept(const std::string& name) : _name(name) {} - virtual ~Concept() = default; - - void setName(const std::string& name) { _name = name; } - const std::string& getName() const { return _name; } - - bool isEnabled() const { return _isEnabled; } - void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } - - virtual const Varying getInput() const { return Varying(); } - virtual const Varying getOutput() const { return Varying(); } - virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; - }; - - Job(Concept* concept) : _concept(concept) {} - -public: - template class Model : public Concept { - public: - typedef T Data; - - Data _data; - - Model() {} - Model(const std::string& name): Concept(name) {} - Model(Data data): _data(data) {} - Model(Data data, const std::string& name): Concept(name), _data(data) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRun(_data, sceneContext, renderContext); - } - } - }; - - template class ModelI : public Concept { - public: - typedef T Data; - typedef I Input; - - Data _data; - Varying _input; - - const Varying getInput() const { return _input; } - - ModelI(const std::string& name, const Varying& input, Data data = Data()) : Concept(name), _data(data), _input(input) {} - ModelI(const std::string& name, Data data): Concept(name), _data(data) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunI(_data, sceneContext, renderContext, _input.get()); - } - } - }; - - template class ModelO : public Concept { - public: - typedef T Data; - typedef O Output; - - Data _data; - Varying _output; - - const Varying getOutput() const { return _output; } - - ModelO(const std::string& name): Concept(name), _output(Output()) { - - } - - ModelO(const std::string& name, Data data): Concept(name), _data(data), _output(Output()) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunO(_data, sceneContext, renderContext, _output.edit()); - } - } - }; - - template class ModelIO : public Concept { - public: - typedef T Data; - typedef I Input; - typedef O Output; - - Data _data; - Varying _input; - Varying _output; - - const Varying getInput() const { return _input; } - const Varying getOutput() const { return _output; } - - ModelIO(const std::string& name, const Varying& input, Data data = Data()): Concept(name), _data(data), _input(input), _output(Output()) {} - ModelIO(const std::string& name, Data data, Output output): Concept(name), _data(data), _output(output) {} - - void setInput(const Varying& input) { _input = input; } - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { - if (isEnabled()) { - jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); - } - } - }; - - std::shared_ptr _concept; -}; - - - - -typedef std::vector Jobs; - void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); @@ -236,25 +34,25 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems); - typedef Job::ModelO JobModel; + using JobModel = Task::Job::ModelO; }; class CullItems { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - typedef Job::ModelIO JobModel; + using JobModel = Task::Job::ModelIO; }; class CullItemsOpaque { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - typedef Job::ModelIO JobModel; + using JobModel = Task::Job::ModelIO; }; class CullItemsTransparent { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - typedef Job::ModelIO JobModel; + using JobModel = Task::Job::ModelIO; }; class DepthSortItems { @@ -265,52 +63,16 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); - typedef Job::ModelIO JobModel; + using JobModel = Task::Job::ModelIO; }; class DrawLight { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - typedef Job::Model JobModel; + using JobModel = Task::Job::Model; }; -class DrawBackground { -public: - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - - - typedef Job::Model JobModel; -}; - - -class DrawSceneTask : public Task { -public: - - DrawSceneTask(); - ~DrawSceneTask(); - - Jobs _jobs; - - virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - -}; - - -// A map of ItemIDs allowing to create bucket lists of SHAPE type items which are filtered by their -// Material -class ItemMaterialBucketMap : public std::map { -public: - - ItemMaterialBucketMap() {} - - void insert(const ItemID& id, const model::MaterialKey& key); - - // standard builders allocating the main buckets - void allocateStandardMaterialBuckets(); -}; -void materialSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); - } -#endif // hifi_render_Task_h +#endif // hifi_render_DrawTask_h diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index 6d065a3c58..aa5816475a 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -8,26 +8,11 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + #include "Engine.h" -#include "DrawTask.h" using namespace render; -RenderContext::RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode) - : _deferredDebugMode{ deferredDebugMode }, _deferredDebugSize{ deferredDebugSize }, - _args{ nullptr }, - _drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect }, -_items{ items }, _tone{ tone }, _ambientOcclusion{ ao } {} - -void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned) { - _occlusionStatus = occlusion; - _fxaaStatus = fxaa; - - if (showOwned) { - _drawStatus |= render::showNetworkStatusFlag; - } -}; - Engine::Engine() : _sceneContext(std::make_shared()), _renderContext(std::make_shared()) @@ -49,16 +34,8 @@ void Engine::addTask(const TaskPointer& task) { } void Engine::run() { + // TODO: Tasks will need to be specified such that their data can feed into each other for (auto task : _tasks) { task->run(_sceneContext, _renderContext); } } - -void Engine::buildStandardTaskPipeline() { - if (!_tasks.empty()) { - _tasks.clear(); - } - - addTask(std::make_shared()); -} - diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index bf77081502..fa01ef6018 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -12,123 +12,11 @@ #ifndef hifi_render_Engine_h #define hifi_render_Engine_h -#include "Scene.h" +#include "Context.h" +#include "Task.h" namespace render { - -class SceneContext { -public: - ScenePointer _scene; - - SceneContext() {} -}; -using SceneContextPointer = std::shared_ptr; - -// see examples/utilities/tools/renderEngineDebug.js -const int showDisplayStatusFlag = 1; -const int showNetworkStatusFlag = 2; - - -class RenderContext { -public: - class ItemsConfig { - public: - class Counter { - public: - Counter() {}; - Counter(const Counter& counter) { - numFeed = numDrawn = 0; - maxDrawn = counter.maxDrawn; - }; - - void setCounts(const Counter& counter) { - numFeed = counter.numFeed; - numDrawn = counter.numDrawn; - }; - - int numFeed = 0; - int numDrawn = 0; - int maxDrawn = -1; - }; - - class State : public Counter { - public: - bool render = true; - bool cull = true; - bool sort = true; - - Counter counter{}; - }; - - ItemsConfig(State opaqueState, State transparentState, Counter overlay3DCounter) - : opaque{ opaqueState }, transparent{ transparentState }, overlay3D{ overlay3DCounter } {} - ItemsConfig() : ItemsConfig{ {}, {}, {} } {} - - // TODO: If member count increases, store counters in a map instead of multiple members - State opaque{}; - State transparent{}; - Counter overlay3D{}; - }; - - class Tone { - public: - int toneCurve = 1; // Means just Gamma 2.2 correction - float exposure = 0.0; - }; - - class AmbientOcclusion { - public: - float radius = 0.5f; // radius in meters of the AO effect - float level = 0.5f; // Level of the obscrance value - }; - - RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode); - RenderContext() : RenderContext({}, {}, {}, {}, {}, {}, {}) {}; - - void setArgs(RenderArgs* args) { _args = args; } - inline RenderArgs* getArgs() { return _args; } - inline ItemsConfig& getItemsConfig() { return _items; } - inline Tone& getTone() { return _tone; } - inline AmbientOcclusion& getAmbientOcclusion() { return _ambientOcclusion; } - inline int getDrawStatus() { return _drawStatus; } - inline bool getDrawHitEffect() { return _drawHitEffect; } - inline bool getOcclusionStatus() { return _occlusionStatus; } - inline bool getFxaaStatus() { return _fxaaStatus; } - void setOptions(bool occlusion, bool fxaa, bool showOwned); - - // Debugging - int _deferredDebugMode; - glm::vec4 _deferredDebugSize; - -protected: - RenderArgs* _args; - - // Options - int _drawStatus; // bitflag - bool _drawHitEffect; - bool _occlusionStatus = false; - bool _fxaaStatus = false; - - ItemsConfig _items; - Tone _tone; - AmbientOcclusion _ambientOcclusion; -}; -typedef std::shared_ptr RenderContextPointer; - -// The base class for a task that runs on the SceneContext -class Task { -public: - Task() {} - ~Task() {} - - virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {} - -protected: -}; -typedef std::shared_ptr TaskPointer; -typedef std::vector Tasks; - // The root of the tasks, the Engine, should not be known from the Tasks, // The SceneContext is what navigates from the engine down to the Tasks class Engine { @@ -150,11 +38,7 @@ public: void run(); - // standard pipeline of tasks - void buildStandardTaskPipeline(); - protected: - Tasks _tasks; SceneContextPointer _sceneContext; @@ -165,3 +49,4 @@ typedef std::shared_ptr EnginePointer; } #endif // hifi_render_Engine_h + diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h new file mode 100644 index 0000000000..4d2a3728c6 --- /dev/null +++ b/libraries/render/src/render/Task.h @@ -0,0 +1,227 @@ +// +// Task.h +// render/src/render +// +// Created by Zach Pomerantz on 1/6/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_Task_h +#define hifi_render_Task_h + +#include "Context.h" + +#include "gpu/Batch.h" +#include + +namespace render { + +// A varying piece of data, to be used as Job/Task I/O +// TODO: Task IO +class Varying { +public: + Varying() {} + Varying(const Varying& var) : _concept(var._concept) {} + template Varying(const T& data) : _concept(std::make_shared>(data)) {} + + template T& edit() { return std::static_pointer_cast>(_concept)->_data; } + template const T& get() { return std::static_pointer_cast>(_concept)->_data; } + +protected: + class Concept { + public: + virtual ~Concept() = default; + }; + template class Model : public Concept { + public: + using Data = T; + + Model(const Data& data) : _data(data) {} + virtual ~Model() = default; + + Data _data; + }; + + std::shared_ptr _concept; +}; + +// FIXME: In c++17, use default classes of nullptr_t to combine these +template void jobRun(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + jobModel.run(sceneContext, renderContext); +} +template void jobRunI(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input) { + jobModel.run(sceneContext, renderContext, input); +} +template void jobRunO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, O& output) { + jobModel.run(sceneContext, renderContext, output); +} +template void jobRunIO(T& jobModel, const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const I& input, O& output) { + jobModel.run(sceneContext, renderContext, input, output); +} + +// The base class for a task that runs on the SceneContext +class Task { +public: + // The guts of a task; tasks are composed of multiple Jobs that execute serially + class Job { + public: + friend class Task; + + // The guts of a job; jobs are composed of a concept + class Concept { + public: + Concept() = default; + virtual ~Concept() = default; + + bool isEnabled() const { return _isEnabled; } + void setEnabled(bool isEnabled) { _isEnabled = isEnabled; } + + virtual const Varying getInput() const { return Varying(); } + virtual const Varying getOutput() const { return Varying(); } + virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) = 0; + + protected: + + bool _isEnabled = true; + }; + using ConceptPointer = std::shared_ptr; + + + template class Model : public Concept { + public: + typedef T Data; + + Data _data; + + Model() {} + Model(Data data): _data(data) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRun(_data, sceneContext, renderContext); + } + } + }; + + template class ModelI : public Concept { + public: + typedef T Data; + typedef I Input; + + Data _data; + Varying _input; + + const Varying getInput() const { return _input; } + + ModelI(const Varying& input, Data data = Data()) : _data(data), _input(input) {} + ModelI(Data data) : _data(data) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunI(_data, sceneContext, renderContext, _input.get()); + } + } + }; + + template class ModelO : public Concept { + public: + typedef T Data; + typedef O Output; + + Data _data; + Varying _output; + + const Varying getOutput() const { return _output; } + + ModelO(Data data) : _data(data), _output(Output()) {} + ModelO() : _output(Output()) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunO(_data, sceneContext, renderContext, _output.edit()); + } + } + }; + + template class ModelIO : public Concept { + public: + typedef T Data; + typedef I Input; + typedef O Output; + + Data _data; + Varying _input; + Varying _output; + + const Varying getInput() const { return _input; } + const Varying getOutput() const { return _output; } + + ModelIO(const Varying& input, Data data = Data()) : _data(data), _input(input), _output(Output()) {} + ModelIO(Data data) : _data(data), _output(Output()) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + if (isEnabled()) { + jobRunIO(_data, sceneContext, renderContext, _input.get(), _output.edit()); + } + } + }; + + Job(ConceptPointer concept) : _concept(concept) {} + Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} + + bool isEnabled() const { return _concept->isEnabled(); } + void setEnabled(bool isEnabled) { _concept->setEnabled(isEnabled); } + + const Varying getInput() const { return _concept->getInput(); } + const Varying getOutput() const { return _concept->getOutput(); } + + template T& edit() { + auto concept = std::static_pointer_cast(_concept); + assert(concept); + return concept->_data; + } + template const T& get() const { + auto concept = std::static_pointer_cast(_concept); + assert(concept); + return concept->_data; + } + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + PerformanceTimer perfTimer(_name.c_str()); + PROFILE_RANGE(_name.c_str()); + + _concept->run(sceneContext, renderContext); + } + protected: + ConceptPointer _concept; + std::string _name = ""; + + }; + using Jobs = std::vector; + +public: + Task() = default; + virtual ~Task() = default; + + // Queue a new job to the task; returns the job's index + template size_t addJob(std::string name, A&&... args) { + _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); + return _jobs.size() - 1; + } + + const Job& getJob(size_t i) const { return _jobs.at(i); } + + virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {} + +protected: + Jobs _jobs; +}; +typedef std::shared_ptr TaskPointer; +typedef std::vector Tasks; + +} + +#endif // hifi_render_Task_h diff --git a/plugins/hifiNeuron/src/NeuronPlugin.h b/plugins/hifiNeuron/src/NeuronPlugin.h index c85a5dd383..33c6879f5b 100644 --- a/plugins/hifiNeuron/src/NeuronPlugin.h +++ b/plugins/hifiNeuron/src/NeuronPlugin.h @@ -28,7 +28,7 @@ public: // Plugin functions virtual bool isSupported() const override; virtual bool isJointController() const override { return true; } - const QString& getName() const override { return NAME; } + virtual const QString& getName() const override { return NAME; } const QString& getID() const override { return NEURON_ID_STRING; } virtual void activate() override; diff --git a/plugins/hifiSdl2/src/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h index 61e2d37fd5..6506cdccb6 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -29,7 +29,7 @@ public: // Plugin functions virtual bool isSupported() const override; virtual bool isJointController() const override { return false; } - const QString& getName() const override { return NAME; } + virtual const QString& getName() const override { return NAME; } virtual void init() override; virtual void deinit() override; diff --git a/plugins/hifiSixense/src/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h index 753974e996..bbb9774368 100644 --- a/plugins/hifiSixense/src/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -29,8 +29,8 @@ public: // Plugin functions virtual bool isSupported() const override; virtual bool isJointController() const override { return true; } - const QString& getName() const override { return NAME; } - const QString& getID() const override { return HYDRA_ID_STRING; } + virtual const QString& getName() const override { return NAME; } + virtual const QString& getID() const override { return HYDRA_ID_STRING; } virtual void activate() override; virtual void deactivate() override; diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.cpp b/plugins/oculus/src/OculusDebugDisplayPlugin.cpp index 26bb3cf9b2..94a3670e4b 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.cpp @@ -10,10 +10,6 @@ const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)"); -const QString & OculusDebugDisplayPlugin::getName() const { - return NAME; -} - static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS"); static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS"); diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.h b/plugins/oculus/src/OculusDebugDisplayPlugin.h index 04b68704cc..c62fe12c73 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.h +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.h @@ -11,7 +11,8 @@ class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin { public: - virtual const QString & getName() const override; + virtual const QString& getName() const override { return NAME; } + virtual grouping getGrouping() const override { return DEVELOPER; } virtual bool isSupported() const override; protected: diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index c8fb0ba080..3002c746a2 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -138,10 +138,6 @@ private: const QString OculusDisplayPlugin::NAME("Oculus Rift"); -const QString & OculusDisplayPlugin::getName() const { - return NAME; -} - static const QString MONO_PREVIEW = "Mono Preview"; static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate"; diff --git a/plugins/oculus/src/OculusDisplayPlugin.h b/plugins/oculus/src/OculusDisplayPlugin.h index 03c9ba7511..98535a1790 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.h +++ b/plugins/oculus/src/OculusDisplayPlugin.h @@ -17,7 +17,7 @@ const float TARGET_RATE_Oculus = 75.0f; class OculusDisplayPlugin : public OculusBaseDisplayPlugin { public: virtual void activate() override; - virtual const QString & getName() const override; + virtual const QString& getName() const override { return NAME; } virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) override final; virtual float getTargetFrameRate() override { return TARGET_RATE_Oculus; } diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp index f0f200fe1a..4bded4e58f 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.cpp @@ -26,11 +26,7 @@ using namespace oglplus; -const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift (0.5) (Simulated)"); - -const QString & OculusLegacyDisplayPlugin::getName() const { - return NAME; -} +const QString OculusLegacyDisplayPlugin::NAME("Oculus Rift (0.5) (Legacy)"); OculusLegacyDisplayPlugin::OculusLegacyDisplayPlugin() { } diff --git a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h index cd1177b581..1ba288cc65 100644 --- a/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h +++ b/plugins/oculusLegacy/src/OculusLegacyDisplayPlugin.h @@ -19,7 +19,7 @@ class OculusLegacyDisplayPlugin : public WindowOpenGLDisplayPlugin { public: OculusLegacyDisplayPlugin(); virtual bool isSupported() const override; - virtual const QString & getName() const override; + virtual const QString& getName() const override { return NAME; } virtual void activate() override; virtual void deactivate() override; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 58f7536856..7fb70180c4 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -31,10 +31,6 @@ const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)"); const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here -const QString & OpenVrDisplayPlugin::getName() const { - return NAME; -} - static vr::IVRCompositor* _compositor{ nullptr }; vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 8186e59936..e290368de0 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -18,7 +18,7 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device p class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin { public: virtual bool isSupported() const override; - virtual const QString & getName() const override; + virtual const QString& getName() const override { return NAME; } virtual bool isHmd() const override { return true; } virtual float getTargetFrameRate() override { return TARGET_RATE_OpenVr; }