diff --git a/interface/resources/config/render.json b/interface/resources/config/render.json index b5b72d7d07..2c63c08510 100644 --- a/interface/resources/config/render.json +++ b/interface/resources/config/render.json @@ -1,16 +1,2 @@ { - "RenderMainView": { - "RenderShadowTask": { - "Enabled": { - "enabled": true - } - }, - "RenderDeferredTask": { - "AmbientOcclusion": { - "Enabled": { - "enabled": true - } - } - } - } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a3c854d883..140d2a7ccc 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -48,6 +48,7 @@ #include "DeferredLightingEffect.h" #include "PickManager.h" +#include "LightingModel.h" #include "AmbientOcclusionEffect.h" #include "RenderShadowTask.h" #include "AntialiasingEffect.h" @@ -393,13 +394,9 @@ Menu::Menu() { connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { - auto mainViewShadowTaskConfig = renderConfig->getConfig("RenderMainView.RenderShadowTask"); - if (mainViewShadowTaskConfig) { - if (action->isChecked()) { - mainViewShadowTaskConfig->setPreset("Enabled"); - } else { - mainViewShadowTaskConfig->setPreset("None"); - } + auto lightingModelConfig = renderConfig->getConfig("RenderMainView.LightingModel"); + if (lightingModelConfig) { + lightingModelConfig->setShadow(action->isChecked()); } } }); @@ -408,15 +405,11 @@ Menu::Menu() { connect(action, &QAction::triggered, [action] { auto renderConfig = qApp->getRenderEngine()->getConfiguration(); if (renderConfig) { - auto mainViewAmbientOcclusionConfig = renderConfig->getConfig("RenderMainView.AmbientOcclusion"); - if (mainViewAmbientOcclusionConfig) { - if (action->isChecked()) { - mainViewAmbientOcclusionConfig->setPreset("Enabled"); - } else { - mainViewAmbientOcclusionConfig->setPreset("None"); - } + auto lightingModelConfig = renderConfig->getConfig("RenderMainView.LightingModel"); + if (lightingModelConfig) { + lightingModelConfig->setAmbientOcclusion(action->isChecked()); } - } + } }); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes); diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 81944ec747..12c9636746 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -270,14 +271,8 @@ public: void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { const auto cachedArg = task.addJob("SecondaryCamera"); - const auto items = task.addJob("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); - assert(items.canCast()); - if (isDeferred) { - const render::Varying cascadeSceneBBoxes; - const auto renderInput = RenderDeferredTask::Input(items, cascadeSceneBBoxes).asVarying(); - task.addJob("RenderDeferredTask", renderInput, false); - } else { - task.addJob("Forward", items); - } + + task.addJob("RenderSecondView", cullFunctor, isDeferred, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1); + task.addJob("EndSecondaryCamera", cachedArg); } \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 2c017da71d..232e6efa67 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -27,8 +27,6 @@ // Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1 // is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down. static const float SPHERE_ENTITY_SCALE = 0.5f; -static const unsigned int SUN_SHADOW_CASCADE_COUNT{ 4 }; -static const float SUN_SHADOW_MAX_DISTANCE{ 40.0f }; using namespace render; using namespace render::entities; @@ -43,7 +41,6 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity if (!LightStage::isIndexInvalid(_sunIndex)) { _stage->removeLight(_sunIndex); _sunIndex = INVALID_INDEX; - _shadowIndex = INVALID_INDEX; } if (!LightStage::isIndexInvalid(_ambientIndex)) { _stage->removeLight(_ambientIndex); @@ -74,36 +71,6 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity } void ZoneEntityRenderer::doRender(RenderArgs* args) { -#if 0 - if (ZoneEntityItem::getDrawZoneBoundaries()) { - switch (_entity->getShapeType()) { - case SHAPE_TYPE_BOX: - case SHAPE_TYPE_SPHERE: - { - PerformanceTimer perfTimer("zone->renderPrimitive"); - static const glm::vec4 DEFAULT_COLOR(1.0f, 1.0f, 1.0f, 1.0f); - if (!updateModelTransform()) { - break; - } - auto geometryCache = DependencyManager::get(); - gpu::Batch& batch = *args->_batch; - batch.setModelTransform(_modelTransform); - if (_entity->getShapeType() == SHAPE_TYPE_SPHERE) { - geometryCache->renderWireSphereInstance(args, batch, DEFAULT_COLOR); - } else { - geometryCache->renderWireCubeInstance(args, batch, DEFAULT_COLOR); - } - } - break; - - // Compund shapes are handled by the _model member - case SHAPE_TYPE_COMPOUND: - default: - // Not handled - break; - } - } -#endif if (!_stage) { _stage = args->_scene->getStage(); assert(_stage); @@ -130,7 +97,6 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_sunIndex)) { _sunIndex = _stage->addLight(_sunLight); - _shadowIndex = _stage->addShadow(_sunIndex, SUN_SHADOW_MAX_DISTANCE, SUN_SHADOW_CASCADE_COUNT); } else { _stage->updateLightArrayBuffer(_sunIndex); } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.h b/libraries/entities-renderer/src/RenderableZoneEntityItem.h index 3e2690e1bd..32b5cf94a0 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.h +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.h @@ -99,7 +99,6 @@ private: ComponentMode _bloomMode { COMPONENT_MODE_INHERIT }; indexed_container::Index _sunIndex { LightStage::INVALID_INDEX }; - indexed_container::Index _shadowIndex { LightStage::INVALID_INDEX }; indexed_container::Index _ambientIndex { LightStage::INVALID_INDEX }; BackgroundStagePointer _backgroundStage; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp index 2c2a4e254c..555a0a1e41 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendTransform.cpp @@ -29,9 +29,9 @@ void GLBackend::do_setProjectionTransform(const Batch& batch, size_t paramOffset } void GLBackend::do_setProjectionJitter(const Batch& batch, size_t paramOffset) { - _transform._projectionJitter.x = batch._params[paramOffset]._float; - _transform._projectionJitter.y = batch._params[paramOffset+1]._float; - _transform._invalidProj = true; + _transform._projectionJitter.x = batch._params[paramOffset]._float; + _transform._projectionJitter.y = batch._params[paramOffset+1]._float; + _transform._invalidProj = true; } void GLBackend::do_setViewportTransform(const Batch& batch, size_t paramOffset) { diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index bbb370010e..b1ca24de1f 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -303,8 +303,6 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() { } void AmbientOcclusionEffect::configure(const Config& config) { - DependencyManager::get()->setAmbientOcclusionEnabled(config.isEnabled()); - bool shouldUpdateBlurs = false; bool shouldUpdateTechnique = false; @@ -591,14 +589,21 @@ void AmbientOcclusionEffect::updateJitterSamples() { } } -void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { +void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); RenderArgs* args = renderContext->args; - const auto& frameTransform = inputs.get0(); - const auto& linearDepthFramebuffer = inputs.get2(); + const auto& lightingModel = input.get0(); + + if (!lightingModel->isAmbientOcclusionEnabled()) { + output.edit0().reset(); + return; + } + + const auto& frameTransform = input.get1(); + const auto& linearDepthFramebuffer = input.get3(); const int resolutionLevel = _aoParametersBuffer->getResolutionLevel(); const auto depthResolutionLevel = getDepthResolutionLevel(); @@ -631,8 +636,8 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte auto occlusionFBO = _framebuffer->getOcclusionFramebuffer(); auto occlusionBlurredFBO = _framebuffer->getOcclusionBlurredFramebuffer(); - outputs.edit0() = _framebuffer; - outputs.edit1() = _aoParametersBuffer; + output.edit0() = _framebuffer; + output.edit1() = _aoParametersBuffer; auto occlusionPipeline = getOcclusionPipeline(); auto bilateralBlurPipeline = getBilateralBlurPipeline(); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index af6f6b21a3..65fc09a814 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -17,6 +17,7 @@ #include "render/DrawTask.h" +#include "LightingModel.h" #include "DeferredFrameTransform.h" #include "DeferredFramebuffer.h" #include "SurfaceGeometryPass.h" @@ -152,15 +153,15 @@ signals: class AmbientOcclusionEffect { public: - using Inputs = render::VaryingSet3; - using Outputs = render::VaryingSet2; + using Input = render::VaryingSet4; + using Output = render::VaryingSet2; using Config = AmbientOcclusionEffectConfig; - using JobModel = render::Job::ModelIO; + using JobModel = render::Job::ModelIO; AmbientOcclusionEffect(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); // Class describing the uniform buffer with all the parameters common to the AO shaders class AOParameters : public AmbientOcclusionParams { diff --git a/libraries/render-utils/src/AssembleLightingStageTask.cpp b/libraries/render-utils/src/AssembleLightingStageTask.cpp new file mode 100644 index 0000000000..589cdb31ea --- /dev/null +++ b/libraries/render-utils/src/AssembleLightingStageTask.cpp @@ -0,0 +1,50 @@ +// +// Created by Samuel Gateau on 2018/12/06 +// Copyright 2013-2018 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 "AssembleLightingStageTask.h" + +#include + +void FetchCurrentFrames::run(const render::RenderContextPointer& renderContext, Output& output) { + auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); + output.edit0() = std::make_shared(lightStage->_currentFrame); + + auto backgroundStage = renderContext->_scene->getStage(); + assert(backgroundStage); + output.edit1() = std::make_shared(backgroundStage->_currentFrame); + + auto hazeStage = renderContext->_scene->getStage(); + assert(hazeStage); + output.edit2() = std::make_shared(hazeStage->_currentFrame); + + auto bloomStage = renderContext->_scene->getStage(); + assert(bloomStage); + output.edit3() = std::make_shared(bloomStage->_currentFrame); +} + + +void AssembleLightingStageTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { + const auto& fetchCullSortOut = input.get(); + const auto& items = fetchCullSortOut.get0(); + //const auto& items = input.get(); + + const auto& lights = items[RenderFetchCullSortTask::LIGHT]; + const auto& metas = items[RenderFetchCullSortTask::META]; + + // Clear Light, Haze, Bloom, and Skybox Stages and render zones from the general metas bucket + const auto zones = task.addJob("ZoneRenderer", metas); + + // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. + task.addJob("DrawLight", lights); + + // Fetch the current frame stacks from all the stages + const auto currentStageFrames = task.addJob("FetchCurrentFrames"); + + output = Output(currentStageFrames, zones); +} + diff --git a/libraries/render-utils/src/AssembleLightingStageTask.h b/libraries/render-utils/src/AssembleLightingStageTask.h new file mode 100644 index 0000000000..9770af473c --- /dev/null +++ b/libraries/render-utils/src/AssembleLightingStageTask.h @@ -0,0 +1,44 @@ +// +// Created by Samuel Gateau on 2018/12/06 +// Copyright 2013-2018 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_AssembleLightingStageTask_h +#define hifi_AssembleLightingStageTask_h + +#include +#include "LightingModel.h" + +#include "LightStage.h" +#include "BackgroundStage.h" +#include "HazeStage.h" +#include "BloomStage.h" + +#include "ZoneRenderer.h" + + +class FetchCurrentFrames { +public: + using Output = render::VaryingSet4; + using JobModel = render::Job::ModelO; + + FetchCurrentFrames() {} + + void run(const render::RenderContextPointer& renderContext, Output& output); +}; + +class AssembleLightingStageTask { +public: + using Input = RenderFetchCullSortTask::Output; + using Output = render::VaryingSet2; + using JobModel = render::Task::ModelIO; + + AssembleLightingStageTask() {} + + void build(JobModel& task, const render::Varying& input, render::Varying& output); +}; + +#endif diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 9bdfdbcda6..01a9c055cc 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -403,7 +403,7 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I auto& ambientOcclusionFramebuffer = inputs.get3(); auto& velocityFramebuffer = inputs.get4(); auto& frameTransform = inputs.get5(); - auto& lightFrame = inputs.get6(); + auto& shadowFrame = inputs.get6(); gpu::doInBatch("DebugDeferredBuffer::run", args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); @@ -439,16 +439,14 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I batch.setResourceTexture(Textures::DebugTexture0, velocityFramebuffer->getVelocityTexture()); } - auto lightStage = renderContext->_scene->getStage(); - assert(lightStage); - assert(lightStage->getNumLights() > 0); - auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(*lightFrame); - const auto& globalShadow = lightAndShadow.second; - if (globalShadow) { - batch.setResourceTexture(Textures::Shadow, globalShadow->map); - batch.setUniformBuffer(UBOs::ShadowParams, globalShadow->getBuffer()); - batch.setUniformBuffer(UBOs::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); - batch.setUniformBuffer(UBOs::DebugDeferredParams, _parameters); + if (!shadowFrame->_objects.empty()) { + const auto& globalShadow = shadowFrame->_objects[0]; + if (globalShadow) { + batch.setResourceTexture(Textures::Shadow, globalShadow->map); + batch.setUniformBuffer(UBOs::ShadowParams, globalShadow->getBuffer()); + batch.setUniformBuffer(UBOs::DeferredFrameTransform, frameTransform->getFrameTransformBuffer()); + batch.setUniformBuffer(UBOs::DebugDeferredParams, _parameters); + } } if (linearDepthTarget) { diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index 8afccfca13..5ff3ab28c9 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -46,7 +46,7 @@ public: AmbientOcclusionFramebufferPointer, VelocityFramebufferPointer, DeferredFrameTransformPointer, - LightStage::FramePointer>; + LightStage::ShadowFramePointer>; using Config = DebugDeferredBufferConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index e0fd9e970d..ab9dea2325 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -374,11 +374,11 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, const DeferredFramebufferPointer& deferredFramebuffer, const LightingModelPointer& lightingModel, const LightStage::FramePointer& lightFrame, + const LightStage::ShadowFramePointer& shadowFrame, const HazeStage::FramePointer& hazeFrame, const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer, - const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource, - bool renderShadows) { + const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource) { auto args = renderContext->args; auto& batch = (*args->_batch); @@ -404,7 +404,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch.setResourceTexture(ru::Texture::DeferredDepth, deferredFramebuffer->getPrimaryDepthTexture()); // FIXME: Different render modes should have different tasks - if (args->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && deferredLightingEffect->isAmbientOcclusionEnabled() && ambientOcclusionFramebuffer) { + if (lightingModel->isAmbientOcclusionEnabled() && ambientOcclusionFramebuffer) { batch.setResourceTexture(ru::Texture::DeferredObscurance, ambientOcclusionFramebuffer->getOcclusionTexture()); } else { // need to assign the white texture if ao is off @@ -429,24 +429,23 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch.setResourceTexture(ru::Texture::SsscSpecularBeckmann, subsurfaceScatteringResource->getScatteringSpecular()); } - // Global directional light and ambient pass - + // Global directional light, maybe shadow and ambient pass auto lightStage = renderContext->_scene->getStage(); assert(lightStage); assert(lightStage->getNumLights() > 0); - auto lightAndShadow = lightStage->getCurrentKeyLightAndShadow(*lightFrame); - const auto& globalShadow = lightAndShadow.second; + auto keyLight = lightStage->getCurrentKeyLight(*lightFrame); - // Bind the shadow buffers - if (globalShadow) { - batch.setResourceTexture(ru::Texture::Shadow, globalShadow->map); + // Check if keylight casts shadows + bool keyLightCastShadows{ false }; + LightStage::ShadowPointer globalShadow; + if (lightingModel->isShadowEnabled() && shadowFrame && !shadowFrame->_objects.empty()) { + globalShadow = shadowFrame->_objects.front(); + if (globalShadow) { + keyLightCastShadows = true; + } } - auto program = deferredLightingEffect->_directionalSkyboxLight; - LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; - - auto keyLight = lightAndShadow.first; - + // Global Ambient light graphics::LightPointer ambientLight; if (lightStage && lightFrame->_ambientLights.size()) { ambientLight = lightStage->getLight(lightFrame->_ambientLights.front()); @@ -454,18 +453,10 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, bool hasAmbientMap = (ambientLight != nullptr); // Setup the global directional pass pipeline + auto program = deferredLightingEffect->_directionalSkyboxLight; + LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; { - // Check if keylight casts shadows - bool keyLightCastShadows { false }; - - if (renderShadows && lightStage && lightFrame->_sunLights.size()) { - graphics::LightPointer keyLight = lightStage->getLight(lightFrame->_sunLights.front()); - if (keyLight) { - keyLightCastShadows = keyLight->getCastShadows(); - } - } - - if (deferredLightingEffect->_shadowMapEnabled && keyLightCastShadows) { + if (keyLightCastShadows) { // If the keylight has an ambient Map then use the Skybox version of the pass // otherwise use the ambient sphere version @@ -488,7 +479,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, } } - if (locations->shadowTransform && globalShadow) { + if (keyLightCastShadows && globalShadow) { + batch.setResourceTexture(ru::Texture::Shadow, globalShadow->map); batch.setUniformBuffer(ru::Buffer::ShadowParams, globalShadow->getBuffer()); } @@ -510,10 +502,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch.draw(gpu::TRIANGLE_STRIP, 4); deferredLightingEffect->unsetKeyLightBatch(batch); - - for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { - batch.setResourceTexture(ru::Texture::Shadow +i, nullptr); - } + batch.setResourceTexture(ru::Texture::Shadow, nullptr); } } @@ -606,9 +595,7 @@ void RenderDeferredCleanup::run(const render::RenderContextPointer& renderContex } } -RenderDeferred::RenderDeferred(bool renderShadows): - _renderShadows(renderShadows) -{ +RenderDeferred::RenderDeferred() { DependencyManager::get()->init(); } @@ -616,18 +603,21 @@ void RenderDeferred::configure(const Config& config) { } void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) { + auto args = renderContext->args; auto deferredTransform = inputs.get0(); auto deferredFramebuffer = inputs.get1(); - auto lightingModel = inputs.get2(); - auto surfaceGeometryFramebuffer = inputs.get3(); - auto ssaoFramebuffer = inputs.get4(); - auto subsurfaceScatteringResource = inputs.get5(); - auto lightClusters = inputs.get6(); - auto args = renderContext->args; + auto extraRenderBuffers = inputs.get2(); + auto surfaceGeometryFramebuffer = extraRenderBuffers.get0(); + auto ssaoFramebuffer = extraRenderBuffers.get1(); + auto subsurfaceScatteringResource = extraRenderBuffers.get2(); - const auto& lightFrame = inputs.get7(); - const auto& hazeFrame = inputs.get8(); + auto lightingModel = inputs.get3(); + auto lightClusters = inputs.get4(); + + const auto& lightFrame = inputs.get5(); + const auto& shadowFrame = inputs.get6(); + const auto& hazeFrame = inputs.get7(); if (!_gpuTimer) { _gpuTimer = std::make_shared < gpu::RangeTimer>(__FUNCTION__); @@ -638,7 +628,7 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs args->_batch = &batch; _gpuTimer->begin(batch); - setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, lightFrame, hazeFrame, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource, _renderShadows); + setupJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, lightFrame, shadowFrame, hazeFrame, surfaceGeometryFramebuffer, ssaoFramebuffer, subsurfaceScatteringResource); lightsJob.run(renderContext, deferredTransform, deferredFramebuffer, lightingModel, surfaceGeometryFramebuffer, lightClusters); @@ -696,7 +686,6 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { // Add the global light to the light stage (for later shadow rendering) // Set this light to be the default _defaultLightID = lightStage->addLight(lp, true); - lightStage->addShadow(_defaultLightID); } auto backgroundStage = renderContext->_scene->getStage(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 9fd9554d31..f4935000ef 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -55,16 +55,9 @@ public: static void setupLocalLightsBatch(gpu::Batch& batch, const LightClustersPointer& lightClusters); static void unsetLocalLightsBatch(gpu::Batch& batch); - void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; - void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } - bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } - private: DeferredLightingEffect() = default; - bool _shadowMapEnabled{ true }; // note that this value is overwritten in the ::configure method - bool _ambientOcclusionEnabled{ false }; - graphics::MeshPointer _pointLightMesh; graphics::MeshPointer getPointLightMesh(); graphics::MeshPointer _spotLightMesh; @@ -146,11 +139,11 @@ public: const DeferredFramebufferPointer& deferredFramebuffer, const LightingModelPointer& lightingModel, const LightStage::FramePointer& lightFrame, + const LightStage::ShadowFramePointer& shadowFrame, const HazeStage::FramePointer& hazeFrame, const SurfaceGeometryFramebufferPointer& surfaceGeometryFramebuffer, const AmbientOcclusionFramebufferPointer& ambientOcclusionFramebuffer, - const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource, - bool renderShadows); + const SubsurfaceScatteringResourcePointer& subsurfaceScatteringResource); }; class RenderDeferredLocals { @@ -167,7 +160,6 @@ public: gpu::BufferView _localLightsBuffer; RenderDeferredLocals(); - }; @@ -182,14 +174,14 @@ using RenderDeferredConfig = render::GPUJobConfig; class RenderDeferred { public: - using Inputs = render::VaryingSet9< - DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, SurfaceGeometryFramebufferPointer, - AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer, LightClustersPointer, LightStage::FramePointer, HazeStage::FramePointer>; + using ExtraDeferredBuffer = render::VaryingSet3; + using Inputs = render::VaryingSet8< + DeferredFrameTransformPointer, DeferredFramebufferPointer, ExtraDeferredBuffer, LightingModelPointer, LightClustersPointer, LightStage::FramePointer, LightStage::ShadowFramePointer, HazeStage::FramePointer>; using Config = RenderDeferredConfig; using JobModel = render::Job::ModelI; - RenderDeferred(bool renderShadows = false); + RenderDeferred(); void configure(const Config& config); @@ -203,7 +195,6 @@ protected: gpu::RangeTimerPointer _gpuTimer; private: - bool _renderShadows { false }; }; class DefaultLightingSetup { diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 252416ea9d..3dc826d56c 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -543,7 +543,7 @@ void LightClusteringPass::configure(const Config& config) { _freeze = config.freeze; } -void LightClusteringPass::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output) { +void LightClusteringPass::run(const render::RenderContextPointer& renderContext, const Input& inputs, Output& output) { auto args = renderContext->args; auto deferredTransform = inputs.get0(); @@ -638,10 +638,9 @@ void DebugLightClusters::run(const render::RenderContextPointer& renderContext, } auto deferredTransform = inputs.get0(); - auto deferredFramebuffer = inputs.get1(); - auto lightingModel = inputs.get2(); - auto linearDepthTarget = inputs.get3(); - auto lightClusters = inputs.get4(); + auto lightingModel = inputs.get1(); + auto linearDepthTarget = inputs.get2(); + auto lightClusters = inputs.get3(); auto args = renderContext->args; diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index e109e43aaa..60978e76e8 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -167,16 +167,16 @@ protected: class LightClusteringPass { public: - using Inputs = render::VaryingSet4; - using Outputs = LightClustersPointer; + using Input = render::VaryingSet4; + using Output = LightClustersPointer; using Config = LightClusteringPassConfig; - using JobModel = render::Job::ModelIO; + using JobModel = render::Job::ModelIO; LightClusteringPass(); void configure(const Config& config); - void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); protected: LightClustersPointer _lightClusters; @@ -213,7 +213,7 @@ protected: class DebugLightClusters { public: - using Inputs = render::VaryingSet5 < DeferredFrameTransformPointer, DeferredFramebufferPointer, LightingModelPointer, LinearDepthFramebufferPointer, LightClustersPointer>; + using Inputs = render::VaryingSet4 < DeferredFrameTransformPointer, LightingModelPointer, LinearDepthFramebufferPointer, LightClustersPointer>; using Config = DebugLightClustersConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index d5e1ca4644..6913949286 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -152,6 +152,11 @@ LightStage::Shadow::Shadow(graphics::LightPointer light, float maxDistance, unsi setMaxDistance(maxDistance); } +void LightStage::Shadow::setLight(graphics::LightPointer light) { + _light = light; +} + + void LightStage::Shadow::setMaxDistance(float value) { // This overlaping factor isn't really used directly for blending of shadow cascades. It // just there to be sure the cascades do overlap. The blending width used is relative @@ -345,27 +350,9 @@ LightStage::Index LightStage::addLight(const LightPointer& light, const bool sho return lightId; } -LightStage::Index LightStage::addShadow(Index lightIndex, float maxDistance, unsigned int cascadeCount) { - auto light = getLight(lightIndex); - Index shadowId = INVALID_INDEX; - if (light) { - assert(_descs[lightIndex].shadowId == INVALID_INDEX); - shadowId = _shadows.newElement(std::make_shared(light, maxDistance, cascadeCount)); - _descs[lightIndex].shadowId = shadowId; - } - return shadowId; -} - LightStage::LightPointer LightStage::removeLight(Index index) { LightPointer removedLight = _lights.freeElement(index); if (removedLight) { - auto shadowId = _descs[index].shadowId; - // Remove shadow if one exists for this light - if (shadowId != INVALID_INDEX) { - auto removedShadow = _shadows.freeElement(shadowId); - assert(removedShadow); - assert(removedShadow->getLight() == removedLight); - } _lightMap.erase(removedLight); _descs[index] = Desc(); } @@ -389,35 +376,6 @@ LightStage::LightPointer LightStage::getCurrentAmbientLight(const LightStage::Fr return _lights.get(keyLightId); } -LightStage::ShadowPointer LightStage::getCurrentKeyShadow(const LightStage::Frame& frame) const { - Index keyLightId { _defaultLightId }; - if (!frame._sunLights.empty()) { - keyLightId = frame._sunLights.front(); - } - auto shadow = getShadow(keyLightId); - assert(shadow == nullptr || shadow->getLight() == getLight(keyLightId)); - return shadow; -} - -LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow(const LightStage::Frame& frame) const { - Index keyLightId { _defaultLightId }; - if (!frame._sunLights.empty()) { - keyLightId = frame._sunLights.front(); - } - auto shadow = getShadow(keyLightId); - auto light = getLight(keyLightId); - assert(shadow == nullptr || shadow->getLight() == light); - return LightAndShadow(light, shadow); -} - -LightStage::Index LightStage::getShadowId(Index lightId) const { - if (checkLightId(lightId)) { - return _descs[lightId].shadowId; - } else { - return INVALID_INDEX; - } -} - void LightStage::updateLightArrayBuffer(Index lightId) { auto lightSize = sizeof(graphics::Light::LightSchema); if (!_lightArrayBuffer) { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 5e5b6cf4fa..1fb1754862 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -76,6 +76,8 @@ public: Shadow(graphics::LightPointer light, float maxDistance, unsigned int cascadeCount = 1); + void setLight(graphics::LightPointer light); + void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth = 1.0f, float farDepth = 1000.0f); void setKeylightCascadeFrustum(unsigned int cascadeIndex, const ViewFrustum& viewFrustum, @@ -93,10 +95,15 @@ public: const graphics::LightPointer& getLight() const { return _light; } gpu::TexturePointer map; +#include "Shadows_shared.slh" + class Schema : public ShadowParameters { + public: + Schema(); + + }; protected: -#include "Shadows_shared.slh" using Cascades = std::vector; @@ -106,25 +113,17 @@ public: float _maxDistance; Cascades _cascades; - class Schema : public ShadowParameters { - public: - Schema(); - - }; UniformBufferView _schemaBuffer = nullptr; }; using ShadowPointer = std::shared_ptr; - using Shadows = render::indexed_container::IndexedPointerVector; Index findLight(const LightPointer& light) const; Index addLight(const LightPointer& light, const bool shouldSetAsDefault = false); Index getDefaultLight() { return _defaultLightId; } - Index addShadow(Index lightIndex, float maxDistance = 20.0f, unsigned int cascadeCount = 1U); - LightPointer removeLight(Index index); bool checkLightId(Index index) const { return _lights.checkIndex(index); } @@ -133,23 +132,7 @@ public: Index getNumFreeLights() const { return _lights.getNumFreeIndices(); } Index getNumAllocatedLights() const { return _lights.getNumAllocatedIndices(); } - LightPointer getLight(Index lightId) const { - return _lights.get(lightId); - } - - Index getShadowId(Index lightId) const; - - ShadowPointer getShadow(Index lightId) const { - return _shadows.get(getShadowId(lightId)); - } - - using LightAndShadow = std::pair; - LightAndShadow getLightAndShadow(Index lightId) const { - auto light = getLight(lightId); - auto shadow = getShadow(lightId); - assert(shadow == nullptr || shadow->getLight() == light); - return LightAndShadow(light, shadow); - } + LightPointer getLight(Index lightId) const { return _lights.get(lightId); } LightStage(); @@ -182,6 +165,24 @@ public: }; using FramePointer = std::shared_ptr; + class ShadowFrame { + public: + ShadowFrame() {} + + void clear() {} + + using Object = ShadowPointer; + using Objects = std::vector; + + void pushShadow(const ShadowPointer& shadow) { + _objects.emplace_back(shadow); + } + + + Objects _objects; + }; + using ShadowFramePointer = std::shared_ptr; + Frame _currentFrame; Index getAmbientOffLight() { return _ambientOffLightId; } @@ -191,8 +192,6 @@ public: LightPointer getCurrentKeyLight(const LightStage::Frame& frame) const; LightPointer getCurrentAmbientLight(const LightStage::Frame& frame) const; - ShadowPointer getCurrentKeyShadow(const LightStage::Frame& frame) const; - LightAndShadow getCurrentKeyLightAndShadow(const LightStage::Frame& frame) const; protected: @@ -204,7 +203,6 @@ protected: gpu::BufferPointer _lightArrayBuffer; Lights _lights; - Shadows _shadows; Descs _descs; LightMap _lightMap; diff --git a/libraries/render-utils/src/LightingModel.cpp b/libraries/render-utils/src/LightingModel.cpp index 05002a5daf..2a85fcd960 100644 --- a/libraries/render-utils/src/LightingModel.cpp +++ b/libraries/render-utils/src/LightingModel.cpp @@ -187,6 +187,24 @@ bool LightingModel::isBlendshapeEnabled() const { return (bool)_parametersBuffer.get().enableBlendshape; } +void LightingModel::setAmbientOcclusion(bool enable) { + if (enable != isAmbientOcclusionEnabled()) { + _parametersBuffer.edit().enableAmbientOcclusion = (float)enable; + } +} +bool LightingModel::isAmbientOcclusionEnabled() const { + return (bool)_parametersBuffer.get().enableAmbientOcclusion; +} + +void LightingModel::setShadow(bool enable) { + if (enable != isShadowEnabled()) { + _parametersBuffer.edit().enableShadow = (float)enable; + } +} +bool LightingModel::isShadowEnabled() const { + return (bool)_parametersBuffer.get().enableShadow; +} + MakeLightingModel::MakeLightingModel() { _lightingModel = std::make_shared(); } @@ -218,6 +236,9 @@ void MakeLightingModel::configure(const Config& config) { _lightingModel->setSkinning(config.enableSkinning); _lightingModel->setBlendshape(config.enableBlendshape); + + _lightingModel->setAmbientOcclusion(config.enableAmbientOcclusion); + _lightingModel->setShadow(config.enableShadow); } void MakeLightingModel::run(const render::RenderContextPointer& renderContext, LightingModelPointer& lightingModel) { diff --git a/libraries/render-utils/src/LightingModel.h b/libraries/render-utils/src/LightingModel.h index de7ff63972..571eadb60b 100644 --- a/libraries/render-utils/src/LightingModel.h +++ b/libraries/render-utils/src/LightingModel.h @@ -76,6 +76,12 @@ public: void setBlendshape(bool enable); bool isBlendshapeEnabled() const; + + void setAmbientOcclusion(bool enable); + bool isAmbientOcclusionEnabled() const; + void setShadow(bool enable); + bool isShadowEnabled() const; + UniformBufferView getParametersBuffer() const { return _parametersBuffer; } protected: @@ -112,6 +118,11 @@ protected: float enableSkinning{ 1.0f }; float enableBlendshape{ 1.0f }; + float enableAmbientOcclusion{ 0.0f }; + float enableShadow{ 1.0f }; + float spare1{ 1.0f }; + float spare2{ 1.0f }; + Parameters() {} }; UniformBufferView _parametersBuffer; @@ -152,6 +163,10 @@ class MakeLightingModelConfig : public render::Job::Config { Q_PROPERTY(bool enableSkinning MEMBER enableSkinning NOTIFY dirty) Q_PROPERTY(bool enableBlendshape MEMBER enableBlendshape NOTIFY dirty) + Q_PROPERTY(bool enableAmbientOcclusion READ isAmbientOcclusionEnabled WRITE setAmbientOcclusion NOTIFY dirty) + Q_PROPERTY(bool enableShadow READ isShadowEnabled WRITE setShadow NOTIFY dirty) + + public: MakeLightingModelConfig() : render::Job::Config() {} // Make Lighting Model is always on @@ -181,6 +196,17 @@ public: bool enableSkinning{ true }; bool enableBlendshape{ true }; + bool enableAmbientOcclusion{ true }; + bool enableShadow{ true }; + + + void setAmbientOcclusion(bool enable) { enableAmbientOcclusion = enable; emit dirty();} + bool isAmbientOcclusionEnabled() const { return enableAmbientOcclusion; } + void setShadow(bool enable) { + enableShadow = enable; emit dirty(); + } + bool isShadowEnabled() const { return enableShadow; } + signals: void dirty(); }; diff --git a/libraries/render-utils/src/RenderCommonTask.cpp b/libraries/render-utils/src/RenderCommonTask.cpp index 4422d15d5c..40724cbf5a 100644 --- a/libraries/render-utils/src/RenderCommonTask.cpp +++ b/libraries/render-utils/src/RenderCommonTask.cpp @@ -203,7 +203,7 @@ void ExtractFrustums::run(const render::RenderContextPointer& renderContext, con RenderArgs* args = renderContext->args; - const auto& lightFrame = inputs; + const auto& shadowFrame = inputs; // Return view frustum auto& viewFrustum = output[VIEW_FRUSTUM].edit(); @@ -214,38 +214,18 @@ void ExtractFrustums::run(const render::RenderContextPointer& renderContext, con } // Return shadow frustum - auto lightStage = args->_scene->getStage(LightStage::getName()); + LightStage::ShadowPointer globalShadow; + if (shadowFrame && !shadowFrame->_objects.empty() && shadowFrame->_objects[0]) { + globalShadow = shadowFrame->_objects[0]; + } for (auto i = 0; i < SHADOW_CASCADE_FRUSTUM_COUNT; i++) { auto& shadowFrustum = output[SHADOW_CASCADE0_FRUSTUM+i].edit(); - if (lightStage) { - auto globalShadow = lightStage->getCurrentKeyShadow(*lightFrame); - - if (globalShadow && i<(int)globalShadow->getCascadeCount()) { - auto& cascade = globalShadow->getCascade(i); - shadowFrustum = cascade.getFrustum(); - } else { - shadowFrustum.reset(); - } + if (globalShadow && i<(int)globalShadow->getCascadeCount()) { + auto& cascade = globalShadow->getCascade(i); + shadowFrustum = cascade.getFrustum(); } else { shadowFrustum.reset(); } } } -void FetchCurrentFrames::run(const render::RenderContextPointer& renderContext, Outputs& outputs) { - auto lightStage = renderContext->_scene->getStage(); - assert(lightStage); - outputs.edit0() = std::make_shared(lightStage->_currentFrame); - - auto backgroundStage = renderContext->_scene->getStage(); - assert(backgroundStage); - outputs.edit1() = std::make_shared(backgroundStage->_currentFrame); - - auto hazeStage = renderContext->_scene->getStage(); - assert(hazeStage); - outputs.edit2() = std::make_shared(hazeStage->_currentFrame); - - auto bloomStage = renderContext->_scene->getStage(); - assert(bloomStage); - outputs.edit3() = std::make_shared(bloomStage->_currentFrame); -} diff --git a/libraries/render-utils/src/RenderCommonTask.h b/libraries/render-utils/src/RenderCommonTask.h index 9b611bc38d..29f195ffff 100644 --- a/libraries/render-utils/src/RenderCommonTask.h +++ b/libraries/render-utils/src/RenderCommonTask.h @@ -10,13 +10,8 @@ #define hifi_RenderCommonTask_h #include -#include -#include "LightingModel.h" - #include "LightStage.h" -#include "BackgroundStage.h" -#include "HazeStage.h" -#include "BloomStage.h" +#include "LightingModel.h" class BeginGPURangeTimer { public: @@ -111,22 +106,11 @@ public: FRUSTUM_COUNT }; - using Inputs = LightStage::FramePointer; + using Inputs = LightStage::ShadowFramePointer; using Outputs = render::VaryingArray; using JobModel = render::Job::ModelIO; void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output); }; - -class FetchCurrentFrames { -public: - using Outputs = render::VaryingSet4; - using JobModel = render::Job::ModelO; - - FetchCurrentFrames() {} - - void run(const render::RenderContextPointer& renderContext, Outputs& outputs); -}; - #endif // hifi_RenderDeferredTask_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 4052b6bd5a..a685f3998e 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -72,6 +72,23 @@ namespace gr { } +class RenderDeferredTaskDebug { +public: + using ExtraBuffers = render::VaryingSet6; + using Input = render::VaryingSet9; + + using JobModel = render::Task::ModelI; + + RenderDeferredTaskDebug(); + + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); +private: +}; + + RenderDeferredTask::RenderDeferredTask() { } @@ -86,37 +103,45 @@ void RenderDeferredTask::configure(const Config& config) { upsamplePrimaryBufferConfig->setProperty("factor", 1.0f / config.resolutionScale); } -const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, const char* selectionName, - const render::Varying& metas, - const render::Varying& opaques, - const render::Varying& transparents) { - const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying(); - const auto selectedMetas = task.addJob("MetaSelection", selectMetaInput, selectionName); - const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, std::string()).asVarying(); - const auto selectedMetasAndOpaques = task.addJob("OpaqueSelection", selectMetaAndOpaqueInput, selectionName); - const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, std::string()).asVarying(); - return task.addJob("TransparentSelection", selectItemInput, selectionName); -} - -void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output, bool renderShadows) { - const auto& inputs = input.get(); - const auto& items = inputs.get0(); - +void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { auto fadeEffect = DependencyManager::get(); - // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); initDeferredPipelines(*shapePlumber, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter()); - // Extract opaques / transparents / lights / metas / overlays / background - const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; - const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; - const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; - const auto& metas = items.get0()[RenderFetchCullSortTask::META]; - const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; - //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; - const auto& spatialSelection = items[1]; + const auto& inputs = input.get(); + + // Separate the fetched items + const auto& fetchedItems = inputs.get0(); + + const auto& items = fetchedItems.get0(); + + // Extract opaques / transparents / lights / metas / overlays / background + const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; + const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; + const auto& overlaysInFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; + const auto& overlaysInFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; + const auto& overlaysHUDOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; + const auto& overlaysHUDTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; + + // Lighting model comes next, the big configuration of the view + const auto& lightingModel = inputs[1]; + + // Extract the Lighting Stages Current frame ( and zones) + const auto& lightingStageInputs = inputs.get2(); + // Fetch the current frame stacks from all the stages + const auto currentStageFrames = lightingStageInputs.get0(); + const auto lightFrame = currentStageFrames[0]; + const auto backgroundFrame = currentStageFrames[1]; + const auto& hazeFrame = currentStageFrames[2]; + const auto& bloomFrame = currentStageFrames[3]; + + // Shadow Task Outputs + const auto& shadowTaskOutputs = inputs.get3(); + + // Shadow Stage Frame + const auto shadowFrame = shadowTaskOutputs[1]; + fadeEffect->build(task, opaques); @@ -127,7 +152,6 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Prepare deferred, generate the shared Deferred Frame Transform. Only valid with the scaled frame buffer const auto deferredFrameTransform = task.addJob("DeferredFrameTransform", jitter); - const auto lightingModel = task.addJob("LightingModel"); const auto opaqueRangeTimer = task.addJob("BeginOpaqueRangeTimer", "DrawOpaques"); @@ -164,38 +188,25 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto scatteringResource = task.addJob("Scattering"); // AO job - const auto ambientOcclusionInputs = AmbientOcclusionEffect::Inputs(deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying(); + const auto ambientOcclusionInputs = AmbientOcclusionEffect::Input(lightingModel, deferredFrameTransform, deferredFramebuffer, linearDepthTarget).asVarying(); const auto ambientOcclusionOutputs = task.addJob("AmbientOcclusion", ambientOcclusionInputs); - const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN(0); - const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN(1); + const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN(0); + const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN(1); // Velocity const auto velocityBufferInputs = VelocityBufferPass::Inputs(deferredFrameTransform, deferredFramebuffer).asVarying(); const auto velocityBufferOutputs = task.addJob("VelocityBuffer", velocityBufferInputs); const auto velocityBuffer = velocityBufferOutputs.getN(0); - // Clear Light, Haze, Bloom, and Skybox Stages and render zones from the general metas bucket - const auto zones = task.addJob("ZoneRenderer", metas); - - // Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now. - task.addJob("DrawLight", lights); - - // Fetch the current frame stacks from all the stages - const auto currentFrames = task.addJob("FetchCurrentFrames"); - const auto lightFrame = currentFrames.getN(0); - const auto backgroundFrame = currentFrames.getN(1); - const auto hazeFrame = currentFrames.getN(2); - const auto bloomFrame = currentFrames.getN(3); - // Light Clustering // Create the cluster grid of lights, cpu job for now - const auto lightClusteringPassInputs = LightClusteringPass::Inputs(deferredFrameTransform, lightingModel, lightFrame, linearDepthTarget).asVarying(); + const auto lightClusteringPassInputs = LightClusteringPass::Input(deferredFrameTransform, lightingModel, lightFrame, linearDepthTarget).asVarying(); const auto lightClusters = task.addJob("LightClustering", lightClusteringPassInputs); // DeferredBuffer is complete, now let's shade it into the LightingBuffer - const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, - surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource, lightClusters, lightFrame, hazeFrame).asVarying(); - task.addJob("RenderDeferred", deferredLightingInputs, renderShadows); + const auto extraDeferredBuffer = RenderDeferred::ExtraDeferredBuffer(surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, scatteringResource).asVarying(); + const auto deferredLightingInputs = RenderDeferred::Inputs(deferredFrameTransform, deferredFramebuffer, extraDeferredBuffer, lightingModel, lightClusters, lightFrame, shadowFrame, hazeFrame).asVarying(); + task.addJob("RenderDeferred", deferredLightingInputs); // Similar to light stage, background stage has been filled by several potential render items and resolved for the frame in this job const auto backgroundInputs = DrawBackgroundStage::Inputs(lightingModel, backgroundFrame).asVarying(); @@ -205,43 +216,22 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawHazeDeferred", drawHazeInputs); // Render transparent objects forward in LightingBuffer - const auto transparentsInputs = DrawDeferred::Inputs(transparents, hazeFrame, lightFrame, lightingModel, lightClusters, jitter).asVarying(); + const auto transparentsInputs = DrawDeferred::Inputs(transparents, hazeFrame, lightFrame, lightingModel, lightClusters, shadowFrame, jitter).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); - // Light Cluster Grid Debuging job - { - const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying(); - task.addJob("DebugLightClusters", debugLightClustersInputs); - } - const auto outlineRangeTimer = task.addJob("BeginHighlightRangeTimer", "Highlight"); - // Select items that need to be outlined - const auto selectionBaseName = "contextOverlayHighlightList"; - const auto selectedItems = addSelectItemJobs(task, selectionBaseName, metas, opaques, transparents); - const auto outlineInputs = DrawHighlightTask::Inputs(items.get0(), deferredFramebuffer, lightingFramebuffer, deferredFrameTransform, jitter).asVarying(); + const auto outlineInputs = DrawHighlightTask::Inputs(items, deferredFramebuffer, lightingFramebuffer, deferredFrameTransform, jitter).asVarying(); task.addJob("DrawHighlight", outlineInputs); task.addJob("HighlightRangeTimer", outlineRangeTimer); - const auto overlaysInFrontRangeTimer = task.addJob("BeginOverlaysInFrontRangeTimer", "BeginOverlaysInFrontRangeTimer"); - - // Layered Overlays - const auto filteredOverlaysOpaque = task.addJob("FilterOverlaysLayeredOpaque", overlayOpaques, render::hifi::LAYER_3D_FRONT); - const auto filteredOverlaysTransparent = task.addJob("FilterOverlaysLayeredTransparent", overlayTransparents, render::hifi::LAYER_3D_FRONT); - const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN(0); - const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN(0); - - // We don't want the overlay to clear the deferred frame buffer depth because we would like to keep it for debugging visualisation - // task.addJob("SeparateDepthForOverlay", deferredFramebuffer); - + // Layered Over (in front) const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, jitter).asVarying(); const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, jitter).asVarying(); task.addJob("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true); task.addJob("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false); - task.addJob("OverlaysInFrontRangeTimer", overlaysInFrontRangeTimer); - const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // AA job before bloom to limit flickering @@ -256,14 +246,115 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); + // Debugging task is happening in the "over" layer after tone mapping and just before HUD + { // Debug the bounds of the rendered items, still look at the zbuffer + const auto extraDebugBuffers = RenderDeferredTaskDebug::ExtraBuffers(linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, ambientOcclusionFramebuffer, scatteringResource, velocityBuffer); + const auto debugInputs = RenderDeferredTaskDebug::Input(fetchedItems, shadowTaskOutputs, lightingStageInputs, lightClusters, prepareDeferredOutputs, extraDebugBuffers, + deferredFrameTransform, jitter, lightingModel).asVarying(); + task.addJob("DebugRenderDeferredTask", debugInputs); + } + + // Upscale to finale resolution + const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", scaledPrimaryFramebuffer); + + // Composite the HUD and HUD overlays + task.addJob("HUD"); + + const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); + const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel, nullJitter).asVarying(); + const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel, nullJitter).asVarying(); + task.addJob("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true); + task.addJob("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false); + + task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); + + // Blit! + task.addJob("Blit", primaryFramebuffer); +} + +RenderDeferredTaskDebug::RenderDeferredTaskDebug() { +} + +void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input, render::Varying& outputs) { + + const auto& inputs = input.get(); + + // RenderFetchCullSortTask out + const auto& fetchCullSortTaskOut = inputs.get0(); + const auto& items = fetchCullSortTaskOut.get0(); + + // Extract opaques / transparents / lights / metas / overlays InFront and HUD / background + const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; + const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; + const auto& lights = items[RenderFetchCullSortTask::LIGHT]; + const auto& metas = items[RenderFetchCullSortTask::META]; + const auto& overlaysInFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; + const auto& overlaysInFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; + const auto& overlaysHUDOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; + const auto& overlaysHUDTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; + + const auto& spatialSelection = fetchCullSortTaskOut[1]; + + // RenderShadowTask out + const auto& shadowOut = inputs.get1(); + + const auto& renderShadowTaskOut = shadowOut[0]; + const auto& shadowFrame = shadowOut[1]; + + // Extract the Lighting Stages Current frame ( and zones) + const auto lightingStageInputs = inputs.get2(); + // Fetch the current frame stacks from all the stages + const auto stageCurrentFrames = lightingStageInputs.get0(); + const auto lightFrame = stageCurrentFrames[0]; + const auto backgroundFrame = stageCurrentFrames[1]; + const auto hazeFrame = stageCurrentFrames[2]; + const auto bloomFrame = stageCurrentFrames[3]; + + // Zones + const auto& zones = lightingStageInputs[1]; + + // Light CLuster + const auto& lightClusters = inputs[3]; + + // PrepareDeferred out + const auto& prepareDeferredOutputs = inputs.get4(); + const auto& deferredFramebuffer = prepareDeferredOutputs[0]; + + // extraDeferredBuffer + const auto& extraDeferredBuffer = inputs.get5(); + const auto& linearDepthTarget = extraDeferredBuffer[0]; + const auto& surfaceGeometryFramebuffer = extraDeferredBuffer[1]; + const auto& ambientOcclusionFramebuffer = extraDeferredBuffer[2]; + const auto& ambientOcclusionUniforms = extraDeferredBuffer[3]; + const auto& scatteringResource = extraDeferredBuffer[4]; + const auto& velocityBuffer = extraDeferredBuffer[5]; + + // GenerateDeferredFrameTransform out + const auto& deferredFrameTransform = inputs[6]; + + // Jitter out + const auto& jitter = inputs[7]; + + // Lighting Model out + const auto& lightingModel = inputs[8]; + + + + // Light Cluster Grid Debuging job + { + const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, lightingModel, linearDepthTarget, lightClusters).asVarying(); + task.addJob("DebugLightClusters", debugLightClustersInputs); + } + + { // Debug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); task.addJob("DrawOpaqueBounds", opaques); task.addJob("DrawTransparentBounds", transparents); - + task.addJob("DrawLightBounds", lights); task.addJob("DrawZones", zones); - const auto frustums = task.addJob("ExtractFrustums", lightFrame); + const auto frustums = task.addJob("ExtractFrustums", shadowFrame); const auto viewFrustum = frustums.getN(ExtractFrustums::VIEW_FRUSTUM); task.addJob("DrawViewFrustum", viewFrustum, glm::vec3(0.0f, 1.0f, 0.0f)); for (auto i = 0; i < ExtractFrustums::SHADOW_CASCADE_FRUSTUM_COUNT; i++) { @@ -272,13 +363,26 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren char jobName[64]; sprintf(jobName, "DrawShadowFrustum%d", i); task.addJob(jobName, shadowFrustum, glm::vec3(0.0f, tint, 1.0f)); - if (!inputs[1].isNull()) { - const auto& shadowCascadeSceneBBoxes = inputs.get1(); + if (!renderShadowTaskOut.isNull()) { + const auto& shadowCascadeSceneBBoxes = renderShadowTaskOut; const auto shadowBBox = shadowCascadeSceneBBoxes[ExtractFrustums::SHADOW_CASCADE0_FRUSTUM + i]; sprintf(jobName, "DrawShadowBBox%d", i); task.addJob(jobName, shadowBBox, glm::vec3(1.0f, tint, 0.0f)); } } + } + + { // Debug Selection... + // TODO: It s busted + // Select items that need to be outlined and show them + const auto selectionBaseName = "contextOverlayHighlightList"; + + const auto selectMetaInput = SelectItems::Inputs(metas, Varying(), std::string()).asVarying(); + const auto selectedMetas = task.addJob("MetaSelection", selectMetaInput, selectionBaseName); + const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, std::string()).asVarying(); + const auto selectedMetasAndOpaques = task.addJob("OpaqueSelection", selectMetaAndOpaqueInput, selectionBaseName); + const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, std::string()).asVarying(); + const auto selectedItems = task.addJob("TransparentSelection", selectItemInput, selectionBaseName); // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true task.addJob("DrawSelectionBounds", selectedItems); @@ -289,10 +393,16 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent); } + { // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer + task.addJob("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque); + task.addJob("DrawOverlayHUDTransparentBounds", overlaysHUDTransparent); + } + // Debugging stages { + // Debugging Deferred buffer job - const auto debugFramebuffers = render::Varying(DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, velocityBuffer, deferredFrameTransform, lightFrame)); + const auto debugFramebuffers = DebugDeferredBuffer::Inputs(deferredFramebuffer, linearDepthTarget, surfaceGeometryFramebuffer, ambientOcclusionFramebuffer, velocityBuffer, deferredFrameTransform, shadowFrame).asVarying(); task.addJob("DebugDeferredBuffer", debugFramebuffers); const auto debugSubsurfaceScatteringInputs = DebugSubsurfaceScattering::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, @@ -310,7 +420,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren // Status icon rendering job { - // Grab a texture map representing the different status icons and assign that to the drawStatsuJob + // Grab a texture map representing the different status icons and assign that to the drawStatusJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath, image::TextureUsage::STRICT_TEXTURE); const auto drawStatusInputs = DrawStatus::Input(opaques, jitter).asVarying(); @@ -319,34 +429,13 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto debugZoneInputs = DebugZoneLighting::Inputs(deferredFrameTransform, lightFrame, backgroundFrame).asVarying(); task.addJob("DrawZoneStack", debugZoneInputs); + } - // Upscale to finale resolution - const auto primaryFramebuffer = task.addJob("PrimaryBufferUpscale", scaledPrimaryFramebuffer); - // Composite the HUD and HUD overlays - task.addJob("HUD"); - - const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN(1); - const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN(1); - const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); - - const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel, nullJitter).asVarying(); - const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel, nullJitter).asVarying(); - task.addJob("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true); - task.addJob("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false); - - { // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer - task.addJob("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque); - task.addJob("DrawOverlayHUDTransparentBounds", overlaysHUDTransparent); - } - - task.addJob("ToneAndPostRangeTimer", toneAndPostRangeTimer); - - // Blit! - task.addJob("Blit", primaryFramebuffer); } + void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& inputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -358,7 +447,8 @@ void DrawDeferred::run(const RenderContextPointer& renderContext, const Inputs& const auto& lightFrame = inputs.get2(); const auto& lightingModel = inputs.get3(); const auto& lightClusters = inputs.get4(); - const auto jitter = inputs.get5(); + // Not needed yet: const auto& shadowFrame = inputs.get5(); + const auto jitter = inputs.get6(); auto deferredLightingEffect = DependencyManager::get(); RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index c18daa6d3d..0a188ec3a6 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -14,10 +14,10 @@ #include #include +#include "AssembleLightingStageTask.h" #include "LightingModel.h" #include "LightClusters.h" #include "RenderShadowTask.h" -#include "HazeStage.h" class DrawDeferredConfig : public render::Job::Config { Q_OBJECT @@ -43,7 +43,7 @@ protected: class DrawDeferred { public: - using Inputs = render::VaryingSet6; + using Inputs = render::VaryingSet7; using Config = DrawDeferredConfig; using JobModel = render::Job::ModelI; @@ -137,21 +137,16 @@ signals: class RenderDeferredTask { public: - using Input = render::VaryingSet2; + using Input = render::VaryingSet4; using Config = RenderDeferredTaskConfig; using JobModel = render::Task::ModelI; RenderDeferredTask(); void configure(const Config& config); - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, bool renderShadows); + void build(JobModel& task, const render::Varying& input, render::Varying& output); private: - static const render::Varying addSelectItemJobs(JobModel& task, - const char* selectionName, - const render::Varying& metas, - const render::Varying& opaques, - const render::Varying& transparents); }; #endif // hifi_RenderDeferredTask_h diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 53f89aaec3..ffdbc1c4b1 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -48,39 +48,46 @@ using namespace render; extern void initForwardPipelines(ShapePlumber& plumber); void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - auto items = input.get(); - auto fadeEffect = DependencyManager::get(); - // Prepare the ShapePipelines + auto fadeEffect = DependencyManager::get(); ShapePlumberPointer shapePlumber = std::make_shared(); initForwardPipelines(*shapePlumber); - // Extract opaques / transparents / lights / metas / overlays / background - const auto& opaques = items.get0()[RenderFetchCullSortTask::OPAQUE_SHAPE]; - const auto& transparents = items.get0()[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; - //const auto& lights = items.get0()[RenderFetchCullSortTask::LIGHT]; - const auto& metas = items.get0()[RenderFetchCullSortTask::META]; - const auto& overlayOpaques = items.get0()[RenderFetchCullSortTask::OVERLAY_OPAQUE_SHAPE]; - const auto& overlayTransparents = items.get0()[RenderFetchCullSortTask::OVERLAY_TRANSPARENT_SHAPE]; + // Unpack inputs + const auto& inputs = input.get(); + + // Separate the fetched items + const auto& fetchedItems = inputs.get0(); - //const auto& background = items.get0()[RenderFetchCullSortTask::BACKGROUND]; - //const auto& spatialSelection = items[1]; + const auto& items = fetchedItems.get0(); + // Extract opaques / transparents / lights / metas / overlays / background + const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE]; + const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE]; + const auto& metas = items[RenderFetchCullSortTask::META]; + const auto& overlaysInFrontOpaque = items[RenderFetchCullSortTask::LAYER_FRONT_OPAQUE_SHAPE]; + const auto& overlaysInFrontTransparent = items[RenderFetchCullSortTask::LAYER_FRONT_TRANSPARENT_SHAPE]; + // TODO: Re enable the rendering of the HUD overlayes + // const auto& overlaysHUDOpaque = items[RenderFetchCullSortTask::LAYER_HUD_OPAQUE_SHAPE]; + // const auto& overlaysHUDTransparent = items[RenderFetchCullSortTask::LAYER_HUD_TRANSPARENT_SHAPE]; + + // Lighting model comes next, the big configuration of the view + const auto& lightingModel = inputs[1]; + + // Extract the Lighting Stages Current frame ( and zones) + const auto& lightingStageInputs = inputs.get2(); + // Fetch the current frame stacks from all the stages + const auto currentStageFrames = lightingStageInputs.get0(); + const auto lightFrame = currentStageFrames[0]; + const auto backgroundFrame = currentStageFrames[1]; + + const auto& zones = lightingStageInputs[1]; + + // First job, alter faded fadeEffect->build(task, opaques); // Prepare objects shared by several jobs const auto deferredFrameTransform = task.addJob("DeferredFrameTransform"); - const auto lightingModel = task.addJob("LightingModel"); - - // Filter zones from the general metas bucket - const auto zones = task.addJob("ZoneRenderer", metas); - - // Fetch the current frame stacks from all the stages - const auto currentFrames = task.addJob("FetchCurrentFrames"); - const auto lightFrame = currentFrames.getN(0); - const auto backgroundFrame = currentFrames.getN(1); - //const auto hazeFrame = currentFrames.getN(2); - //const auto bloomFrame = currentFrames.getN(3); // GPU jobs: Start preparing the main framebuffer const auto framebuffer = task.addJob("PrepareFramebuffer"); @@ -91,12 +98,9 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend task.addJob("PrepareStencil", framebuffer); // Layered Overlays - const auto filteredOverlaysOpaque = task.addJob("FilterOverlaysLayeredOpaque", overlayOpaques, render::hifi::LAYER_3D_FRONT); - const auto filteredOverlaysTransparent = task.addJob("FilterOverlaysLayeredTransparent", overlayTransparents, render::hifi::LAYER_3D_FRONT); - const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN(0); - const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN(0); const auto nullJitter = Varying(glm::vec2(0.0f, 0.0f)); + // Layered Over (in front) const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel, nullJitter).asVarying(); const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel, nullJitter).asVarying(); task.addJob("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true); diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 54341d1ded..e6a6008319 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -14,17 +14,17 @@ #include #include +#include "AssembleLightingStageTask.h" #include "LightingModel.h" -#include "LightStage.h" class RenderForwardTask { public: - using Input = RenderFetchCullSortTask::Output; + using Input = render::VaryingSet3; using JobModel = render::Task::ModelI; RenderForwardTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + void build(JobModel& task, const render::Varying& input, render::Varying& output); }; class PrepareFramebuffer { diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index b5b3e9c5b9..bfa6f5e5d1 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -25,6 +25,7 @@ #include "RenderUtilsLogging.h" #include "RenderCommonTask.h" +#include "AssembleLightingStageTask.h" #include "FadeEffect.h" @@ -32,13 +33,15 @@ // but are readjusted afterwards #define SHADOW_FRUSTUM_NEAR 1.0f #define SHADOW_FRUSTUM_FAR 500.0f +static const unsigned int SHADOW_CASCADE_COUNT{ 4 }; +static const float SHADOW_MAX_DISTANCE{ 40.0f }; using namespace render; extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state, const render::ShapePipeline::BatchSetter& batchSetter, const render::ShapePipeline::ItemSetter& itemSetter); void RenderShadowTask::configure(const Config& configuration) { - DependencyManager::get()->setShadowMapEnabled(configuration.isEnabled()); + //DependencyManager::get()->setShadowMapEnabled(configuration.isEnabled()); // This is a task, so must still propogate configure() to its Jobs // Task::configure(configuration); } @@ -57,11 +60,13 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende // FIXME: calling this here before the zones/lights are drawn during the deferred/forward passes means we're actually using the frames from the previous draw // Fetch the current frame stacks from all the stages - const auto currentFrames = task.addJob("FetchCurrentFrames"); - const auto lightFrame = currentFrames.getN(0); + // Starting with the Light Frame genreated in previous tasks + + const auto& lightFrame = input.getN(0); - const auto setupOutput = task.addJob("ShadowSetup", lightFrame); - const auto queryResolution = setupOutput.getN(1); + const auto setupOutput = task.addJob("ShadowSetup", input); + const auto queryResolution = setupOutput.getN(1); + const auto shadowFrame = setupOutput.getN(3); // Fetch and cull the items from the scene static const auto shadowCasterReceiverFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(tagBits, tagMask); @@ -73,7 +78,7 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende // Cull objects that are not visible in camera view. Hopefully the cull functor only performs LOD culling, not // frustum culling or this will make shadow casters out of the camera frustum disappear. - const auto cameraFrustum = setupOutput.getN(2); + const auto cameraFrustum = setupOutput.getN(2); const auto applyFunctorInputs = ApplyCullFunctorOnItemBounds::Inputs(shadowItems, cameraFrustum).asVarying(); const auto culledShadowItems = task.addJob("ShadowCullCamera", applyFunctorInputs, cameraCullFunctor); @@ -90,12 +95,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende #endif }; - Output cascadeSceneBBoxes; + render::VaryingArray cascadeSceneBBoxes; for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) { char jobName[64]; sprintf(jobName, "ShadowCascadeSetup%d", i); - const auto cascadeSetupOutput = task.addJob(jobName, lightFrame, i, tagBits, tagMask); + const auto cascadeSetupOutput = task.addJob(jobName, shadowFrame, i, tagBits, tagMask); const auto shadowFilter = cascadeSetupOutput.getN(0); auto antiFrustum = render::Varying(ViewFrustumPointer()); cascadeFrustums[i] = cascadeSetupOutput.getN(1); @@ -110,17 +115,18 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende // GPU jobs: Render to shadow map sprintf(jobName, "RenderShadowMap%d", i); const auto shadowInputs = RenderShadowMap::Inputs(culledShadowItemsAndBounds.getN(0), - culledShadowItemsAndBounds.getN(1), lightFrame).asVarying(); + culledShadowItemsAndBounds.getN(1), shadowFrame).asVarying(); task.addJob(jobName, shadowInputs, shapePlumber, i); sprintf(jobName, "ShadowCascadeTeardown%d", i); task.addJob(jobName, shadowFilter); cascadeSceneBBoxes[i] = culledShadowItemsAndBounds.getN(1); } - - output = render::Varying(cascadeSceneBBoxes); - task.addJob("ShadowTeardown", setupOutput); + + + output = Output(cascadeSceneBBoxes, setupOutput.getN(3)); + } static void computeNearFar(const Triangle& triangle, const Plane shadowClipPlanes[4], float& near, float& far) { @@ -211,12 +217,12 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con const auto& inShapes = inputs.get0(); const auto& inShapeBounds = inputs.get1(); - const auto& lightFrame = inputs.get2(); + const auto& shadowFrame = inputs.get2(); - auto lightStage = renderContext->_scene->getStage(); - assert(lightStage); - - auto shadow = lightStage->getCurrentKeyShadow(*lightFrame); + LightStage::ShadowPointer shadow; + if (shadowFrame && !shadowFrame->_objects.empty()) { + shadow = shadowFrame->_objects.front(); + } if (!shadow || _cascadeIndex >= shadow->getCascadeCount()) { return; } @@ -314,7 +320,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con RenderShadowSetup::RenderShadowSetup() : _cameraFrustum{ std::make_shared() }, _coarseShadowFrustum{ std::make_shared() } { - + _shadowFrameCache = std::make_shared(); } void RenderShadowSetup::configure(const Config& configuration) { @@ -338,12 +344,19 @@ void RenderShadowSetup::setSlopeBias(int cascadeIndex, float value) { _bias[cascadeIndex]._slope = value * value * value * 0.01f; } -void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output) { +void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, const Input& input, Output& output) { // Abort all jobs if not casting shadows auto lightStage = renderContext->_scene->getStage(); - auto lightFrame = *input; assert(lightStage); - if (!lightStage->getCurrentKeyLight(lightFrame) || !lightStage->getCurrentKeyLight(lightFrame)->getCastShadows()) { + + const auto lightFrame = *input.get0(); + const auto lightingModel = input.get1(); + + // Clear previous shadow frame always + _shadowFrameCache->_objects.clear(); + output.edit3() = _shadowFrameCache; + + if (!lightingModel->isShadowEnabled() || !lightStage->getCurrentKeyLight(lightFrame) || !lightStage->getCurrentKeyLight(lightFrame)->getCastShadows()) { renderContext->taskFlow.abortTask(); return; } @@ -357,22 +370,29 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c *_cameraFrustum = args->getViewFrustum(); output.edit2() = _cameraFrustum; - const auto globalShadow = lightStage->getCurrentKeyShadow(lightFrame); - if (globalShadow) { - globalShadow->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); + if (!_globalShadowObject) { + _globalShadowObject = std::make_shared(graphics::LightPointer(), SHADOW_MAX_DISTANCE, SHADOW_CASCADE_COUNT); + } + + const auto theGlobalLight = lightStage->getCurrentKeyLight(lightFrame); + if (theGlobalLight && theGlobalLight->getCastShadows()) { + _globalShadowObject->setLight(theGlobalLight); + _globalShadowObject->setKeylightFrustum(args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); - auto& firstCascade = globalShadow->getCascade(0); + auto& firstCascade = _globalShadowObject->getCascade(0); auto& firstCascadeFrustum = firstCascade.getFrustum(); unsigned int cascadeIndex; // Adjust each cascade frustum - for (cascadeIndex = 0; cascadeIndex < globalShadow->getCascadeCount(); ++cascadeIndex) { + for (cascadeIndex = 0; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { auto& bias = _bias[cascadeIndex]; - globalShadow->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), + _globalShadowObject->setKeylightCascadeFrustum(cascadeIndex, args->getViewFrustum(), SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR, bias._constant, bias._slope); } + _shadowFrameCache->pushShadow(_globalShadowObject); + // Now adjust coarse frustum bounds auto frustumPosition = firstCascadeFrustum->getPosition(); auto farTopLeft = firstCascadeFrustum->getFarTopLeft() - frustumPosition; @@ -385,8 +405,8 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c auto near = firstCascadeFrustum->getNearClip(); auto far = firstCascadeFrustum->getFarClip(); - for (cascadeIndex = 1; cascadeIndex < globalShadow->getCascadeCount(); ++cascadeIndex) { - auto& cascadeFrustum = globalShadow->getCascade(cascadeIndex).getFrustum(); + for (cascadeIndex = 1; cascadeIndex < _globalShadowObject->getCascadeCount(); ++cascadeIndex) { + auto& cascadeFrustum = _globalShadowObject->getCascade(cascadeIndex).getFrustum(); farTopLeft = cascadeFrustum->getFarTopLeft() - frustumPosition; farBottomRight = cascadeFrustum->getFarBottomRight() - frustumPosition; @@ -425,36 +445,42 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, c } void RenderShadowCascadeSetup::run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output) { - auto lightStage = renderContext->_scene->getStage(); - const auto& lightFrame = *input; - assert(lightStage); + const auto shadowFrame = input; // Cache old render args RenderArgs* args = renderContext->args; RenderShadowTask::CullFunctor cullFunctor; + if (shadowFrame && !shadowFrame->_objects.empty() && shadowFrame->_objects[0]) { + const auto globalShadow = shadowFrame->_objects[0]; - const auto globalShadow = lightStage->getCurrentKeyShadow(lightFrame); - if (globalShadow && _cascadeIndex < globalShadow->getCascadeCount()) { - // Second item filter is to filter items to keep in shadow frustum computation (here we need to keep shadow receivers) - output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask); + if (globalShadow && _cascadeIndex < globalShadow->getCascadeCount()) { + // Second item filter is to filter items to keep in shadow frustum computation (here we need to keep shadow receivers) + output.edit0() = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered().withTagBits(_tagBits, _tagMask); - // Set the keylight render args - auto& cascade = globalShadow->getCascade(_cascadeIndex); - auto& cascadeFrustum = cascade.getFrustum(); - args->pushViewFrustum(*cascadeFrustum); - auto texelSize = glm::min(cascadeFrustum->getHeight(), cascadeFrustum->getWidth()) / cascade.framebuffer->getSize().x; - // Set the cull threshold to 24 shadow texels. This is totally arbitrary - const auto minTexelCount = 24.0f; - // TODO : maybe adapt that with LOD management system? - texelSize *= minTexelCount; - cullFunctor._minSquareSize = texelSize * texelSize; + // Set the keylight render args + auto& cascade = globalShadow->getCascade(_cascadeIndex); + auto& cascadeFrustum = cascade.getFrustum(); + args->pushViewFrustum(*cascadeFrustum); + auto texelSize = glm::min(cascadeFrustum->getHeight(), cascadeFrustum->getWidth()) / cascade.framebuffer->getSize().x; + // Set the cull threshold to 24 shadow texels. This is totally arbitrary + const auto minTexelCount = 24.0f; + // TODO : maybe adapt that with LOD management system? + texelSize *= minTexelCount; + cullFunctor._minSquareSize = texelSize * texelSize; - output.edit1() = cascadeFrustum; - } else { + output.edit1() = cascadeFrustum; + + } else { + output.edit0() = ItemFilter::Builder::nothing(); + output.edit1() = ViewFrustumPointer(); + } + } + else { output.edit0() = ItemFilter::Builder::nothing(); output.edit1() = ViewFrustumPointer(); } + output.edit2() = cullFunctor; } diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index e90725d66d..271c3e8200 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -19,13 +19,14 @@ #include "Shadows_shared.slh" +#include "LightingModel.h" #include "LightStage.h" class ViewFrustum; class RenderShadowMap { public: - using Inputs = render::VaryingSet3; + using Inputs = render::VaryingSet3; using JobModel = render::Job::ModelI; RenderShadowMap(render::ShapePlumberPointer shapePlumber, unsigned int cascadeIndex) : _shapePlumber{ shapePlumber }, _cascadeIndex{ cascadeIndex } {} @@ -36,10 +37,12 @@ protected: unsigned int _cascadeIndex; }; -class RenderShadowTaskConfig : public render::Task::Config::Persistent { +//class RenderShadowTaskConfig : public render::Task::Config::Persistent { +class RenderShadowTaskConfig : public render::Task::Config { Q_OBJECT public: - RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {} + // RenderShadowTaskConfig() : render::Task::Config::Persistent(QStringList() << "Render" << "Engine" << "Shadows", true) {} + RenderShadowTaskConfig() {} signals: void dirty(); @@ -49,9 +52,10 @@ class RenderShadowTask { public: // There is one AABox per shadow cascade - using Output = render::VaryingArray; + using Input = render::VaryingSet2; + using Output = render::VaryingSet2, LightStage::ShadowFramePointer>; using Config = RenderShadowTaskConfig; - using JobModel = render::Task::ModelO; + using JobModel = render::Task::ModelIO; RenderShadowTask() {} void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cameraCullFunctor, uint8_t tagBits = 0x00, uint8_t tagMask = 0x00); @@ -99,14 +103,14 @@ signals: class RenderShadowSetup { public: - using Inputs = LightStage::FramePointer; - using Outputs = render::VaryingSet3; + using Input = RenderShadowTask::Input; + using Output = render::VaryingSet4; using Config = RenderShadowSetupConfig; - using JobModel = render::Job::ModelIO; + using JobModel = render::Job::ModelIO; RenderShadowSetup(); void configure(const Config& configuration); - void run(const render::RenderContextPointer& renderContext, const Inputs& input, Outputs& output); + void run(const render::RenderContextPointer& renderContext, const Input& input, Output& output); private: @@ -117,13 +121,16 @@ private: float _slope; } _bias[SHADOW_CASCADE_MAX_COUNT]; + LightStage::ShadowFrame::Object _globalShadowObject; + LightStage::ShadowFramePointer _shadowFrameCache; + void setConstantBias(int cascadeIndex, float value); void setSlopeBias(int cascadeIndex, float value); }; class RenderShadowCascadeSetup { public: - using Inputs = LightStage::FramePointer; + using Inputs = LightStage::ShadowFramePointer; using Outputs = render::VaryingSet3; using JobModel = render::Job::ModelIO; @@ -147,7 +154,7 @@ public: class RenderShadowTeardown { public: - using Input = RenderShadowSetup::Outputs; + using Input = RenderShadowSetup::Output; using JobModel = render::Job::ModelI; void run(const render::RenderContextPointer& renderContext, const Input& input); }; diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index 2e03082ff4..7230635060 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -10,24 +10,32 @@ // #include "RenderViewTask.h" +#include "AssembleLightingStageTask.h" #include "RenderShadowTask.h" #include "RenderDeferredTask.h" #include "RenderForwardTask.h" void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits, uint8_t tagMask) { - // auto items = input.get(); - const auto items = task.addJob("FetchCullSort", cullFunctor, tagBits, tagMask); assert(items.canCast()); + // Issue the lighting model, aka the big global settings for the view + const auto lightingModel = task.addJob("LightingModel"); + + // Assemble the lighting stages current frames + const auto lightingStageFramesAndZones = task.addJob("AssembleStages", items); + if (isDeferred) { // Warning : the cull functor passed to the shadow pass should only be testing for LOD culling. If frustum culling // is performed, then casters not in the view frustum will be removed, which is not what we wish. - const auto cascadeSceneBBoxes = task.addJob("RenderShadowTask", cullFunctor, tagBits, tagMask); - const auto renderInput = RenderDeferredTask::Input(items, cascadeSceneBBoxes).asVarying(); - task.addJob("RenderDeferredTask", renderInput, true); + const auto shadowTaskIn = RenderShadowTask::Input(lightingStageFramesAndZones.get().get0()[0], lightingModel).asVarying(); + const auto shadowTaskOut = task.addJob("RenderShadowTask", shadowTaskIn, cullFunctor, tagBits, tagMask); + + const auto renderInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying(); + task.addJob("RenderDeferredTask", renderInput); } else { - task.addJob("Forward", items); + const auto renderInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying(); + task.addJob("Forward", renderInput); } } diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 4ffc8730a7..0e9672a7f2 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -51,7 +51,7 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& outp output = zoneItems; } -void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { +void SetupZones::run(const RenderContextPointer& context, const Input& input) { // Grab light, background, haze, and bloom stages and clear them auto lightStage = context->_scene->getStage(); assert(lightStage); @@ -70,7 +70,7 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) bloomStage->_currentFrame.clear(); // call render over the zones to grab their components in the correct order first... - render::renderItems(context, inputs); + render::renderItems(context, input); // Finally add the default lights and background: lightStage->_currentFrame.pushSunLight(lightStage->getDefaultLight()); diff --git a/libraries/render-utils/src/ZoneRenderer.h b/libraries/render-utils/src/ZoneRenderer.h index 1646c5977d..6eeee1293a 100644 --- a/libraries/render-utils/src/ZoneRenderer.h +++ b/libraries/render-utils/src/ZoneRenderer.h @@ -21,12 +21,12 @@ class SetupZones { public: - using Inputs = render::ItemBounds; - using JobModel = render::Job::ModelI; + using Input = render::ItemBounds; + using JobModel = render::Job::ModelI; SetupZones() {} - void run(const render::RenderContextPointer& context, const Inputs& inputs); + void run(const render::RenderContextPointer& context, const Input& input); }; class ZoneRendererConfig : public render::Task::Config { @@ -51,13 +51,14 @@ public: static const render::Selection::Name ZONES_SELECTION; - using Inputs = render::ItemBounds; + using Input = render::ItemBounds; + using Output = render::ItemBounds; using Config = ZoneRendererConfig; - using JobModel = render::Task::ModelI; + using JobModel = render::Task::ModelIO; ZoneRendererTask() {} - void build(JobModel& task, const render::Varying& inputs, render::Varying& output); + void build(JobModel& task, const render::Varying& input, render::Varying& output); void configure(const Config& config) { _maxDrawn = config.maxDrawn; } diff --git a/libraries/render/src/render/FilterTask.h b/libraries/render/src/render/FilterTask.h index 9b40728b00..c2244e5f57 100644 --- a/libraries/render/src/render/FilterTask.h +++ b/libraries/render/src/render/FilterTask.h @@ -114,7 +114,8 @@ namespace render { class SelectItems { public: using Inputs = VaryingSet3; - using JobModel = Job::ModelIO; + using Outputs = ItemBounds; + using JobModel = Job::ModelIO; std::string _name; SelectItems() {} diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 7b9765dca1..324f1d879f 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -70,5 +70,13 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto overlayTransparents = task.addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; - output = Output(BucketList{ opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, background }, spatialSelection); + // split up the overlays into 3D front, hud + const auto filteredOverlaysOpaque = task.addJob("FilterOverlaysLayeredOpaque", overlayOpaques, ItemKey::Layer::LAYER_1); + const auto filteredOverlaysTransparent = task.addJob("FilterOverlaysLayeredTransparent", overlayTransparents, ItemKey::Layer::LAYER_1); + + + output = Output(BucketList{ opaques, transparents, lights, metas, overlayOpaques, overlayTransparents, + filteredOverlaysOpaque.getN(0), filteredOverlaysTransparent.getN(0), + filteredOverlaysOpaque.getN(1), filteredOverlaysTransparent.getN(1), + background }, spatialSelection); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.h b/libraries/render/src/render/RenderFetchCullSortTask.h index 8c9f2e7304..a75c814d91 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.h +++ b/libraries/render/src/render/RenderFetchCullSortTask.h @@ -25,6 +25,11 @@ public: META, OVERLAY_OPAQUE_SHAPE, OVERLAY_TRANSPARENT_SHAPE, + LAYER_FRONT_OPAQUE_SHAPE, + LAYER_FRONT_TRANSPARENT_SHAPE, + LAYER_HUD_OPAQUE_SHAPE, + LAYER_HUD_TRANSPARENT_SHAPE, + BACKGROUND, NUM_BUCKETS diff --git a/libraries/task/src/task/Task.cpp b/libraries/task/src/task/Task.cpp index 9123ef8b04..2d6493fbc5 100644 --- a/libraries/task/src/task/Task.cpp +++ b/libraries/task/src/task/Task.cpp @@ -29,5 +29,3 @@ void TaskFlow::abortTask() { bool TaskFlow::doAbortTask() const { return _doAbortTask; } - - diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index fb7012b16c..632e8a222e 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -146,7 +146,7 @@ public: Concept(name, config), _data(Data(std::forward(args)...)), _input(input), - _output(Output()) { + _output(Output(), name + ".o") { applyConfiguration(); } @@ -419,6 +419,7 @@ protected: template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > using VaryingSet7 = task::VaryingSet7; \ template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8; \ template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > using VaryingSet9 = task::VaryingSet9; \ + template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > using VaryingSet10 = task::VaryingSet10; \ template < class T, int NUM > using VaryingArray = task::VaryingArray; diff --git a/libraries/task/src/task/Varying.h b/libraries/task/src/task/Varying.h index 9536db2799..686a00446b 100644 --- a/libraries/task/src/task/Varying.h +++ b/libraries/task/src/task/Varying.h @@ -12,10 +12,13 @@ #ifndef hifi_task_Varying_h #define hifi_task_Varying_h +#include #include #include namespace task { +class Varying; + // A varying piece of data, to be used as Job/Task I/O class Varying { @@ -23,15 +26,16 @@ public: Varying() {} Varying(const Varying& var) : _concept(var._concept) {} Varying& operator=(const Varying& var) { - _concept = var._concept; + _concept = var._concept; return (*this); } - template Varying(const T& data) : _concept(std::make_shared>(data)) {} + template Varying(const T& data, const std::string& name = "noname") : _concept(std::make_shared>(data, name)) {} template bool canCast() const { return !!std::dynamic_pointer_cast>(_concept); } template const T& get() const { return std::static_pointer_cast>(_concept)->_data; } template T& edit() { return std::static_pointer_cast>(_concept)->_data; } + const std::string name() const { return _concept->name(); } // access potential sub varyings contained in this one. Varying operator[] (uint8_t index) const { return (*_concept)[index]; } @@ -45,23 +49,30 @@ public: protected: class Concept { public: + Concept(const std::string& name) : _name(name) {} + virtual ~Concept() = default; virtual Varying operator[] (uint8_t index) const = 0; virtual uint8_t length() const = 0; + + const std::string name() { return _name; } + + const std::string _name; }; template class Model : public Concept { public: using Data = T; - Model(const Data& data) : _data(data) {} + Model(const Data& data, const std::string& name) : Concept(name), _data(data) {} virtual ~Model() = default; virtual Varying operator[] (uint8_t index) const override { - Varying var; - return var; + return Varying(); + } + virtual uint8_t length() const override { + return 0; } - virtual uint8_t length() const override { return 0; } Data _data; }; @@ -69,11 +80,10 @@ protected: std::shared_ptr _concept; }; -using VaryingPairBase = std::pair; template < typename T0, typename T1 > -class VaryingSet2 : public VaryingPairBase { +class VaryingSet2 : public std::pair { public: - using Parent = VaryingPairBase; + using Parent = std::pair; typedef void is_proxy_tag; VaryingSet2() : Parent(Varying(T0()), Varying(T1())) {} @@ -98,7 +108,6 @@ public: Varying asVarying() const { return Varying((*this)); } }; - template class VaryingSet3 : public std::tuple{ public: @@ -168,7 +177,6 @@ public: Varying asVarying() const { return Varying((*this)); } }; - template class VaryingSet5 : public std::tuple{ public: @@ -289,6 +297,26 @@ public: const T6& get6() const { return std::get<6>((*this)).template get(); } T6& edit6() { return std::get<6>((*this)).template edit(); } + virtual Varying operator[] (uint8_t index) const { + switch (index) { + default: + return std::get<0>((*this)); + case 1: + return std::get<1>((*this)); + case 2: + return std::get<2>((*this)); + case 3: + return std::get<3>((*this)); + case 4: + return std::get<4>((*this)); + case 5: + return std::get<5>((*this)); + case 6: + return std::get<6>((*this)); + }; + } + virtual uint8_t length() const { return 7; } + Varying asVarying() const { return Varying((*this)); } }; @@ -325,6 +353,28 @@ public: const T7& get7() const { return std::get<7>((*this)).template get(); } T7& edit7() { return std::get<7>((*this)).template edit(); } + virtual Varying operator[] (uint8_t index) const { + switch (index) { + default: + return std::get<0>((*this)); + case 1: + return std::get<1>((*this)); + case 2: + return std::get<2>((*this)); + case 3: + return std::get<3>((*this)); + case 4: + return std::get<4>((*this)); + case 5: + return std::get<5>((*this)); + case 6: + return std::get<6>((*this)); + case 7: + return std::get<7>((*this)); + }; + } + virtual uint8_t length() const { return 8; } + Varying asVarying() const { return Varying((*this)); } }; @@ -363,6 +413,98 @@ public: const T8& get8() const { return std::get<8>((*this)).template get(); } T8& edit8() { return std::get<8>((*this)).template edit(); } + virtual Varying operator[] (uint8_t index) const { + switch (index) { + default: + return std::get<0>((*this)); + case 1: + return std::get<1>((*this)); + case 2: + return std::get<2>((*this)); + case 3: + return std::get<3>((*this)); + case 4: + return std::get<4>((*this)); + case 5: + return std::get<5>((*this)); + case 6: + return std::get<6>((*this)); + case 7: + return std::get<7>((*this)); + case 8: + return std::get<8>((*this)); + }; + } + virtual uint8_t length() const { return 9; } + + Varying asVarying() const { return Varying((*this)); } +}; + + +template +class VaryingSet10 : public std::tuple { +public: + using Parent = std::tuple; + + VaryingSet10() : Parent(Varying(T0()), Varying(T1()), Varying(T2()), Varying(T3()), Varying(T4()), Varying(T5()), Varying(T6()), Varying(T7()), Varying(T8()), Varying(T9())) {} + VaryingSet10(const VaryingSet10& src) : Parent(std::get<0>(src), std::get<1>(src), std::get<2>(src), std::get<3>(src), std::get<4>(src), std::get<5>(src), std::get<6>(src), std::get<7>(src), std::get<8>(src), std::get<9>(src)) {} + VaryingSet10(const Varying& first, const Varying& second, const Varying& third, const Varying& fourth, const Varying& fifth, const Varying& sixth, const Varying& seventh, const Varying& eighth, const Varying& nine, const Varying& ten) : Parent(first, second, third, fourth, fifth, sixth, seventh, eighth, nine, ten) {} + + const T0& get0() const { return std::get<0>((*this)).template get(); } + T0& edit0() { return std::get<0>((*this)).template edit(); } + + const T1& get1() const { return std::get<1>((*this)).template get(); } + T1& edit1() { return std::get<1>((*this)).template edit(); } + + const T2& get2() const { return std::get<2>((*this)).template get(); } + T2& edit2() { return std::get<2>((*this)).template edit(); } + + const T3& get3() const { return std::get<3>((*this)).template get(); } + T3& edit3() { return std::get<3>((*this)).template edit(); } + + const T4& get4() const { return std::get<4>((*this)).template get(); } + T4& edit4() { return std::get<4>((*this)).template edit(); } + + const T5& get5() const { return std::get<5>((*this)).template get(); } + T5& edit5() { return std::get<5>((*this)).template edit(); } + + const T6& get6() const { return std::get<6>((*this)).template get(); } + T6& edit6() { return std::get<6>((*this)).template edit(); } + + const T7& get7() const { return std::get<7>((*this)).template get(); } + T7& edit7() { return std::get<7>((*this)).template edit(); } + + const T8& get8() const { return std::get<8>((*this)).template get(); } + T8& edit8() { return std::get<8>((*this)).template edit(); } + + const T9& get9() const { return std::get<9>((*this)).template get(); } + T9& edit9() { return std::get<9>((*this)).template edit(); } + + virtual Varying operator[] (uint8_t index) const { + switch (index) { + default: + return std::get<0>((*this)); + case 1: + return std::get<1>((*this)); + case 2: + return std::get<2>((*this)); + case 3: + return std::get<3>((*this)); + case 4: + return std::get<4>((*this)); + case 5: + return std::get<5>((*this)); + case 6: + return std::get<6>((*this)); + case 7: + return std::get<7>((*this)); + case 8: + return std::get<8>((*this)); + case 9: + return std::get<9>((*this)); + }; + } + virtual uint8_t length() const { return 10; } Varying asVarying() const { return Varying((*this)); } }; @@ -381,6 +523,7 @@ public: std::copy(list.begin(), list.end(), std::array::begin()); } }; + } #endif // hifi_task_Varying_h diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 71fb3e1f70..40563e4b2c 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -45,6 +45,24 @@ function job_propKeys(job) { return propKeys; } +// Access job inputs +// return all the inputs of a job +function job_inoutKeys(job) { + var keys = Object.keys(job) + var inoutKeys = []; + for (var k=0; k < keys.length;k++) { + // Filter for relevant property + var key = keys[k] + if ((typeof job[key]) !== "function") { + if ((key == "input") || (key == "output")) { + inoutKeys.push(keys[k]); + } + } + } + + return inoutKeys; +} + // Use this function to create a functor that will fill the specifed array with one entry name per task and job and it s rank function job_list_functor(jobList, maxDepth) { if (maxDepth === undefined) maxDepth = 100 @@ -55,7 +73,7 @@ function job_list_functor(jobList, maxDepth) { } // Use this function to create a functor that will print the content of the Job visited calling the specified 'printout' function -function job_print_functor(printout, showProps, maxDepth) { +function job_print_functor(printout, showProps, showInOuts, maxDepth) { if (maxDepth === undefined) maxDepth = 100 return function (job, depth, index) { var tab = " " @@ -69,6 +87,14 @@ function job_print_functor(printout, showProps, maxDepth) { printout(depthTab + tab + tab + typeof prop + " " + keys[p] + " " + prop); } } + if (showInOuts) { + printout("jsdkfkjdskflj") + var inouts = job_inoutKeys(job); + for (var p=0; p < inouts.length;p++) { + var prop = job[inouts[p]] + printout(depthTab + tab + tab + typeof prop + " " + inouts[p] + " " + prop); + } + } return depth < maxDepth; } } diff --git a/scripts/developer/utilities/lib/jet/qml/TaskList.qml b/scripts/developer/utilities/lib/jet/qml/TaskList.qml index 166f604666..e4b0267d3f 100644 --- a/scripts/developer/utilities/lib/jet/qml/TaskList.qml +++ b/scripts/developer/utilities/lib/jet/qml/TaskList.qml @@ -32,7 +32,7 @@ Rectangle { Component.onCompleted: { var message = "" - var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }, false); + var functor = Jet.job_print_functor(function (line) { message += line + "\n"; }, false, true); Jet.task_traverseTree(rootConfig, functor); textArea.append(message); } diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 78edf7939f..9737fb7f1a 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -47,8 +47,8 @@ Rectangle { "Emissive:LightingModel:enableEmissive", "Lightmap:LightingModel:enableLightmap", "Background:LightingModel:enableBackground", - "Haze:LightingModel:enableHaze", - "ssao:AmbientOcclusion:enabled", + "Haze:LightingModel:enableHaze", + "ssao:LightingModel:enableAmbientOcclusion", "Textures:LightingModel:enableMaterialTexturing" ] HifiControls.CheckBox { @@ -93,7 +93,7 @@ Rectangle { "Spot:LightingModel:enableSpotLight", "Light Contour:LightingModel:showLightContour", "Zone Stack:DrawZoneStack:enabled", - "Shadow:RenderShadowTask:enabled" + "Shadow:LightingModel:enableShadow" ] HifiControls.CheckBox { boxSize: 20 diff --git a/scripts/developer/utilities/render/engineList.js b/scripts/developer/utilities/render/engineList.js new file mode 100644 index 0000000000..85028ded53 --- /dev/null +++ b/scripts/developer/utilities/render/engineList.js @@ -0,0 +1,13 @@ + function openEngineTaskView() { + // Set up the qml ui + var qml = Script.resolvePath('engineList.qml'); + var window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + //window.closed.connect(function() { Script.stop(); }); + } + openEngineTaskView(); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineList.qml b/scripts/developer/utilities/render/engineList.qml new file mode 100644 index 0000000000..bf5c2a13a8 --- /dev/null +++ b/scripts/developer/utilities/render/engineList.qml @@ -0,0 +1,30 @@ +// +// engineList.qml +// +// Created by Sam Gateau on 12/3/2018 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + +import "../lib/jet/qml" as Jet + +Item { + HifiConstants { id: hifi;} + id: render; + anchors.fill: parent + + property var mainViewTask: Render.getConfig("RenderMainView") + + Jet.TaskList { + rootConfig: Render + anchors.fill: render + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/workload/avatars.js b/scripts/developer/utilities/workload/avatars.js new file mode 100644 index 0000000000..3080ef09db --- /dev/null +++ b/scripts/developer/utilities/workload/avatars.js @@ -0,0 +1,129 @@ +"use strict"; + +// +// Avatars.js +// tablet-engine app +// +// Copyright 2018 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 +// + +(function() { + var TABLET_BUTTON_NAME = "Avatars"; + var QMLAPP_URL = Script.resolvePath("./avatars.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/lod-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/lod-a.svg"); + + var onTablet = false; // set this to true to use the tablet, false use a floating window + + var onAppScreen = false; + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + var hasEventBridge = false; + + var onScreen = false; + var window; + + function onClicked() { + if (onTablet) { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } else { + if (onScreen) { + killWindow() + } else { + createWindow() + } + } + } + + function createWindow() { + var qml = Script.resolvePath(QMLAPP_URL); + window = Desktop.createWindow(Script.resolvePath(QMLAPP_URL), { + title: TABLET_BUTTON_NAME, + flags: Desktop.ALWAYS_ON_TOP, + presentationMode: Desktop.PresentationMode.NATIVE, + size: {x: 400, y: 600} + }); + window.closed.connect(killWindow); + window.fromQml.connect(fromQml); + onScreen = true + button.editProperties({isActive: true}); + } + + function killWindow() { + if (window !== undefined) { + window.closed.disconnect(killWindow); + window.fromQml.disconnect(fromQml); + window.close() + window = undefined + } + onScreen = false + button.editProperties({isActive: false}) + } + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (onTablet) { + onAppScreen = (url === QMLAPP_URL); + + button.editProperties({isActive: onAppScreen}); + wireEventBridge(onAppScreen); + } + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + Script.scriptEnding.connect(function () { + killWindow() + if (onAppScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + }); + + function fromQml(message) { + } + + function sendToQml(message) { + if (onTablet) { + tablet.sendToQml(message); + } else { + if (window) { + window.sendToQml(message); + } + } + } + +}()); diff --git a/scripts/developer/utilities/workload/avatars.qml b/scripts/developer/utilities/workload/avatars.qml new file mode 100644 index 0000000000..5951e72c31 --- /dev/null +++ b/scripts/developer/utilities/workload/avatars.qml @@ -0,0 +1,78 @@ +// +// avatars.qml +// scripts/developer/utilities/workload +// +// Created by Sam Gateau on 2018.11.28 +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +import stylesUit 1.0 +import controlsUit 1.0 as HifiControls + +import "../lib/plotperf" +import "../render/configSlider" + +Item { + id: root + anchors.fill:parent + + Component.onCompleted: { + } + + Component.onDestruction: { + } + + Column { + id: topHeader + spacing: 8 + anchors.right: parent.right + anchors.left: parent.left + } + + Column { + id: stats + spacing: 4 + anchors.right: parent.right + anchors.left: parent.left + anchors.top: topHeader.bottom + anchors.bottom: parent.bottom + + function evalEvenHeight() { + // Why do we have to do that manually ? cannot seem to find a qml / anchor / layout mode that does that ? + var numPlots = (children.length + - 2) + return (height - topLine.height - bottomLine.height - spacing * (numPlots - 1)) / (numPlots) + } + + Separator { + id: topLine + } + + PlotPerf { + title: "Avatars" + height: parent.evalEvenHeight() + object: Stats + valueScale: 1 + valueUnit: "num" + plots: [ + { + prop: "updatedAvatarCount", + label: "updatedAvatarCount", + color: "#FFFF00" + }, + { + prop: "notUpdatedAvatarCount", + label: "notUpdatedAvatarCount", + color: "#00FF00" + } + ] + } + Separator { + id: bottomLine + } + } +}