From bc41be7ec1eec7a285d4de51a39fcf9e279620a0 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 9 May 2017 17:10:05 -0700 Subject: [PATCH] Introucing the BackgroundStage to manage the background / skybox in one place --- .../src/RenderableZoneEntityItem.cpp | 39 ++++- libraries/render-utils/CMakeLists.txt | 2 +- .../render-utils/src/BackgroundStage.cpp | 142 ++++++++++++++++++ libraries/render-utils/src/BackgroundStage.h | 80 ++++++++++ .../src/DeferredLightingEffect.cpp | 13 ++ .../render-utils/src/DeferredLightingEffect.h | 14 ++ .../render-utils/src/RenderDeferredTask.cpp | 7 +- plugins/openvr/CMakeLists.txt | 2 +- tests/render-perf/CMakeLists.txt | 2 +- 9 files changed, 289 insertions(+), 12 deletions(-) create mode 100644 libraries/render-utils/src/BackgroundStage.cpp create mode 100644 libraries/render-utils/src/BackgroundStage.h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 55d47dde98..074f78ef09 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -26,6 +26,8 @@ #include #include "DeferredLightingEffect.h" +#include + class RenderableZoneEntityItemMeta { public: RenderableZoneEntityItemMeta(EntityItemPointer entity); @@ -45,7 +47,8 @@ public: model::LightPointer editSunLight() { _needSunUpdate = true; return _sunLight; } model::LightPointer editAmbientLight() { _needAmbientUpdate = true; return _ambientLight; } - model::SkyboxPointer editSkybox() { _needSkyboxUpdate = true; return _skybox; } + model::SunSkyStagePointer editBackground() { _needBackgroundUpdate = true; return _background; } + model::SkyboxPointer editSkybox() { return editBackground()->getSkybox(); } void setAmbientURL(const QString& ambientUrl); @@ -56,16 +59,19 @@ protected: model::LightPointer _sunLight; model::LightPointer _ambientLight; - model::SkyboxPointer _skybox; + model::SunSkyStagePointer _background; LightStagePointer _stage; LightStage::Index _sunIndex { LightStage::INVALID_INDEX }; LightStage::Index _ambientIndex { LightStage::INVALID_INDEX }; + BackgroundStagePointer _backgroundStage; + BackgroundStage::Index _backgroundIndex { BackgroundStage::INVALID_INDEX }; + bool _needUpdate { true }; bool _needSunUpdate { true }; bool _needAmbientUpdate { true }; - bool _needSkyboxUpdate { true }; + bool _needBackgroundUpdate { true }; bool _isVisible { true }; @@ -356,7 +362,7 @@ void RenderableZoneEntityItem::updateKeyAmbientFromEntity(RenderableZoneEntityIt } void RenderableZoneEntityItem::updateKeyBackgroundFromEntity(RenderableZoneEntityItemMeta& keyZonePayload) { - auto skybox = keyZonePayload.editSkybox(); + auto background = keyZonePayload.editBackground(); this->getBackgroundMode(); @@ -436,8 +442,10 @@ RenderableZoneEntityItemMeta::RenderableZoneEntityItemMeta(EntityItemPointer ent entity(entity), _sunLight(std::make_shared()), _ambientLight(std::make_shared()), - _skybox(std::make_shared()) -{} + _background(std::make_shared()) +{ + _background->setSkybox(std::make_shared()); +} RenderableZoneEntityItemMeta::~RenderableZoneEntityItemMeta() { @@ -450,6 +458,12 @@ RenderableZoneEntityItemMeta::~RenderableZoneEntityItemMeta() { } } + + if (_backgroundStage) { + if (!BackgroundStage::isIndexInvalid(_backgroundIndex)) { + _backgroundStage->removeBackground(_backgroundIndex); + } + } } void RenderableZoneEntityItemMeta::setAmbientURL(const QString& ambientUrl) { @@ -541,6 +555,10 @@ void RenderableZoneEntityItemMeta::render(RenderArgs* args) { _stage = DependencyManager::get()->getLightStage(); } + if (!_backgroundStage) { + _backgroundStage = DependencyManager::get()->getBackgroundStage(); + } + { // Sun // Need an update ? if (_needSunUpdate) { @@ -572,11 +590,20 @@ void RenderableZoneEntityItemMeta::render(RenderArgs* args) { { // Skybox updateSkyboxMap(); + if (_needBackgroundUpdate) { + if (BackgroundStage::isIndexInvalid(_backgroundIndex)) { + _backgroundIndex = _backgroundStage->addBackground(_background); + } else { + + } + _needBackgroundUpdate = false; + } } if (isVisible()) { // FInally, push the light visible in the frame _stage->_currentFrame.pushSunLight(_sunIndex); _stage->_currentFrame.pushAmbientLight(_ambientIndex); + _backgroundStage->_currentFrame.pushBackground(_backgroundIndex); } } diff --git a/libraries/render-utils/CMakeLists.txt b/libraries/render-utils/CMakeLists.txt index 454097233a..c359924e0d 100644 --- a/libraries/render-utils/CMakeLists.txt +++ b/libraries/render-utils/CMakeLists.txt @@ -3,7 +3,7 @@ AUTOSCRIBE_SHADER_LIB(gpu model render) # pull in the resources.qrc file qt5_add_resources(QT_RESOURCES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/res/fonts/fonts.qrc") setup_hifi_library(Widgets OpenGL Network Qml Quick Script) -link_hifi_libraries(shared ktx gpu model model-networking render animation fbx entities image) +link_hifi_libraries(shared ktx gpu model model-networking render animation fbx entities image procedural) if (NOT ANDROID) target_nsight() diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp new file mode 100644 index 0000000000..b25f5effd8 --- /dev/null +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -0,0 +1,142 @@ +// +// BackgroundStage.cpp +// +// Created by Sam Gateau on 5/9/2017. +// 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 "BackgroundStage.h" + +#include "DeferredLightingEffect.h" + +#include + +BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const { + auto found = _backgroundMap.find(background); + if (found != _backgroundMap.end()) { + return INVALID_INDEX; + } else { + return (*found).second; + } + +} + +BackgroundStage::Index BackgroundStage::addBackground(const BackgroundPointer& background) { + + auto found = _backgroundMap.find(background); + if (found == _backgroundMap.end()) { + auto backgroundId = _backgrounds.newElement(background); + // Avoid failing to allocate a background, just pass + if (backgroundId != INVALID_INDEX) { + + // Insert the background and its index in the reverse map + _backgroundMap.insert(BackgroundMap::value_type(background, backgroundId)); + } + return backgroundId; + } else { + return (*found).second; + } +} + + +BackgroundStage::BackgroundPointer BackgroundStage::removeBackground(Index index) { + BackgroundPointer removed = _backgrounds.freeElement(index); + + if (removed) { + _backgroundMap.erase(removed); + } + return removed; +} + + +void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + + const auto& lightingModel = inputs; + if (!lightingModel->isBackgroundEnabled()) { + return; + } + + + // Background rendering decision + auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + model::SunSkyStagePointer background; + model::SkyboxPointer skybox; + if (backgroundStage->_currentFrame._backgrounds.size()) { + auto backgroundId = backgroundStage->_currentFrame._backgrounds.front(); + auto background = backgroundStage->getBackground(backgroundId); + if (background) { + skybox = background->getSkybox(); + } + } else { + skybox = DependencyManager::get()->getDefaultSkybox(); + } + + /* auto backgroundMode = skyStage->getBackgroundMode(); + + switch (backgroundMode) { + case model::SunSkyStage::SKY_DEFAULT: { + auto scene = DependencyManager::get()->getStage(); + auto sceneKeyLight = scene->getKeyLight(); + + scene->setSunModelEnable(false); + sceneKeyLight->setColor(ColorUtils::toVec3(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_COLOR)); + sceneKeyLight->setIntensity(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_INTENSITY); + sceneKeyLight->setAmbientIntensity(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_AMBIENT_INTENSITY); + sceneKeyLight->setDirection(KeyLightPropertyGroup::DEFAULT_KEYLIGHT_DIRECTION); + // fall through: render a skybox (if available), or the defaults (if requested) + } + + case model::SunSkyStage::SKY_BOX: {*/ + if (skybox && !skybox->empty()) { + PerformanceTimer perfTimer("skybox"); + auto args = renderContext->args; + + gpu::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->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + skybox->render(batch, args->getViewFrustum()); + }); + args->_batch = nullptr; + gpu::Batch& batch = *args->_batch; + + // break; + } + // fall through: render defaults (if requested) +// } +/* + case model::SunSkyStage::SKY_DEFAULT_AMBIENT_TEXTURE: { + if (Menu::getInstance()->isOptionChecked(MenuOption::DefaultSkybox)) { + auto scene = DependencyManager::get()->getStage(); + auto sceneKeyLight = scene->getKeyLight(); + auto defaultSkyboxAmbientTexture = qApp->getDefaultSkyboxAmbientTexture(); + if (defaultSkyboxAmbientTexture) { + sceneKeyLight->setAmbientSphere(defaultSkyboxAmbientTexture->getIrradiance()); + sceneKeyLight->setAmbientMap(defaultSkyboxAmbientTexture); + } else { + static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex( + "Failed to get a valid Default Skybox Ambient Texture ? probably because it couldn't be find during initialization step"); + } + // fall through: render defaults skybox + } else { + break; + } + } + + + backgroundStage->_currentFrame.clear(); +} \ No newline at end of file diff --git a/libraries/render-utils/src/BackgroundStage.h b/libraries/render-utils/src/BackgroundStage.h new file mode 100644 index 0000000000..1dd1651c98 --- /dev/null +++ b/libraries/render-utils/src/BackgroundStage.h @@ -0,0 +1,80 @@ +// +// BackgroundStage.h + +// Created by Sam Gateau on 5/9/2017. +// 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_utils_BackgroundStage_h +#define hifi_render_utils_BackgroundStage_h + +#include +#include +#include +#include + +#include "LightingModel.h" + + +// Background stage to set up background-related rendering tasks +class BackgroundStage { +public: + using Index = render::indexed_container::Index; + static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; + static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } + + using BackgroundPointer = model::SunSkyStagePointer; + using Backgrounds = render::indexed_container::IndexedPointerVector; + using BackgroundMap = std::unordered_map; + + using BackgroundIndices = std::vector; + + + Index findBackground(const BackgroundPointer& background) const; + Index addBackground(const BackgroundPointer& background); + + BackgroundPointer removeBackground(Index index); + + bool checkBackgroundId(Index index) const { return _backgrounds.checkIndex(index); } + + Index getNumBackgrounds() const { return _backgrounds.getNumElements(); } + Index getNumFreeBackgrounds() const { return _backgrounds.getNumFreeIndices(); } + Index getNumAllocatedBackgrounds() const { return _backgrounds.getNumAllocatedIndices(); } + + BackgroundPointer getBackground(Index backgroundId) const { + return _backgrounds.get(backgroundId); + } + + Backgrounds _backgrounds; + BackgroundMap _backgroundMap; + + class Frame { + public: + Frame() {} + + void clear() { _backgrounds.clear(); } + + void pushBackground(BackgroundStage::Index index) { _backgrounds.emplace_back(index); } + + BackgroundStage::BackgroundIndices _backgrounds; + }; + + Frame _currentFrame; +}; +using BackgroundStagePointer = std::shared_ptr; + + +class DrawBackgroundStage { +public: + using Inputs = LightingModelPointer; + using JobModel = render::Job::ModelI; + + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + +protected: +}; + +#endif diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 947d0d502c..96f92758ea 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -141,6 +141,19 @@ void DeferredLightingEffect::init() { _globalLights.push_back(_lightStage->addLight(lp)); _lightStage->addShadow(_globalLights[0]); + + _backgroundStage = std::make_shared(); + + auto textureCache = DependencyManager::get(); + + QString skyboxUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-cubemap.jpg" }; + QString skyboxAmbientUrl { PathUtils::resourcesPath() + "images/Default-Sky-9-ambient.jpg" }; + + _defaultSkyboxTexture = textureCache->getImageTexture(skyboxUrl, image::TextureUsage::CUBE_TEXTURE, { { "generateIrradiance", false } }); + _defaultSkyboxAmbientTexture = textureCache->getImageTexture(skyboxAmbientUrl, image::TextureUsage::CUBE_TEXTURE, { { "generateIrradiance", true } }); + + _defaultSkybox->setCubemap(_defaultSkyboxTexture); + } void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 02f759bab3..63895c2ec9 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -20,6 +20,8 @@ #include "model/Light.h" #include "model/Geometry.h" +#include + #include #include "DeferredFrameTransform.h" @@ -28,11 +30,13 @@ #include "LightStage.h" #include "LightClusters.h" +#include "BackgroundEffect.h" #include "SurfaceGeometryPass.h" #include "SubsurfaceScattering.h" #include "AmbientOcclusionEffect.h" + class RenderArgs; struct LightLocations; using LightLocationsPtr = std::shared_ptr; @@ -51,15 +55,21 @@ public: void setGlobalLight(const model::LightPointer& light); const LightStagePointer& getLightStage() { return _lightStage; } + const BackgroundStagePointer& getBackgroundStage() { return _backgroundStage; } void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } + model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } + gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; } + gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; } + private: DeferredLightingEffect() = default; LightStagePointer _lightStage; + BackgroundStagePointer _backgroundStage; bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; @@ -103,6 +113,10 @@ private: Lights _allocatedLights; std::vector _globalLights; + model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; + gpu::TexturePointer _defaultSkyboxTexture; + gpu::TexturePointer _defaultSkyboxAmbientTexture; + friend class LightClusteringPass; friend class RenderDeferredSetup; friend class RenderDeferredLocals; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 693c150004..4264cfb424 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -139,9 +139,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("RenderDeferred", deferredLightingInputs); // Use Stencil and draw background in Lighting buffer to complete filling in the opaque - const auto backgroundInputs = DrawBackgroundDeferred::Inputs(background, lightingModel).hasVarying(); - task.addJob("DrawBackgroundDeferred", backgroundInputs); - + //const auto backgroundInputs = DrawBackgroundDeferred::Inputs(background, lightingModel).hasVarying(); + //task.addJob("DrawBackgroundDeferred", backgroundInputs); + + task.addJob("DrawBackgroundDeferred", lightingModel); // Render transparent objects forward in LightingBuffer const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).hasVarying(); diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index bc62117e70..af65f3dbf7 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -13,7 +13,7 @@ if (WIN32) setup_hifi_plugin(OpenGL Script Qml Widgets) link_hifi_libraries(shared gl networking controllers ui plugins display-plugins ui-plugins input-plugins script-engine - render-utils model gpu gpu-gl render model-networking fbx ktx image) + render-utils model gpu gpu-gl render model-networking fbx ktx image procedural) include_hifi_library_headers(octree) diff --git a/tests/render-perf/CMakeLists.txt b/tests/render-perf/CMakeLists.txt index 1e85dd3ea8..553e7c06e7 100644 --- a/tests/render-perf/CMakeLists.txt +++ b/tests/render-perf/CMakeLists.txt @@ -10,7 +10,7 @@ setup_hifi_project(Quick Gui OpenGL) set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "Tests/manual-tests/") # link in the shared libraries -link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics image) +link_hifi_libraries(shared octree ktx gl gpu gpu-gl render model model-networking networking render-utils fbx entities entities-renderer animation audio avatars script-engine physics image procedural) package_libraries_for_deployment()