mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Merge pull request #14602 from samcake/punk
Case 20303 : Cleaning up the render view tasks and jobs for better 2ndary camera
This commit is contained in:
commit
440f517b88
44 changed files with 1070 additions and 524 deletions
|
@ -1,16 +1,2 @@
|
|||
{
|
||||
"RenderMainView": {
|
||||
"RenderShadowTask": {
|
||||
"Enabled": {
|
||||
"enabled": true
|
||||
}
|
||||
},
|
||||
"RenderDeferredTask": {
|
||||
"AmbientOcclusion": {
|
||||
"Enabled": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<RenderShadowTask>("RenderMainView.RenderShadowTask");
|
||||
if (mainViewShadowTaskConfig) {
|
||||
if (action->isChecked()) {
|
||||
mainViewShadowTaskConfig->setPreset("Enabled");
|
||||
} else {
|
||||
mainViewShadowTaskConfig->setPreset("None");
|
||||
}
|
||||
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("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<AmbientOcclusionEffect>("RenderMainView.AmbientOcclusion");
|
||||
if (mainViewAmbientOcclusionConfig) {
|
||||
if (action->isChecked()) {
|
||||
mainViewAmbientOcclusionConfig->setPreset("Enabled");
|
||||
} else {
|
||||
mainViewAmbientOcclusionConfig->setPreset("None");
|
||||
}
|
||||
auto lightingModelConfig = renderConfig->getConfig<MakeLightingModel>("RenderMainView.LightingModel");
|
||||
if (lightingModelConfig) {
|
||||
lightingModelConfig->setAmbientOcclusion(action->isChecked());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::WorldAxes);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <RenderForwardTask.h>
|
||||
#include <RenderViewTask.h>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
#include <gpu/Context.h>
|
||||
|
@ -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<SecondaryCameraJob>("SecondaryCamera");
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
if (isDeferred) {
|
||||
const render::Varying cascadeSceneBBoxes;
|
||||
const auto renderInput = RenderDeferredTask::Input(items, cascadeSceneBBoxes).asVarying();
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", renderInput, false);
|
||||
} else {
|
||||
task.addJob<RenderForwardTask>("Forward", items);
|
||||
}
|
||||
|
||||
task.addJob<RenderViewTask>("RenderSecondView", cullFunctor, isDeferred, render::ItemKey::TAG_BITS_1, render::ItemKey::TAG_BITS_1);
|
||||
|
||||
task.addJob<EndSecondaryCameraFrame>("EndSecondaryCamera", cachedArg);
|
||||
}
|
|
@ -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<GeometryCache>();
|
||||
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<LightStage>();
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -303,8 +303,6 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() {
|
|||
}
|
||||
|
||||
void AmbientOcclusionEffect::configure(const Config& config) {
|
||||
DependencyManager::get<DeferredLightingEffect>()->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();
|
||||
|
|
|
@ -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<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
|
||||
using Outputs = render::VaryingSet2<AmbientOcclusionFramebufferPointer, gpu::BufferView>;
|
||||
using Input = render::VaryingSet4<LightingModelPointer, DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
|
||||
using Output = render::VaryingSet2<AmbientOcclusionFramebufferPointer, gpu::BufferView>;
|
||||
using Config = AmbientOcclusionEffectConfig;
|
||||
using JobModel = render::Job::ModelIO<AmbientOcclusionEffect, Inputs, Outputs, Config>;
|
||||
using JobModel = render::Job::ModelIO<AmbientOcclusionEffect, Input, Output, Config>;
|
||||
|
||||
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 {
|
||||
|
|
50
libraries/render-utils/src/AssembleLightingStageTask.cpp
Normal file
50
libraries/render-utils/src/AssembleLightingStageTask.cpp
Normal file
|
@ -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 <render/DrawTask.h>
|
||||
|
||||
void FetchCurrentFrames::run(const render::RenderContextPointer& renderContext, Output& output) {
|
||||
auto lightStage = renderContext->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
output.edit0() = std::make_shared<LightStage::Frame>(lightStage->_currentFrame);
|
||||
|
||||
auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
assert(backgroundStage);
|
||||
output.edit1() = std::make_shared<BackgroundStage::Frame>(backgroundStage->_currentFrame);
|
||||
|
||||
auto hazeStage = renderContext->_scene->getStage<HazeStage>();
|
||||
assert(hazeStage);
|
||||
output.edit2() = std::make_shared<HazeStage::Frame>(hazeStage->_currentFrame);
|
||||
|
||||
auto bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
assert(bloomStage);
|
||||
output.edit3() = std::make_shared<BloomStage::Frame>(bloomStage->_currentFrame);
|
||||
}
|
||||
|
||||
|
||||
void AssembleLightingStageTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
const auto& fetchCullSortOut = input.get<Input>();
|
||||
const auto& items = fetchCullSortOut.get0();
|
||||
//const auto& items = input.get<Input>();
|
||||
|
||||
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<ZoneRendererTask>("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<render::DrawLight>("DrawLight", lights);
|
||||
|
||||
// Fetch the current frame stacks from all the stages
|
||||
const auto currentStageFrames = task.addJob<FetchCurrentFrames>("FetchCurrentFrames");
|
||||
|
||||
output = Output(currentStageFrames, zones);
|
||||
}
|
||||
|
44
libraries/render-utils/src/AssembleLightingStageTask.h
Normal file
44
libraries/render-utils/src/AssembleLightingStageTask.h
Normal file
|
@ -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 <render/RenderFetchCullSortTask.h>
|
||||
#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<LightStage::FramePointer, BackgroundStage::FramePointer, HazeStage::FramePointer, BloomStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelO<FetchCurrentFrames, Output>;
|
||||
|
||||
FetchCurrentFrames() {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, Output& output);
|
||||
};
|
||||
|
||||
class AssembleLightingStageTask {
|
||||
public:
|
||||
using Input = RenderFetchCullSortTask::Output;
|
||||
using Output = render::VaryingSet2<FetchCurrentFrames::Output, ZoneRendererTask::Output>;
|
||||
using JobModel = render::Task::ModelIO<AssembleLightingStageTask, Input, Output, render::Task::Config>;
|
||||
|
||||
AssembleLightingStageTask() {}
|
||||
|
||||
void build(JobModel& task, const render::Varying& input, render::Varying& output);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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<LightStage>();
|
||||
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) {
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
AmbientOcclusionFramebufferPointer,
|
||||
VelocityFramebufferPointer,
|
||||
DeferredFrameTransformPointer,
|
||||
LightStage::FramePointer>;
|
||||
LightStage::ShadowFramePointer>;
|
||||
using Config = DebugDeferredBufferConfig;
|
||||
using JobModel = render::Job::ModelI<DebugDeferredBuffer, Inputs, Config>;
|
||||
|
||||
|
|
|
@ -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<LightStage>();
|
||||
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<DeferredLightingEffect>()->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<BackgroundStage>();
|
||||
|
|
|
@ -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<SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, SubsurfaceScatteringResourcePointer>;
|
||||
using Inputs = render::VaryingSet8<
|
||||
DeferredFrameTransformPointer, DeferredFramebufferPointer, ExtraDeferredBuffer, LightingModelPointer, LightClustersPointer, LightStage::FramePointer, LightStage::ShadowFramePointer, HazeStage::FramePointer>;
|
||||
|
||||
using Config = RenderDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<RenderDeferred, Inputs, Config>;
|
||||
|
||||
RenderDeferred(bool renderShadows = false);
|
||||
RenderDeferred();
|
||||
|
||||
void configure(const Config& config);
|
||||
|
||||
|
@ -203,7 +195,6 @@ protected:
|
|||
gpu::RangeTimerPointer _gpuTimer;
|
||||
|
||||
private:
|
||||
bool _renderShadows { false };
|
||||
};
|
||||
|
||||
class DefaultLightingSetup {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -167,16 +167,16 @@ protected:
|
|||
|
||||
class LightClusteringPass {
|
||||
public:
|
||||
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, LightingModelPointer, LightStage::FramePointer, LinearDepthFramebufferPointer>;
|
||||
using Outputs = LightClustersPointer;
|
||||
using Input = render::VaryingSet4<DeferredFrameTransformPointer, LightingModelPointer, LightStage::FramePointer, LinearDepthFramebufferPointer>;
|
||||
using Output = LightClustersPointer;
|
||||
using Config = LightClusteringPassConfig;
|
||||
using JobModel = render::Job::ModelIO<LightClusteringPass, Inputs, Outputs, Config>;
|
||||
using JobModel = render::Job::ModelIO<LightClusteringPass, Input, Output, Config>;
|
||||
|
||||
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<DebugLightClusters, Inputs, Config>;
|
||||
|
||||
|
|
|
@ -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<Shadow>(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) {
|
||||
|
|
|
@ -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<Cascade>;
|
||||
|
||||
|
@ -106,25 +113,17 @@ public:
|
|||
float _maxDistance;
|
||||
Cascades _cascades;
|
||||
|
||||
class Schema : public ShadowParameters {
|
||||
public:
|
||||
|
||||
Schema();
|
||||
|
||||
};
|
||||
UniformBufferView _schemaBuffer = nullptr;
|
||||
};
|
||||
|
||||
using ShadowPointer = std::shared_ptr<Shadow>;
|
||||
using Shadows = render::indexed_container::IndexedPointerVector<Shadow>;
|
||||
|
||||
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<LightPointer, ShadowPointer>;
|
||||
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<Frame>;
|
||||
|
||||
class ShadowFrame {
|
||||
public:
|
||||
ShadowFrame() {}
|
||||
|
||||
void clear() {}
|
||||
|
||||
using Object = ShadowPointer;
|
||||
using Objects = std::vector<Object>;
|
||||
|
||||
void pushShadow(const ShadowPointer& shadow) {
|
||||
_objects.emplace_back(shadow);
|
||||
}
|
||||
|
||||
|
||||
Objects _objects;
|
||||
};
|
||||
using ShadowFramePointer = std::shared_ptr<ShadowFrame>;
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -187,6 +187,24 @@ bool LightingModel::isBlendshapeEnabled() const {
|
|||
return (bool)_parametersBuffer.get<Parameters>().enableBlendshape;
|
||||
}
|
||||
|
||||
void LightingModel::setAmbientOcclusion(bool enable) {
|
||||
if (enable != isAmbientOcclusionEnabled()) {
|
||||
_parametersBuffer.edit<Parameters>().enableAmbientOcclusion = (float)enable;
|
||||
}
|
||||
}
|
||||
bool LightingModel::isAmbientOcclusionEnabled() const {
|
||||
return (bool)_parametersBuffer.get<Parameters>().enableAmbientOcclusion;
|
||||
}
|
||||
|
||||
void LightingModel::setShadow(bool enable) {
|
||||
if (enable != isShadowEnabled()) {
|
||||
_parametersBuffer.edit<Parameters>().enableShadow = (float)enable;
|
||||
}
|
||||
}
|
||||
bool LightingModel::isShadowEnabled() const {
|
||||
return (bool)_parametersBuffer.get<Parameters>().enableShadow;
|
||||
}
|
||||
|
||||
MakeLightingModel::MakeLightingModel() {
|
||||
_lightingModel = std::make_shared<LightingModel>();
|
||||
}
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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<ViewFrustumPointer>();
|
||||
|
@ -214,38 +214,18 @@ void ExtractFrustums::run(const render::RenderContextPointer& renderContext, con
|
|||
}
|
||||
|
||||
// Return shadow frustum
|
||||
auto lightStage = args->_scene->getStage<LightStage>(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<ViewFrustumPointer>();
|
||||
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<LightStage>();
|
||||
assert(lightStage);
|
||||
outputs.edit0() = std::make_shared<LightStage::Frame>(lightStage->_currentFrame);
|
||||
|
||||
auto backgroundStage = renderContext->_scene->getStage<BackgroundStage>();
|
||||
assert(backgroundStage);
|
||||
outputs.edit1() = std::make_shared<BackgroundStage::Frame>(backgroundStage->_currentFrame);
|
||||
|
||||
auto hazeStage = renderContext->_scene->getStage<HazeStage>();
|
||||
assert(hazeStage);
|
||||
outputs.edit2() = std::make_shared<HazeStage::Frame>(hazeStage->_currentFrame);
|
||||
|
||||
auto bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
assert(bloomStage);
|
||||
outputs.edit3() = std::make_shared<BloomStage::Frame>(bloomStage->_currentFrame);
|
||||
}
|
||||
|
|
|
@ -10,13 +10,8 @@
|
|||
#define hifi_RenderCommonTask_h
|
||||
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
#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<ViewFrustumPointer, FRUSTUM_COUNT>;
|
||||
using JobModel = render::Job::ModelIO<ExtractFrustums, Inputs, Outputs>;
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& output);
|
||||
};
|
||||
|
||||
|
||||
class FetchCurrentFrames {
|
||||
public:
|
||||
using Outputs = render::VaryingSet4<LightStage::FramePointer, BackgroundStage::FramePointer, HazeStage::FramePointer, BloomStage::FramePointer>;
|
||||
using JobModel = render::Job::ModelO<FetchCurrentFrames, Outputs>;
|
||||
|
||||
FetchCurrentFrames() {}
|
||||
|
||||
void run(const render::RenderContextPointer& renderContext, Outputs& outputs);
|
||||
};
|
||||
|
||||
#endif // hifi_RenderDeferredTask_h
|
||||
|
|
|
@ -72,6 +72,23 @@ namespace gr {
|
|||
}
|
||||
|
||||
|
||||
class RenderDeferredTaskDebug {
|
||||
public:
|
||||
using ExtraBuffers = render::VaryingSet6<LinearDepthFramebufferPointer, SurfaceGeometryFramebufferPointer, AmbientOcclusionFramebufferPointer, gpu::BufferView, SubsurfaceScatteringResourcePointer, VelocityFramebufferPointer>;
|
||||
using Input = render::VaryingSet9<RenderFetchCullSortTask::Output, RenderShadowTask::Output,
|
||||
AssembleLightingStageTask::Output, LightClusteringPass::Output,
|
||||
PrepareDeferred::Outputs, ExtraBuffers, GenerateDeferredFrameTransform::Output,
|
||||
JitterSample::Output, LightingModel>;
|
||||
|
||||
using JobModel = render::Task::ModelI<RenderDeferredTaskDebug, Input>;
|
||||
|
||||
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<SelectItems>("MetaSelection", selectMetaInput, selectionName);
|
||||
const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, std::string()).asVarying();
|
||||
const auto selectedMetasAndOpaques = task.addJob<SelectItems>("OpaqueSelection", selectMetaAndOpaqueInput, selectionName);
|
||||
const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, std::string()).asVarying();
|
||||
return task.addJob<SelectItems>("TransparentSelection", selectItemInput, selectionName);
|
||||
}
|
||||
|
||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output, bool renderShadows) {
|
||||
const auto& inputs = input.get<Input>();
|
||||
const auto& items = inputs.get0();
|
||||
|
||||
void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) {
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
|
||||
// Prepare the ShapePipelines
|
||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||
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<Input>();
|
||||
|
||||
// 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<GenerateDeferredFrameTransform>("DeferredFrameTransform", jitter);
|
||||
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
|
||||
|
||||
const auto opaqueRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOpaqueRangeTimer", "DrawOpaques");
|
||||
|
||||
|
@ -164,38 +188,25 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto scatteringResource = task.addJob<SubsurfaceScattering>("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<AmbientOcclusionEffect>("AmbientOcclusion", ambientOcclusionInputs);
|
||||
const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Outputs>(0);
|
||||
const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Outputs>(1);
|
||||
const auto ambientOcclusionFramebuffer = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Output>(0);
|
||||
const auto ambientOcclusionUniforms = ambientOcclusionOutputs.getN<AmbientOcclusionEffect::Output>(1);
|
||||
|
||||
// Velocity
|
||||
const auto velocityBufferInputs = VelocityBufferPass::Inputs(deferredFrameTransform, deferredFramebuffer).asVarying();
|
||||
const auto velocityBufferOutputs = task.addJob<VelocityBufferPass>("VelocityBuffer", velocityBufferInputs);
|
||||
const auto velocityBuffer = velocityBufferOutputs.getN<VelocityBufferPass::Outputs>(0);
|
||||
|
||||
// Clear Light, Haze, Bloom, and Skybox Stages and render zones from the general metas bucket
|
||||
const auto zones = task.addJob<ZoneRendererTask>("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>("DrawLight", lights);
|
||||
|
||||
// Fetch the current frame stacks from all the stages
|
||||
const auto currentFrames = task.addJob<FetchCurrentFrames>("FetchCurrentFrames");
|
||||
const auto lightFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(0);
|
||||
const auto backgroundFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(1);
|
||||
const auto hazeFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(2);
|
||||
const auto bloomFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(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<LightClusteringPass>("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>("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>("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<DrawHaze>("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<DrawDeferred>("DrawTransparentDeferred", transparentsInputs, shapePlumber);
|
||||
|
||||
// Light Cluster Grid Debuging job
|
||||
{
|
||||
const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying();
|
||||
task.addJob<DebugLightClusters>("DebugLightClusters", debugLightClustersInputs);
|
||||
}
|
||||
|
||||
const auto outlineRangeTimer = task.addJob<BeginGPURangeTimer>("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<DrawHighlightTask>("DrawHighlight", outlineInputs);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("HighlightRangeTimer", outlineRangeTimer);
|
||||
|
||||
const auto overlaysInFrontRangeTimer = task.addJob<BeginGPURangeTimer>("BeginOverlaysInFrontRangeTimer", "BeginOverlaysInFrontRangeTimer");
|
||||
|
||||
// Layered Overlays
|
||||
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, render::hifi::LAYER_3D_FRONT);
|
||||
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, render::hifi::LAYER_3D_FRONT);
|
||||
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
|
||||
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(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<SetSeparateDeferredDepthBuffer>("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<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("OverlaysInFrontRangeTimer", overlaysInFrontRangeTimer);
|
||||
|
||||
const auto toneAndPostRangeTimer = task.addJob<BeginGPURangeTimer>("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<ToneMappingDeferred>("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<RenderDeferredTaskDebug>("DebugRenderDeferredTask", debugInputs);
|
||||
}
|
||||
|
||||
// Upscale to finale resolution
|
||||
const auto primaryFramebuffer = task.addJob<render::Upsample>("PrimaryBufferUpscale", scaledPrimaryFramebuffer);
|
||||
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("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<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
|
||||
|
||||
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
|
||||
|
||||
// Blit!
|
||||
task.addJob<Blit>("Blit", primaryFramebuffer);
|
||||
}
|
||||
|
||||
RenderDeferredTaskDebug::RenderDeferredTaskDebug() {
|
||||
}
|
||||
|
||||
void RenderDeferredTaskDebug::build(JobModel& task, const render::Varying& input, render::Varying& outputs) {
|
||||
|
||||
const auto& inputs = input.get<Input>();
|
||||
|
||||
// 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>("DebugLightClusters", debugLightClustersInputs);
|
||||
}
|
||||
|
||||
|
||||
{ // Debug the bounds of the rendered items, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawMetaBounds", metas);
|
||||
task.addJob<DrawBounds>("DrawOpaqueBounds", opaques);
|
||||
task.addJob<DrawBounds>("DrawTransparentBounds", transparents);
|
||||
|
||||
|
||||
task.addJob<DrawBounds>("DrawLightBounds", lights);
|
||||
task.addJob<DrawBounds>("DrawZones", zones);
|
||||
const auto frustums = task.addJob<ExtractFrustums>("ExtractFrustums", lightFrame);
|
||||
const auto frustums = task.addJob<ExtractFrustums>("ExtractFrustums", shadowFrame);
|
||||
const auto viewFrustum = frustums.getN<ExtractFrustums::Outputs>(ExtractFrustums::VIEW_FRUSTUM);
|
||||
task.addJob<DrawFrustum>("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<DrawFrustum>(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<DrawAABox>(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<SelectItems>("MetaSelection", selectMetaInput, selectionBaseName);
|
||||
const auto selectMetaAndOpaqueInput = SelectItems::Inputs(opaques, selectedMetas, std::string()).asVarying();
|
||||
const auto selectedMetasAndOpaques = task.addJob<SelectItems>("OpaqueSelection", selectMetaAndOpaqueInput, selectionBaseName);
|
||||
const auto selectItemInput = SelectItems::Inputs(transparents, selectedMetasAndOpaques, std::string()).asVarying();
|
||||
const auto selectedItems = task.addJob<SelectItems>("TransparentSelection", selectItemInput, selectionBaseName);
|
||||
|
||||
// Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true
|
||||
task.addJob<DrawBounds>("DrawSelectionBounds", selectedItems);
|
||||
|
@ -289,10 +393,16 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<DrawBounds>("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent);
|
||||
}
|
||||
|
||||
{ // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque);
|
||||
task.addJob<DrawBounds>("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>("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<TextureCache>()->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<DebugZoneLighting>("DrawZoneStack", debugZoneInputs);
|
||||
|
||||
}
|
||||
|
||||
// Upscale to finale resolution
|
||||
const auto primaryFramebuffer = task.addJob<render::Upsample>("PrimaryBufferUpscale", scaledPrimaryFramebuffer);
|
||||
|
||||
// Composite the HUD and HUD overlays
|
||||
task.addJob<CompositeHUD>("HUD");
|
||||
|
||||
const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1);
|
||||
const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(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<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
|
||||
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
|
||||
|
||||
{ // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer
|
||||
task.addJob<DrawBounds>("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque);
|
||||
task.addJob<DrawBounds>("DrawOverlayHUDTransparentBounds", overlaysHUDTransparent);
|
||||
}
|
||||
|
||||
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
|
||||
|
||||
// Blit!
|
||||
task.addJob<Blit>("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<DeferredLightingEffect>();
|
||||
|
||||
RenderArgs* args = renderContext->args;
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
#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<render::ItemBounds, HazeStage::FramePointer, LightStage::FramePointer, LightingModelPointer, LightClustersPointer, glm::vec2>;
|
||||
using Inputs = render::VaryingSet7<render::ItemBounds, HazeStage::FramePointer, LightStage::FramePointer, LightingModelPointer, LightClustersPointer, LightStage::ShadowFramePointer, glm::vec2>;
|
||||
using Config = DrawDeferredConfig;
|
||||
using JobModel = render::Job::ModelI<DrawDeferred, Inputs, Config>;
|
||||
|
||||
|
@ -137,21 +137,16 @@ signals:
|
|||
|
||||
class RenderDeferredTask {
|
||||
public:
|
||||
using Input = render::VaryingSet2<RenderFetchCullSortTask::Output, RenderShadowTask::Output>;
|
||||
using Input = render::VaryingSet4<RenderFetchCullSortTask::Output, LightingModelPointer, AssembleLightingStageTask::Output, RenderShadowTask::Output>;
|
||||
using Config = RenderDeferredTaskConfig;
|
||||
using JobModel = render::Task::ModelI<RenderDeferredTask, Input, Config>;
|
||||
|
||||
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
|
||||
|
|
|
@ -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<Input>();
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
|
||||
// Prepare the ShapePipelines
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
ShapePlumberPointer shapePlumber = std::make_shared<ShapePlumber>();
|
||||
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<Input>();
|
||||
|
||||
// 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<GenerateDeferredFrameTransform>("DeferredFrameTransform");
|
||||
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
|
||||
|
||||
// Filter zones from the general metas bucket
|
||||
const auto zones = task.addJob<ZoneRendererTask>("ZoneRenderer", metas);
|
||||
|
||||
// Fetch the current frame stacks from all the stages
|
||||
const auto currentFrames = task.addJob<FetchCurrentFrames>("FetchCurrentFrames");
|
||||
const auto lightFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(0);
|
||||
const auto backgroundFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(1);
|
||||
//const auto hazeFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(2);
|
||||
//const auto bloomFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(3);
|
||||
|
||||
// GPU jobs: Start preparing the main framebuffer
|
||||
const auto framebuffer = task.addJob<PrepareFramebuffer>("PrepareFramebuffer");
|
||||
|
@ -91,12 +98,9 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
task.addJob<PrepareStencil>("PrepareStencil", framebuffer);
|
||||
|
||||
// Layered Overlays
|
||||
const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, render::hifi::LAYER_3D_FRONT);
|
||||
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, render::hifi::LAYER_3D_FRONT);
|
||||
const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
|
||||
const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(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<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
|
||||
|
|
|
@ -14,17 +14,17 @@
|
|||
|
||||
#include <gpu/Pipeline.h>
|
||||
#include <render/RenderFetchCullSortTask.h>
|
||||
#include "AssembleLightingStageTask.h"
|
||||
#include "LightingModel.h"
|
||||
#include "LightStage.h"
|
||||
|
||||
class RenderForwardTask {
|
||||
public:
|
||||
using Input = RenderFetchCullSortTask::Output;
|
||||
using Input = render::VaryingSet3<RenderFetchCullSortTask::Output, LightingModelPointer, AssembleLightingStageTask::Output>;
|
||||
using JobModel = render::Task::ModelI<RenderForwardTask, Input>;
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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<DeferredLightingEffect>()->setShadowMapEnabled(configuration.isEnabled());
|
||||
//DependencyManager::get<DeferredLightingEffect>()->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>("FetchCurrentFrames");
|
||||
const auto lightFrame = currentFrames.getN<FetchCurrentFrames::Outputs>(0);
|
||||
// Starting with the Light Frame genreated in previous tasks
|
||||
|
||||
const auto& lightFrame = input.getN<Input>(0);
|
||||
|
||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup", lightFrame);
|
||||
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Outputs>(1);
|
||||
const auto setupOutput = task.addJob<RenderShadowSetup>("ShadowSetup", input);
|
||||
const auto queryResolution = setupOutput.getN<RenderShadowSetup::Output>(1);
|
||||
const auto shadowFrame = setupOutput.getN<RenderShadowSetup::Output>(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<RenderShadowSetup::Outputs>(2);
|
||||
const auto cameraFrustum = setupOutput.getN<RenderShadowSetup::Output>(2);
|
||||
const auto applyFunctorInputs = ApplyCullFunctorOnItemBounds::Inputs(shadowItems, cameraFrustum).asVarying();
|
||||
const auto culledShadowItems = task.addJob<ApplyCullFunctorOnItemBounds>("ShadowCullCamera", applyFunctorInputs, cameraCullFunctor);
|
||||
|
||||
|
@ -90,12 +95,12 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende
|
|||
#endif
|
||||
};
|
||||
|
||||
Output cascadeSceneBBoxes;
|
||||
render::VaryingArray<AABox,4> cascadeSceneBBoxes;
|
||||
|
||||
for (auto i = 0; i < SHADOW_CASCADE_MAX_COUNT; i++) {
|
||||
char jobName[64];
|
||||
sprintf(jobName, "ShadowCascadeSetup%d", i);
|
||||
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, lightFrame, i, tagBits, tagMask);
|
||||
const auto cascadeSetupOutput = task.addJob<RenderShadowCascadeSetup>(jobName, shadowFrame, i, tagBits, tagMask);
|
||||
const auto shadowFilter = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(0);
|
||||
auto antiFrustum = render::Varying(ViewFrustumPointer());
|
||||
cascadeFrustums[i] = cascadeSetupOutput.getN<RenderShadowCascadeSetup::Outputs>(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<CullShadowBounds::Outputs>(0),
|
||||
culledShadowItemsAndBounds.getN<CullShadowBounds::Outputs>(1), lightFrame).asVarying();
|
||||
culledShadowItemsAndBounds.getN<CullShadowBounds::Outputs>(1), shadowFrame).asVarying();
|
||||
task.addJob<RenderShadowMap>(jobName, shadowInputs, shapePlumber, i);
|
||||
sprintf(jobName, "ShadowCascadeTeardown%d", i);
|
||||
task.addJob<RenderShadowCascadeTeardown>(jobName, shadowFilter);
|
||||
|
||||
cascadeSceneBBoxes[i] = culledShadowItemsAndBounds.getN<CullShadowBounds::Outputs>(1);
|
||||
}
|
||||
|
||||
output = render::Varying(cascadeSceneBBoxes);
|
||||
|
||||
task.addJob<RenderShadowTeardown>("ShadowTeardown", setupOutput);
|
||||
|
||||
|
||||
output = Output(cascadeSceneBBoxes, setupOutput.getN<RenderShadowSetup::Output>(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<LightStage>();
|
||||
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<ViewFrustum>() },
|
||||
_coarseShadowFrustum{ std::make_shared<ViewFrustum>() } {
|
||||
|
||||
_shadowFrameCache = std::make_shared<LightStage::ShadowFrame>();
|
||||
}
|
||||
|
||||
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<LightStage>();
|
||||
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<LightStage::Shadow>(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<LightStage>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
|
||||
#include "Shadows_shared.slh"
|
||||
|
||||
#include "LightingModel.h"
|
||||
#include "LightStage.h"
|
||||
|
||||
class ViewFrustum;
|
||||
|
||||
class RenderShadowMap {
|
||||
public:
|
||||
using Inputs = render::VaryingSet3<render::ShapeBounds, AABox, LightStage::FramePointer>;
|
||||
using Inputs = render::VaryingSet3<render::ShapeBounds, AABox, LightStage::ShadowFramePointer>;
|
||||
using JobModel = render::Job::ModelI<RenderShadowMap, Inputs>;
|
||||
|
||||
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<AABox, SHADOW_CASCADE_MAX_COUNT>;
|
||||
using Input = render::VaryingSet2<LightStage::FramePointer, LightingModelPointer>;
|
||||
using Output = render::VaryingSet2<render::VaryingArray<AABox, SHADOW_CASCADE_MAX_COUNT>, LightStage::ShadowFramePointer>;
|
||||
using Config = RenderShadowTaskConfig;
|
||||
using JobModel = render::Task::ModelO<RenderShadowTask, Output, Config>;
|
||||
using JobModel = render::Task::ModelIO<RenderShadowTask, Input, Output, Config>;
|
||||
|
||||
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<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer>;
|
||||
using Input = RenderShadowTask::Input;
|
||||
using Output = render::VaryingSet4<RenderArgs::RenderMode, glm::ivec2, ViewFrustumPointer, LightStage::ShadowFramePointer>;
|
||||
using Config = RenderShadowSetupConfig;
|
||||
using JobModel = render::Job::ModelIO<RenderShadowSetup, Inputs, Outputs, Config>;
|
||||
using JobModel = render::Job::ModelIO<RenderShadowSetup, Input, Output, Config>;
|
||||
|
||||
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<render::ItemFilter, ViewFrustumPointer, RenderShadowTask::CullFunctor>;
|
||||
using JobModel = render::Job::ModelIO<RenderShadowCascadeSetup, Inputs, Outputs>;
|
||||
|
||||
|
@ -147,7 +154,7 @@ public:
|
|||
|
||||
class RenderShadowTeardown {
|
||||
public:
|
||||
using Input = RenderShadowSetup::Outputs;
|
||||
using Input = RenderShadowSetup::Output;
|
||||
using JobModel = render::Job::ModelI<RenderShadowTeardown, Input>;
|
||||
void run(const render::RenderContextPointer& renderContext, const Input& input);
|
||||
};
|
||||
|
|
|
@ -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<Input>();
|
||||
|
||||
const auto items = task.addJob<RenderFetchCullSortTask>("FetchCullSort", cullFunctor, tagBits, tagMask);
|
||||
assert(items.canCast<RenderFetchCullSortTask::Output>());
|
||||
|
||||
// Issue the lighting model, aka the big global settings for the view
|
||||
const auto lightingModel = task.addJob<MakeLightingModel>("LightingModel");
|
||||
|
||||
// Assemble the lighting stages current frames
|
||||
const auto lightingStageFramesAndZones = task.addJob<AssembleLightingStageTask>("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>("RenderShadowTask", cullFunctor, tagBits, tagMask);
|
||||
const auto renderInput = RenderDeferredTask::Input(items, cascadeSceneBBoxes).asVarying();
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", renderInput, true);
|
||||
const auto shadowTaskIn = RenderShadowTask::Input(lightingStageFramesAndZones.get<AssembleLightingStageTask::Output>().get0()[0], lightingModel).asVarying();
|
||||
const auto shadowTaskOut = task.addJob<RenderShadowTask>("RenderShadowTask", shadowTaskIn, cullFunctor, tagBits, tagMask);
|
||||
|
||||
const auto renderInput = RenderDeferredTask::Input(items, lightingModel, lightingStageFramesAndZones, shadowTaskOut).asVarying();
|
||||
task.addJob<RenderDeferredTask>("RenderDeferredTask", renderInput);
|
||||
} else {
|
||||
task.addJob<RenderForwardTask>("Forward", items);
|
||||
const auto renderInput = RenderForwardTask::Input(items, lightingModel, lightingStageFramesAndZones).asVarying();
|
||||
task.addJob<RenderForwardTask>("Forward", renderInput);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<LightStage>();
|
||||
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());
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
|
||||
class SetupZones {
|
||||
public:
|
||||
using Inputs = render::ItemBounds;
|
||||
using JobModel = render::Job::ModelI<SetupZones, Inputs>;
|
||||
using Input = render::ItemBounds;
|
||||
using JobModel = render::Job::ModelI<SetupZones, Input>;
|
||||
|
||||
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<ZoneRendererTask, Inputs, Config>;
|
||||
using JobModel = render::Task::ModelIO<ZoneRendererTask, Input, Output, Config>;
|
||||
|
||||
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; }
|
||||
|
||||
|
|
|
@ -114,7 +114,8 @@ namespace render {
|
|||
class SelectItems {
|
||||
public:
|
||||
using Inputs = VaryingSet3<ItemBounds, ItemBounds, std::string>;
|
||||
using JobModel = Job::ModelIO<SelectItems, Inputs, ItemBounds>;
|
||||
using Outputs = ItemBounds;
|
||||
using JobModel = Job::ModelIO<SelectItems, Inputs, Outputs>;
|
||||
|
||||
std::string _name;
|
||||
SelectItems() {}
|
||||
|
|
|
@ -70,5 +70,13 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin
|
|||
const auto overlayTransparents = task.addJob<DepthSortItems>("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<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, ItemKey::Layer::LAYER_1);
|
||||
const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, ItemKey::Layer::LAYER_1);
|
||||
|
||||
|
||||
output = Output(BucketList{ opaques, transparents, lights, metas, overlayOpaques, overlayTransparents,
|
||||
filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0), filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0),
|
||||
filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1), filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(1),
|
||||
background }, spatialSelection);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,5 +29,3 @@ void TaskFlow::abortTask() {
|
|||
bool TaskFlow::doAbortTask() const {
|
||||
return _doAbortTask;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
Concept(name, config),
|
||||
_data(Data(std::forward<A>(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<T0, T1, T2, T3, T4, T5, T6>; \
|
||||
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8<T0, T1, T2, T3, T4, T5, T6, T7>; \
|
||||
template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > using VaryingSet9 = task::VaryingSet9<T0, T1, T2, T3, T4, T5, T6, T7, T8>; \
|
||||
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<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>; \
|
||||
template < class T, int NUM > using VaryingArray = task::VaryingArray<T, NUM>;
|
||||
|
||||
|
||||
|
|
|
@ -12,10 +12,13 @@
|
|||
#ifndef hifi_task_Varying_h
|
||||
#define hifi_task_Varying_h
|
||||
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
|
||||
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 <class T> Varying(const T& data) : _concept(std::make_shared<Model<T>>(data)) {}
|
||||
template <class T> Varying(const T& data, const std::string& name = "noname") : _concept(std::make_shared<Model<T>>(data, name)) {}
|
||||
|
||||
template <class T> bool canCast() const { return !!std::dynamic_pointer_cast<Model<T>>(_concept); }
|
||||
template <class T> const T& get() const { return std::static_pointer_cast<const Model<T>>(_concept)->_data; }
|
||||
template <class T> T& edit() { return std::static_pointer_cast<Model<T>>(_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 T> 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> _concept;
|
||||
};
|
||||
|
||||
using VaryingPairBase = std::pair<Varying, Varying>;
|
||||
template < typename T0, typename T1 >
|
||||
class VaryingSet2 : public VaryingPairBase {
|
||||
class VaryingSet2 : public std::pair<Varying, Varying> {
|
||||
public:
|
||||
using Parent = VaryingPairBase;
|
||||
using Parent = std::pair<Varying, Varying>;
|
||||
typedef void is_proxy_tag;
|
||||
|
||||
VaryingSet2() : Parent(Varying(T0()), Varying(T1())) {}
|
||||
|
@ -98,7 +108,6 @@ public:
|
|||
Varying asVarying() const { return Varying((*this)); }
|
||||
};
|
||||
|
||||
|
||||
template <class T0, class T1, class T2>
|
||||
class VaryingSet3 : public std::tuple<Varying, Varying,Varying>{
|
||||
public:
|
||||
|
@ -168,7 +177,6 @@ public:
|
|||
Varying asVarying() const { return Varying((*this)); }
|
||||
};
|
||||
|
||||
|
||||
template <class T0, class T1, class T2, class T3, class T4>
|
||||
class VaryingSet5 : public std::tuple<Varying, Varying, Varying, Varying, Varying>{
|
||||
public:
|
||||
|
@ -289,6 +297,26 @@ public:
|
|||
const T6& get6() const { return std::get<6>((*this)).template get<T6>(); }
|
||||
T6& edit6() { return std::get<6>((*this)).template edit<T6>(); }
|
||||
|
||||
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>(); }
|
||||
T7& edit7() { return std::get<7>((*this)).template edit<T7>(); }
|
||||
|
||||
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>(); }
|
||||
T8& edit8() { return std::get<8>((*this)).template edit<T8>(); }
|
||||
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 T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
|
||||
class VaryingSet10 : public std::tuple<Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying> {
|
||||
public:
|
||||
using Parent = std::tuple<Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying, Varying>;
|
||||
|
||||
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>(); }
|
||||
T0& edit0() { return std::get<0>((*this)).template edit<T0>(); }
|
||||
|
||||
const T1& get1() const { return std::get<1>((*this)).template get<T1>(); }
|
||||
T1& edit1() { return std::get<1>((*this)).template edit<T1>(); }
|
||||
|
||||
const T2& get2() const { return std::get<2>((*this)).template get<T2>(); }
|
||||
T2& edit2() { return std::get<2>((*this)).template edit<T2>(); }
|
||||
|
||||
const T3& get3() const { return std::get<3>((*this)).template get<T3>(); }
|
||||
T3& edit3() { return std::get<3>((*this)).template edit<T3>(); }
|
||||
|
||||
const T4& get4() const { return std::get<4>((*this)).template get<T4>(); }
|
||||
T4& edit4() { return std::get<4>((*this)).template edit<T4>(); }
|
||||
|
||||
const T5& get5() const { return std::get<5>((*this)).template get<T5>(); }
|
||||
T5& edit5() { return std::get<5>((*this)).template edit<T5>(); }
|
||||
|
||||
const T6& get6() const { return std::get<6>((*this)).template get<T6>(); }
|
||||
T6& edit6() { return std::get<6>((*this)).template edit<T6>(); }
|
||||
|
||||
const T7& get7() const { return std::get<7>((*this)).template get<T7>(); }
|
||||
T7& edit7() { return std::get<7>((*this)).template edit<T7>(); }
|
||||
|
||||
const T8& get8() const { return std::get<8>((*this)).template get<T8>(); }
|
||||
T8& edit8() { return std::get<8>((*this)).template edit<T8>(); }
|
||||
|
||||
const T9& get9() const { return std::get<9>((*this)).template get<T9>(); }
|
||||
T9& edit9() { return std::get<9>((*this)).template edit<T9>(); }
|
||||
|
||||
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<Varying, NUM>::begin());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // hifi_task_Varying_h
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
13
scripts/developer/utilities/render/engineList.js
Normal file
13
scripts/developer/utilities/render/engineList.js
Normal file
|
@ -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();
|
30
scripts/developer/utilities/render/engineList.qml
Normal file
30
scripts/developer/utilities/render/engineList.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
129
scripts/developer/utilities/workload/avatars.js
Normal file
129
scripts/developer/utilities/workload/avatars.js
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}());
|
78
scripts/developer/utilities/workload/avatars.qml
Normal file
78
scripts/developer/utilities/workload/avatars.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue