From c704a8d8c56f8455960e7cc96a0ac99cf25c24d1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 13:53:11 -0800 Subject: [PATCH] Add RenderShadowTask --- .../render-utils/src/RenderShadowTask.cpp | 128 ++++++++++++++++++ libraries/render-utils/src/RenderShadowTask.h | 41 ++++++ libraries/render/src/render/DrawTask.h | 1 + 3 files changed, 170 insertions(+) create mode 100644 libraries/render-utils/src/RenderShadowTask.cpp create mode 100644 libraries/render-utils/src/RenderShadowTask.h diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp new file mode 100644 index 0000000000..1447da624d --- /dev/null +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -0,0 +1,128 @@ +// +// RenderShadowTask.cpp +// render-utils/src/ +// +// Created by Zach Pomerantz on 1/7/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include "DeferredLightingEffect.h" +#include "FramebufferCache.h" + +#include "RenderShadowTask.h" + +#include "model_shadow_vert.h" +#include "skin_model_shadow_vert.h" + +#include "model_shadow_frag.h" +#include "skin_model_shadow_frag.h" + +using namespace render; + +void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, + const render::ItemIDsBounds& inItems) { + assert(renderContext->getArgs()); + assert(renderContext->getArgs()->_viewFrustum); + + const auto& lightStage = DependencyManager::get()->getLightStage(); + const auto globalLight = lightStage.lights[0]; + const auto& shadow = globalLight->shadow; + const auto& fbo = shadow.framebuffer; + + RenderArgs* args = renderContext->getArgs(); + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + glm::ivec4 viewport{0, 0, fbo->getWidth(), fbo->getHeight()}; + batch.setViewportTransform(viewport); + batch.setStateScissorRect(viewport); + + batch.setFramebuffer(fbo); + batch.clearFramebuffer( + gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, + vec4(vec3(1.0, 1.0, 1.0), 1.0), 1.0, 0, true); + + batch.setProjectionTransform(shadow.getProjection()); + batch.setViewTransform(shadow.getView()); + + renderShapes(sceneContext, renderContext, _shapePlumber, inItems); + args->_batch = nullptr; + }); +} + +RenderShadowTask::RenderShadowTask() : Task() { + // Prepare the ShapePipeline + ShapePlumberPointer shapePlumber = std::make_shared(); + { + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_BACK); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + + auto modelVertex = gpu::Shader::createVertex(std::string(model_shadow_vert)); + auto modelPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); + gpu::ShaderPointer modelProgram = gpu::Shader::createProgram(modelVertex, modelPixel); + shapePlumber->addPipeline( + ShapeKey::Filter::Builder().withoutSkinned(), + modelProgram, state); + + auto skinVertex = gpu::Shader::createVertex(std::string(skin_model_shadow_vert)); + auto skinPixel = gpu::Shader::createPixel(std::string(skin_model_shadow_frag)); + gpu::ShaderPointer skinProgram = gpu::Shader::createProgram(skinVertex, skinPixel); + shapePlumber->addPipeline( + ShapeKey::Filter::Builder().withSkinned(), + skinProgram, state); + } + + // CPU: Fetch shadow-casting opaques + addJob("FetchShadowMap"); + + // CPU: Cull against KeyLight frustum (nearby viewing camera) + addJob>("CullShadowMap", _jobs.back().getOutput()); + + // CPU: Sort front to back + addJob("DepthSortShadowMap", _jobs.back().getOutput()); + + // GPU: Render to shadow map + addJob("RenderShadowMap", _jobs.back().getOutput(), shapePlumber); +} + +void RenderShadowTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + assert(sceneContext); + RenderArgs* args = renderContext->getArgs(); + + // sanity checks + if (!sceneContext->_scene || !args) { + return; + } + + // TODO: If we're not using the global keylight, bail + const auto& lightStage = DependencyManager::get()->getLightStage(); + const auto globalLight = lightStage.lights[0]; + + // If the global light is not set, bail + if (!globalLight) { + return; + } + + ViewFrustum* viewFrustum = args->_viewFrustum; + + const auto nearClip = viewFrustum->getNearClip(); + globalLight->shadow.setKeylightFrustum(viewFrustum, nearClip - 1, nearClip + 20); + + // Set the keylight frustum + args->_viewFrustum = globalLight->shadow.getFrustum().get(); + + for (auto job : _jobs) { + job.run(sceneContext, renderContext); + } + + // Reset the view frustum + args->_viewFrustum = viewFrustum; +}; diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h new file mode 100644 index 0000000000..333ed18c84 --- /dev/null +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -0,0 +1,41 @@ +// +// RenderShadowTask.h +// render-utils/src/ +// +// Created by Zach Pomerantz on 1/7/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_RenderShadowTask_h +#define hifi_RenderShadowTask_h + +#include +#include + +#include +#include + +class ViewFrustum; + +class RenderShadowMap { +public: + RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, + const render::ItemIDsBounds& inItems); + + using JobModel = render::Task::Job::ModelI; +protected: + render::ShapePlumberPointer _shapePlumber; +}; + +class RenderShadowTask : public render::Task { +public: + RenderShadowTask(); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); +}; + +#endif // hifi_RenderShadowTask_h diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index b31ec9763e..3c2c0973b2 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -28,6 +28,7 @@ void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPo class FetchItems { public: typedef std::function ProbeNumItems; + FetchItems() {} FetchItems(const ProbeNumItems& probe): _probeNumItems(probe) {} FetchItems(const ItemFilter& filter, const ProbeNumItems& probe): _filter(filter), _probeNumItems(probe) {}