From ee69d8f81704a58d3f35c5a722fb7e976c49b6b9 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 17:44:01 -0800 Subject: [PATCH 01/32] Fix bitsetters for ShapeKey::Builder --- libraries/render/src/render/ShapePipeline.cpp | 4 ++- libraries/render/src/render/ShapePipeline.h | 34 +++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 99424cbf4b..c83f16c456 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -91,7 +91,9 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke auto& batch = args->_batch; // Run the pipeline's BatchSetter on the passed in batch - shapePipeline->batchSetter(*shapePipeline, *batch); + if (shapePipeline->batchSetter) { + shapePipeline->batchSetter(*shapePipeline, *batch); + } // Setup the one pipeline (to rule them all) batch->setPipeline(shapePipeline->pipeline); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 3d189f15fa..1a6837efa3 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -83,32 +83,32 @@ public: Filter build() const { return Filter(_flags, _mask); } - Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } Builder& withTranslucent() { _flags.set(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } + Builder& withOpaque() { _flags.reset(TRANSLUCENT); _mask.set(TRANSLUCENT); return (*this); } - Builder& withLightmap() { _flags.reset(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); } - Builder& withoutLightmap() { _flags.set(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); } + Builder& withLightmap() { _flags.set(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); } + Builder& withoutLightmap() { _flags.reset(LIGHTMAP); _mask.set(LIGHTMAP); return (*this); } - Builder& withTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS); return (*this); } - Builder& withoutTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS); return (*this); } + Builder& withTangents() { _flags.set(TANGENTS); _mask.set(TANGENTS); return (*this); } + Builder& withoutTangents() { _flags.reset(TANGENTS); _mask.set(TANGENTS); return (*this); } - Builder& withSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); } - Builder& withoutSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); } + Builder& withSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); } + Builder& withoutSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); } - Builder& withEmissive() { _flags.reset(EMISSIVE); _mask.set(EMISSIVE); return (*this); } - Builder& withoutEmissive() { _flags.set(EMISSIVE); _mask.set(EMISSIVE); return (*this); } + Builder& withEmissive() { _flags.set(EMISSIVE); _mask.set(EMISSIVE); return (*this); } + Builder& withoutEmissive() { _flags.reset(EMISSIVE); _mask.set(EMISSIVE); return (*this); } - Builder& withSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } - Builder& withoutSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } + Builder& withSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } + Builder& withoutSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } - Builder& withStereo() { _flags.reset(STEREO); _mask.set(STEREO); return (*this); } - Builder& withoutStereo() { _flags.set(STEREO); _mask.set(STEREO); return (*this); } + Builder& withStereo() { _flags.set(STEREO); _mask.set(STEREO); return (*this); } + Builder& withoutStereo() { _flags.reset(STEREO); _mask.set(STEREO); return (*this); } - Builder& withDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } - Builder& withoutDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } + Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } + Builder& withoutDepthOnly() { _flags.reset(DEPTH_ONLY); _mask.set(DEPTH_ONLY); return (*this); } - Builder& withWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); } - Builder& withoutWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); } + Builder& withWireframe() { _flags.set(WIREFRAME); _mask.set(WIREFRAME); return (*this); } + Builder& withoutWireframe() { _flags.reset(WIREFRAME); _mask.set(WIREFRAME); return (*this); } protected: friend class Filter; From 293882916726ecaca47e811346a9ce84bd5e1766 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 17:48:09 -0800 Subject: [PATCH 02/32] Add shadow items to stats --- interface/resources/qml/Stats.qml | 9 +++++++++ interface/src/ui/Stats.cpp | 4 ++++ interface/src/ui/Stats.h | 8 ++++++++ libraries/shared/src/RenderArgs.h | 5 +++++ 4 files changed, 26 insertions(+) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 9954cab063..2155a11d91 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -188,6 +188,7 @@ Item { visible: root.expanded; text: "\tItems Rendered Opaque: " + root.opaqueRendered + " / Translucent: " + root.translucentRendered + + " / Shadow: " + root.shadowRendered + " / Other: " + root.otherRendered; } Text { @@ -198,6 +199,14 @@ Item { " / Out of view: " + root.opaqueOutOfView + " / Too small: " + root.opaqueTooSmall; } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + visible: root.expanded; + text: "\tShadow considered: " + root.shadowConsidered + + " / Out of view: " + root.shadowOutOfView + + " / Too small: " + root.shadowTooSmall; + } Text { color: root.fontColor; font.pixelSize: root.fontSize diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index b82ab93068..ae9e37b591 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -348,6 +348,10 @@ void Stats::setRenderDetails(const RenderDetails& details) { STAT_UPDATE(opaqueOutOfView, details._opaque._outOfView); STAT_UPDATE(opaqueTooSmall, details._opaque._tooSmall); STAT_UPDATE(opaqueRendered, (int)details._opaque._rendered); + STAT_UPDATE(shadowConsidered, (int)details._shadow._considered); + STAT_UPDATE(shadowOutOfView, details._shadow._outOfView); + STAT_UPDATE(shadowTooSmall, details._shadow._tooSmall); + STAT_UPDATE(shadowRendered, (int)details._shadow._rendered); STAT_UPDATE(translucentConsidered, (int)details._translucent._considered); STAT_UPDATE(translucentOutOfView, details._translucent._outOfView); STAT_UPDATE(translucentTooSmall, details._translucent._tooSmall); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 5e948ce0f0..fc01fe7f23 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -64,6 +64,10 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, opaqueOutOfView, 0) STATS_PROPERTY(int, opaqueTooSmall, 0) STATS_PROPERTY(int, opaqueRendered, 0) + STATS_PROPERTY(int, shadowConsidered, 0) + STATS_PROPERTY(int, shadowOutOfView, 0) + STATS_PROPERTY(int, shadowTooSmall, 0) + STATS_PROPERTY(int, shadowRendered, 0) STATS_PROPERTY(int, translucentConsidered, 0) STATS_PROPERTY(int, translucentOutOfView, 0) STATS_PROPERTY(int, translucentTooSmall, 0) @@ -151,6 +155,10 @@ signals: void opaqueOutOfViewChanged(); void opaqueTooSmallChanged(); void opaqueRenderedChanged(); + void shadowConsideredChanged(); + void shadowOutOfViewChanged(); + void shadowTooSmallChanged(); + void shadowRenderedChanged(); void translucentConsideredChanged(); void translucentOutOfViewChanged(); void translucentTooSmallChanged(); diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 789033b826..e5dfd5f8ea 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -36,6 +36,7 @@ class RenderDetails { public: enum Type { OPAQUE_ITEM, + SHADOW_ITEM, TRANSLUCENT_ITEM, OTHER_ITEM }; @@ -51,6 +52,7 @@ public: int _trianglesRendered = 0; Item _opaque; + Item _shadow; Item _translucent; Item _other; @@ -61,6 +63,9 @@ public: case OPAQUE_ITEM: _item = &_opaque; break; + case SHADOW_ITEM: + _item = &_shadow; + break; case TRANSLUCENT_ITEM: _item = &_translucent; break; From e471dcc90e931b5a5283f5e8663215b123929ad6 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 17:50:34 -0800 Subject: [PATCH 03/32] Fix GLBackend::do_setDepthRangeTransform by swapping hither/yon --- libraries/gpu/src/gpu/GLBackendTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/GLBackendTransform.cpp b/libraries/gpu/src/gpu/GLBackendTransform.cpp index 686b52296f..9bfd258833 100755 --- a/libraries/gpu/src/gpu/GLBackendTransform.cpp +++ b/libraries/gpu/src/gpu/GLBackendTransform.cpp @@ -51,7 +51,7 @@ void GLBackend::do_setViewportTransform(Batch& batch, size_t paramOffset) { void GLBackend::do_setDepthRangeTransform(Batch& batch, size_t paramOffset) { - Vec2 depthRange(batch._params[paramOffset + 0]._float, batch._params[paramOffset + 1]._float); + Vec2 depthRange(batch._params[paramOffset + 1]._float, batch._params[paramOffset + 0]._float); if ((depthRange.x != _transform._depthRange.x) || (depthRange.y != _transform._depthRange.y)) { _transform._depthRange = depthRange; From 70cc7d87e474baf0f7c8edc42e20a93cf4f03294 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 17:52:02 -0800 Subject: [PATCH 04/32] Expose global light through DeferredLighting singleton --- libraries/render-utils/src/DeferredLightingEffect.cpp | 4 ++++ libraries/render-utils/src/DeferredLightingEffect.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 7c8aa393d4..a5fce0b377 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -541,6 +541,10 @@ void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const gl light->setAmbientIntensity(ambientIntensity); } +model::LightPointer DeferredLightingEffect::getGlobalLight() { + return _allocatedLights[_globalLights.front()]; +} + void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) { _skybox = skybox; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index cb746153a1..e75961e11a 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -48,9 +48,10 @@ public: void setAmbientLightMode(int preset); void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity, float ambientIntensity); void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; } - void setGlobalSkybox(const model::SkyboxPointer& skybox); + model::LightPointer getGlobalLight(); + private: DeferredLightingEffect() = default; From 5c9c34377eb8bfa39e65dcb46cd24f5ca660ca70 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 17:53:15 -0800 Subject: [PATCH 05/32] Move GL context sync to render Engine (from Task) --- libraries/render-utils/src/RenderDeferredTask.cpp | 2 -- libraries/render/src/render/Engine.cpp | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index b9dfa3e3ec..37126e6558 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -186,8 +186,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setToneMappingExposure(renderContext->getTone().exposure); setToneMappingToneCurve(renderContext->getTone().toneCurve); - renderContext->getArgs()->_context->syncCache(); - for (auto job : _jobs) { job.run(sceneContext, renderContext); } diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index aa5816475a..06cfd2e78b 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Engine.h" using namespace render; @@ -34,7 +36,9 @@ void Engine::addTask(const TaskPointer& task) { } void Engine::run() { - // TODO: Tasks will need to be specified such that their data can feed into each other + // Sync GPU state before beginning to render + _renderContext->getArgs()->_context->syncCache(); + for (auto task : _tasks) { task->run(_sceneContext, _renderContext); } From 1436b4f6b168b82dd6683abdcde79f8f0ffcac92 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 18:17:40 -0800 Subject: [PATCH 06/32] Guard against unspecified deferredDebugMode --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index ca678770fb..ab2fa403f1 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -182,6 +182,14 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren assert(renderContext->getArgs()); assert(renderContext->getArgs()->_viewFrustum); RenderArgs* args = renderContext->getArgs(); + + // Guard against unspecified modes + auto mode = renderContext->_deferredDebugMode; + if (mode > (int)CustomMode) { + renderContext->_deferredDebugMode = -1; + return; + } + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { const auto geometryBuffer = DependencyManager::get(); const auto framebufferCache = DependencyManager::get(); From ed5c53f23c0f2cdd142a7dfccd2db3f7c73dfd66 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 13 Jan 2016 22:49:00 -0800 Subject: [PATCH 07/32] Add getCorners to ViewFrustum --- libraries/octree/src/ViewFrustum.cpp | 17 +++++++++++++++++ libraries/octree/src/ViewFrustum.h | 13 ++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index fd175a8e5b..0e7df1d9a4 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -736,6 +736,23 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth } } +const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) { + glm::vec3 normal = glm::normalize(_direction); + + auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) { + const auto dir = glm::normalize(_cornersWorld[nearCorner] - _cornersWorld[farCorner]); + const auto factor = depth / glm::dot(dir, normal); + return _position + factor * dir; + }; + + return Corners{ + getCorner(TOP_LEFT_NEAR, TOP_LEFT_FAR), + getCorner(TOP_RIGHT_NEAR, TOP_RIGHT_FAR), + getCorner(BOTTOM_LEFT_NEAR, BOTTOM_LEFT_FAR), + getCorner(BOTTOM_RIGHT_NEAR, BOTTOM_RIGHT_FAR) + }; +} + float ViewFrustum::distanceToCamera(const glm::vec3& point) const { glm::vec3 temp = getPosition() - point; float distanceToPoint = sqrtf(glm::dot(temp, temp)); diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 795a259a3c..4a39ac5f44 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -61,11 +61,22 @@ public: float getFarClip() const { return _farClip; } float getFocalLength() const { return _focalLength; } + const class Corners{ + public: + Corners(glm::vec3&& topLeft, glm::vec3&& topRight, glm::vec3&& bottomLeft, glm::vec3&& bottomRight) + : topLeft{ topLeft }, topRight{ topRight }, bottomLeft{ bottomLeft }, bottomRight{ bottomRight } {} + glm::vec3 topLeft; + glm::vec3 topRight; + glm::vec3 bottomLeft; + glm::vec3 bottomRight; + // Get the corners depth units from frustum position, along frustum orientation + } getCorners(const float& depth); + + // getters for corners const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; } const glm::vec3& getFarTopRight() const { return _cornersWorld[TOP_RIGHT_FAR]; } const glm::vec3& getFarBottomLeft() const { return _cornersWorld[BOTTOM_LEFT_FAR]; } const glm::vec3& getFarBottomRight() const { return _cornersWorld[BOTTOM_RIGHT_FAR]; } - const glm::vec3& getNearTopLeft() const { return _cornersWorld[TOP_LEFT_NEAR]; } const glm::vec3& getNearTopRight() const { return _cornersWorld[TOP_RIGHT_NEAR]; } const glm::vec3& getNearBottomLeft() const { return _cornersWorld[BOTTOM_LEFT_NEAR]; } From 82f7ea515d28afd07b603cf3489fea2496f3ce3c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 11:05:58 -0800 Subject: [PATCH 08/32] Clean up task construction --- .../render-utils/src/RenderDeferredTask.cpp | 43 +++++++---------- .../render-utils/src/RenderDeferredTask.h | 46 +++++++------------ libraries/render/src/render/Task.h | 7 +-- 3 files changed, 36 insertions(+), 60 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 37126e6558..d0d0338742 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -77,30 +77,28 @@ RenderDeferredTask::RenderDeferredTask() : Task() { ShapePlumberPointer shapePlumber = std::make_shared(); initDeferredPipelines(*shapePlumber); - // CPU only, create the list of renderedOpaques items - addJob("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { + // CPU: Fetch the renderOpaques + const auto fetchedOpaques = addJob("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { context->getItemsConfig().opaque.numFeed = count; })); - addJob>("CullOpaque", _jobs.back().getOutput()); - addJob("DepthSortOpaque", _jobs.back().getOutput()); - auto& renderedOpaques = _jobs.back().getOutput(); + const auto culledOpaques = addJob>("CullOpaque", fetchedOpaques); + const auto opaques = addJob("DepthSortOpaque", culledOpaques); // CPU only, create the list of renderedTransparents items - addJob("FetchTransparent", FetchItems( + const auto fetchedTransparents = addJob("FetchTransparent", FetchItems( ItemFilter::Builder::transparentShape().withoutLayered(), [](const RenderContextPointer& context, int count) { context->getItemsConfig().transparent.numFeed = count; } - )); - addJob>("CullTransparent", _jobs.back().getOutput()); - addJob("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false)); - auto& renderedTransparents = _jobs.back().getOutput(); + )); + const auto culledTransparents = addJob>("CullTransparent", fetchedTransparents); + const auto transparents = addJob("DepthSortTransparent", culledTransparents, DepthSortItems(false)); // GPU Jobs: Start preparing the deferred and lighting buffer addJob("PrepareDeferred"); // Render opaque objects in DeferredBuffer - addJob("DrawOpaqueDeferred", renderedOpaques, shapePlumber); + addJob("DrawOpaqueDeferred", opaques, shapePlumber); // Once opaque is all rendered create stencil background addJob("DrawOpaqueStencil"); @@ -116,16 +114,16 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // AO job, to be revisited addJob("AmbientOcclusion"); - _jobs.back().setEnabled(false); _occlusionJobIndex = (int)_jobs.size() - 1; + enableJob(_occlusionJobIndex, false); // AA job to be revisited addJob("Antialiasing"); - _jobs.back().setEnabled(false); _antialiasingJobIndex = (int)_jobs.size() - 1; + enableJob(_antialiasingJobIndex, false); // Render transparent objects forward in LigthingBuffer - addJob("DrawTransparentDeferred", renderedTransparents, shapePlumber); + addJob("DrawTransparentDeferred", transparents, shapePlumber); // Lighting Buffer ready for tone mapping addJob("ToneMapping"); @@ -133,24 +131,24 @@ RenderDeferredTask::RenderDeferredTask() : Task() { // Debugging Deferred buffer job addJob("DebugDeferredBuffer"); - _jobs.back().setEnabled(false); _drawDebugDeferredBufferIndex = (int)_jobs.size() - 1; + enableJob(_drawDebugDeferredBufferIndex, false); // Status icon rendering job { // Grab a texture map representing the different status icons and assign that to the drawStatsuJob auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg"; auto statusIconMap = DependencyManager::get()->getImageTexture(iconMapPath); - addJob("DrawStatus", renderedOpaques, DrawStatus(statusIconMap)); - _jobs.back().setEnabled(false); + addJob("DrawStatus", opaques, DrawStatus(statusIconMap)); _drawStatusJobIndex = (int)_jobs.size() - 1; + enableJob(_drawStatusJobIndex, false); } addJob("DrawOverlay3D", shapePlumber); addJob("HitEffect"); - _jobs.back().setEnabled(false); _drawHitEffectJobIndex = (int)_jobs.size() -1; + enableJob(_drawHitEffectJobIndex, false); addJob("Blit"); } @@ -168,21 +166,12 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend return; } - // Make sure we turn the deferred buffer debug on/off setDrawDebugDeferredBuffer(renderContext->_deferredDebugMode); - - // Make sure we turn the displayItemStatus on/off setDrawItemStatus(renderContext->getDrawStatus()); - - // Make sure we display hit effect on screen, as desired from a script setDrawHitEffect(renderContext->getDrawHitEffect()); - - // TODO: turn on/off AO through menu item setOcclusionStatus(renderContext->getOcclusionStatus()); - setAntialiasingStatus(renderContext->getFxaaStatus()); - setToneMappingExposure(renderContext->getTone().exposure); setToneMappingToneCurve(renderContext->getTone().toneCurve); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 85e3e7f211..4fe0c75198 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -113,41 +113,32 @@ public: class RenderDeferredTask : public render::Task { public: - RenderDeferredTask(); - int _drawDebugDeferredBufferIndex = -1; - int _drawStatusJobIndex = -1; - int _drawHitEffectJobIndex = -1; + int _drawDebugDeferredBufferIndex; + int _drawStatusJobIndex; + int _drawHitEffectJobIndex; + int _occlusionJobIndex; + int _antialiasingJobIndex; + int _toneMappingJobIndex; - void setDrawDebugDeferredBuffer(int draw) { - if (_drawDebugDeferredBufferIndex >= 0) { - _jobs[_drawDebugDeferredBufferIndex].setEnabled(draw >= 0); - } - } - bool doDrawDebugDeferredBuffer() const { if (_drawDebugDeferredBufferIndex >= 0) { return _jobs[_drawDebugDeferredBufferIndex].isEnabled(); } else { return false; } } + void setDrawDebugDeferredBuffer(int draw) { enableJob(_drawDebugDeferredBufferIndex, draw >= 0); } + bool doDrawDebugDeferredBuffer() const { return getEnableJob(_drawDebugDeferredBufferIndex); } - void setDrawItemStatus(int draw) { - if (_drawStatusJobIndex >= 0) { - _jobs[_drawStatusJobIndex].setEnabled(draw > 0); - } - } - bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } } + void setDrawItemStatus(int draw) { enableJob(_drawStatusJobIndex, draw > 0); } + bool doDrawItemStatus() const { return getEnableJob(_drawStatusJobIndex); } - void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } } - bool doDrawHitEffect() const { if (_drawHitEffectJobIndex >=0) { return _jobs[_drawHitEffectJobIndex].isEnabled(); } else { return false; } } + void setDrawHitEffect(bool draw) { enableJob(_drawHitEffectJobIndex, draw); } + bool doDrawHitEffect() const { return getEnableJob(_drawHitEffectJobIndex); } - int _occlusionJobIndex = -1; - void setOcclusionStatus(bool draw) { if (_occlusionJobIndex >= 0) { _jobs[_occlusionJobIndex].setEnabled(draw); } } - bool doOcclusionStatus() const { if (_occlusionJobIndex >= 0) { return _jobs[_occlusionJobIndex].isEnabled(); } else { return false; } } + void setOcclusionStatus(bool draw) { enableJob(_occlusionJobIndex, draw); } + bool doOcclusionStatus() const { return getEnableJob(_occlusionJobIndex); } - int _antialiasingJobIndex = -1; - void setAntialiasingStatus(bool draw) { if (_antialiasingJobIndex >= 0) { _jobs[_antialiasingJobIndex].setEnabled(draw); } } - bool doAntialiasingStatus() const { if (_antialiasingJobIndex >= 0) { return _jobs[_antialiasingJobIndex].isEnabled(); } else { return false; } } + void setAntialiasingStatus(bool draw) { enableJob(_antialiasingJobIndex, draw); } + bool doAntialiasingStatus() const { return getEnableJob(_antialiasingJobIndex); } - int _toneMappingJobIndex = -1; void setToneMappingExposure(float exposure); float getToneMappingExposure() const; @@ -156,11 +147,6 @@ public: int getToneMappingToneCurve() const; virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - - - gpu::Queries _timerQueries; - int _currentTimerQueryIndex = 0; }; - #endif // hifi_RenderDeferredTask_h diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 4d2a3728c6..b63cb88dcf 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -207,12 +207,13 @@ public: virtual ~Task() = default; // Queue a new job to the task; returns the job's index - template size_t addJob(std::string name, A&&... args) { + template const Varying addJob(std::string name, A&&... args) { _jobs.emplace_back(name, std::make_shared(std::forward(args)...)); - return _jobs.size() - 1; + return _jobs.back().getOutput(); } - const Job& getJob(size_t i) const { return _jobs.at(i); } + void enableJob(size_t jobIndex, bool enable = true) { _jobs.at(jobIndex).setEnabled(enable); } + bool getEnableJob(size_t jobIndex) const { return _jobs.at(jobIndex).isEnabled(); } virtual void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {} From 0776ae7e7285746eef65b683e36171c0a8e69b5a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 12:25:34 -0800 Subject: [PATCH 09/32] Add LightStage for rendering lights --- libraries/octree/src/ViewFrustum.h | 1 + .../src/DeferredLightingEffect.cpp | 6 +- .../render-utils/src/DeferredLightingEffect.h | 27 ++----- libraries/render-utils/src/LightStage.cpp | 79 +++++++++++++++++++ libraries/render-utils/src/LightStage.h | 62 +++++++++++++++ 5 files changed, 150 insertions(+), 25 deletions(-) create mode 100644 libraries/render-utils/src/LightStage.cpp create mode 100644 libraries/render-utils/src/LightStage.h diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 4a39ac5f44..1c033cc38c 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -162,6 +162,7 @@ private: // Used to project points glm::mat4 _ourModelViewProjectionMatrix; }; +using ViewFrustumPointer = std::shared_ptr; #endif // hifi_ViewFrustum_h diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index a5fce0b377..b5f866166e 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -69,6 +69,8 @@ void DeferredLightingEffect::init() { _allocatedLights.push_back(std::make_shared()); model::LightPointer lp = _allocatedLights[0]; + // Add the global light to the light stage (for later shadow rendering) + _lightStage.addLight(lp); lp->setDirection(-glm::vec3(1.0f, 1.0f, 1.0f)); lp->setColor(glm::vec3(1.0f)); @@ -541,10 +543,6 @@ void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const gl light->setAmbientIntensity(ambientIntensity); } -model::LightPointer DeferredLightingEffect::getGlobalLight() { - return _allocatedLights[_globalLights.front()]; -} - void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) { _skybox = skybox; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index e75961e11a..d11dee7d49 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -21,6 +21,8 @@ #include "model/Stage.h" #include "model/Geometry.h" +#include "LightStage.h" + class RenderArgs; struct LightLocations; using LightLocationsPtr = std::shared_ptr; @@ -50,9 +52,11 @@ public: void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; } void setGlobalSkybox(const model::SkyboxPointer& skybox); - model::LightPointer getGlobalLight(); + const LightStage& getLightStage() { return _lightStage; } private: + LightStage _lightStage; + DeferredLightingEffect() = default; model::MeshPointer _spotLightMesh; @@ -72,26 +76,7 @@ private: gpu::PipelinePointer _spotLight; LightLocationsPtr _spotLightLocations; - class PointLight { - public: - glm::vec4 position; - float radius; - glm::vec4 ambient; - glm::vec4 diffuse; - glm::vec4 specular; - float constantAttenuation; - float linearAttenuation; - float quadraticAttenuation; - }; - - class SpotLight : public PointLight { - public: - glm::vec3 direction; - float exponent; - float cutoff; - }; - - typedef std::vector< model::LightPointer > Lights; + using Lights = std::vector; Lights _allocatedLights; std::vector _globalLights; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp new file mode 100644 index 0000000000..0e79d7239c --- /dev/null +++ b/libraries/render-utils/src/LightStage.cpp @@ -0,0 +1,79 @@ +// +// LightStage.cpp +// render-utils/src +// +// Created by Zach Pomerantz on 1/14/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ViewFrustum.h" + +#include "LightStage.h" + +LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } { + framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); + map = framebuffer->getDepthStencilBuffer(); +} + +void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBack, float zFront) { + // Orient the keylight frustum + const auto& direction = glm::normalize(_light->getDirection()); + glm::quat orientation; + if (direction == IDENTITY_UP) { + orientation = glm::quat(glm::mat3(IDENTITY_UP, -IDENTITY_FRONT, IDENTITY_RIGHT)); + } else { + auto side = glm::normalize(glm::cross(direction, IDENTITY_UP)); + auto up = glm::normalize(glm::cross(side, direction)); + auto orientation = glm::quat(glm::mat3(direction, up, side)); + } + _frustum->setOrientation(orientation); + + // Position the keylight frustum + _frustum->setPosition(viewFrustum->getPosition() - 21.0f * direction); + + _view = _frustum->getView(); + const Transform viewInverse{ _view.getInverseMatrix() }; + + viewFrustum->calculate(); + //const auto nearCorners = viewFrustum->getCorners(0); + const auto nearClip = viewFrustum->getNearClip(); + const auto nearCorners = viewFrustum->getCorners(nearClip - 1); + const auto farCorners = viewFrustum->getCorners(nearClip + 20); + + vec3 min{ viewInverse.transform(nearCorners.bottomLeft) }; + vec3 max{ min }; + // Expand keylight frustum to fit view frustum + auto fitFrustum = [&min, &max, &viewInverse](const vec3& viewCorner) { + const auto corner = viewInverse.transform(viewCorner); + + min.x = glm::min(min.x, corner.x); + min.y = glm::min(min.y, corner.y); + min.z = glm::min(min.z, corner.z); + + max.x = glm::max(max.x, corner.x); + max.y = glm::max(max.y, corner.y); + max.z = glm::max(max.z, corner.z); + }; + fitFrustum(nearCorners.bottomLeft); + fitFrustum(nearCorners.bottomRight); + fitFrustum(nearCorners.topLeft); + fitFrustum(nearCorners.topRight); + fitFrustum(farCorners.bottomLeft); + fitFrustum(farCorners.bottomRight); + fitFrustum(farCorners.topLeft); + fitFrustum(farCorners.topRight); + + glm::mat4 ortho = glm::ortho(min.x, max.x, min.y, max.y, -max.z, -min.z); + _frustum->setProjection(ortho); + _projection = ortho; +} + +const LightStage::LightPointer& LightStage::addLight(model::LightPointer light) { + Shadow stageShadow{light}; + LightPointer stageLight = std::make_shared(std::move(stageShadow)); + lights.push_back(stageLight); + return stageLight; +} diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h new file mode 100644 index 0000000000..de6e138ace --- /dev/null +++ b/libraries/render-utils/src/LightStage.h @@ -0,0 +1,62 @@ +// +// LightStage.h +// render-utils/src +// +// Created by Zach Pomerantz on 1/14/2015. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_utils_LightStage_h +#define hifi_render_utils_LightStage_h + +#include "gpu/Framebuffer.h" + +#include "model/Light.h" + +class ViewFrustum; + +// Light stage to set up light-related rendering tasks +class LightStage { +public: + class Shadow { + public: + const int MAP_SIZE = 2048; + + Shadow(model::LightPointer light); + + void setKeylightFrustum(ViewFrustum* viewFrustum, float zBack, float zFront); + + const std::shared_ptr getFrustum() const { return _frustum; } + const glm::mat4& getProjection() const { return _projection; } + const Transform& getView() const { return _view; } + + gpu::FramebufferPointer framebuffer; + gpu::TexturePointer map; + protected: + model::LightPointer _light; + std::shared_ptr _frustum; + glm::mat4 _projection; + Transform _view; + }; + using ShadowPointer = std::shared_ptr; + + class Light { + public: + Light(Shadow&& shadow) : shadow{ shadow } {} + + model::LightPointer light; + Shadow shadow; + }; + using LightPointer = std::shared_ptr; + using Lights = std::vector; + + const LightPointer& addLight(model::LightPointer light); + // TODO: removeLight + + Lights lights; +}; + +#endif From b9b407fea03d084d2272f0da7b455f8dd4d81963 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 12:47:21 -0800 Subject: [PATCH 10/32] Remove static shadowMap --- libraries/render-utils/src/FramebufferCache.cpp | 8 -------- libraries/render-utils/src/FramebufferCache.h | 6 +++--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/FramebufferCache.cpp b/libraries/render-utils/src/FramebufferCache.cpp index 9f3d4ba0fe..4b2919e931 100644 --- a/libraries/render-utils/src/FramebufferCache.cpp +++ b/libraries/render-utils/src/FramebufferCache.cpp @@ -183,14 +183,6 @@ void FramebufferCache::releaseFramebuffer(const gpu::FramebufferPointer& framebu } } -gpu::FramebufferPointer FramebufferCache::getShadowFramebuffer() { - if (!_shadowFramebuffer) { - const int SHADOW_MAP_SIZE = 2048; - _shadowFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(SHADOW_MAP_SIZE)); - } - return _shadowFramebuffer; -} - gpu::FramebufferPointer FramebufferCache::getSelfieFramebuffer() { if (!_selfieFramebuffer) { createPrimaryFramebuffer(); diff --git a/libraries/render-utils/src/FramebufferCache.h b/libraries/render-utils/src/FramebufferCache.h index 7ac5e4af63..911c6f98dc 100644 --- a/libraries/render-utils/src/FramebufferCache.h +++ b/libraries/render-utils/src/FramebufferCache.h @@ -23,6 +23,9 @@ class FramebufferCache : public Dependency { SINGLETON_DEPENDENCY public: + // Shadow map size is static + static const int SHADOW_MAP_SIZE = 2048; + /// Sets the desired texture resolution for the framebuffer objects. void setFrameBufferSize(QSize frameBufferSize); const QSize& getFrameBufferSize() const { return _frameBufferSize; } @@ -45,9 +48,6 @@ public: gpu::TexturePointer getLightingTexture(); gpu::FramebufferPointer getLightingFramebuffer(); - /// Returns the framebuffer object used to render shadow maps; - gpu::FramebufferPointer getShadowFramebuffer(); - /// Returns the framebuffer object used to render selfie maps; gpu::FramebufferPointer getSelfieFramebuffer(); From 7744b89ba5be016d6f3cb22ebbd8ae84d175ae56 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 12:48:27 -0800 Subject: [PATCH 11/32] Prepare shadowMap pipeline to debug in color --- libraries/gpu/src/gpu/Framebuffer.cpp | 9 +++- .../render-utils/src/DebugDeferredBuffer.cpp | 49 ++++++++++++------- .../render-utils/src/DebugDeferredBuffer.h | 1 + libraries/render-utils/src/model_shadow.slf | 6 +-- .../render-utils/src/skin_model_shadow.slf | 20 ++++++++ 5 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 libraries/render-utils/src/skin_model_shadow.slf diff --git a/libraries/gpu/src/gpu/Framebuffer.cpp b/libraries/gpu/src/gpu/Framebuffer.cpp index ea650c6ad9..404ffa0a91 100755 --- a/libraries/gpu/src/gpu/Framebuffer.cpp +++ b/libraries/gpu/src/gpu/Framebuffer.cpp @@ -49,7 +49,9 @@ Framebuffer* Framebuffer::create( const Format& colorBufferFormat, const Format& Framebuffer* Framebuffer::createShadowmap(uint16 width) { auto framebuffer = Framebuffer::create(); - auto depthTexture = TexturePointer(Texture::create2D(Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH), width, width)); + + auto depthFormat = Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH); // Depth32 texel format + auto depthTexture = TexturePointer(Texture::create2D(depthFormat, width, width)); Sampler::Desc samplerDesc; samplerDesc._borderColor = glm::vec4(1.0f); @@ -59,8 +61,11 @@ Framebuffer* Framebuffer::createShadowmap(uint16 width) { samplerDesc._comparisonFunc = LESS_EQUAL; depthTexture->setSampler(Sampler(samplerDesc)); + framebuffer->setDepthStencilBuffer(depthTexture, depthFormat); - framebuffer->setDepthStencilBuffer(depthTexture, Element(gpu::SCALAR, gpu::FLOAT, gpu::DEPTH)); + // Use a render buffer to allow use of the DebugDeferredBuffer Job + gpu::TexturePointer colorbuffer{gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, width, width)}; + framebuffer->setRenderBuffer(0, colorbuffer); return framebuffer; } diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index ab2fa403f1..e76a843121 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -20,6 +20,7 @@ #include "GeometryCache.h" #include "FramebufferCache.h" +#include "DeferredLightingEffect.h" #include "debug_deferred_buffer_vert.h" #include "debug_deferred_buffer_frag.h" @@ -31,45 +32,53 @@ enum Slots { Normal, Specular, Depth, - Lighting + Lighting, + Shadow }; -static const std::string DEEFAULT_DIFFUSE_SHADER { +static const std::string DEFAULT_DIFFUSE_SHADER { "vec4 getFragmentColor() {" " return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);" " }" }; -static const std::string DEEFAULT_ALPHA_SHADER { +static const std::string DEFAULT_ALPHA_SHADER { "vec4 getFragmentColor() {" " return vec4(vec3(texture(diffuseMap, uv).a), 1.0);" " }" }; -static const std::string DEEFAULT_SPECULAR_SHADER { +static const std::string DEFAULT_SPECULAR_SHADER { "vec4 getFragmentColor() {" " return vec4(texture(specularMap, uv).xyz, 1.0);" " }" }; -static const std::string DEEFAULT_ROUGHNESS_SHADER { +static const std::string DEFAULT_ROUGHNESS_SHADER { "vec4 getFragmentColor() {" " return vec4(vec3(texture(specularMap, uv).a), 1.0);" " }" }; -static const std::string DEEFAULT_NORMAL_SHADER { +static const std::string DEFAULT_NORMAL_SHADER { "vec4 getFragmentColor() {" " return vec4(normalize(texture(normalMap, uv).xyz), 1.0);" " }" }; -static const std::string DEEFAULT_DEPTH_SHADER { +static const std::string DEFAULT_DEPTH_SHADER { "vec4 getFragmentColor() {" " return vec4(vec3(texture(depthMap, uv).x), 1.0);" " }" }; -static const std::string DEEFAULT_LIGHTING_SHADER { +static const std::string DEFAULT_LIGHTING_SHADER { "vec4 getFragmentColor() {" " return vec4(pow(texture(lightingMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);" " }" }; -static const std::string DEEFAULT_CUSTOM_SHADER { +static const std::string DEFAULT_SHADOW_SHADER { + "uniform sampler2D shadowMapColor;" + // The actual shadowMap is a sampler2DShadow, so we cannot normally sample it + "vec4 getFragmentColor() {" + " return vec4(texture(shadowMapColor, uv).xyz, 1.0);" + " }" +}; +static const std::string DEFAULT_CUSTOM_SHADER { "vec4 getFragmentColor() {" " return vec4(1.0, 0.0, 0.0, 1.0);" " }" @@ -98,21 +107,23 @@ DebugDeferredBuffer::DebugDeferredBuffer() { std::string DebugDeferredBuffer::getShaderSourceCode(Modes mode, std::string customFile) { switch (mode) { case DiffuseMode: - return DEEFAULT_DIFFUSE_SHADER; + return DEFAULT_DIFFUSE_SHADER; case AlphaMode: - return DEEFAULT_ALPHA_SHADER; + return DEFAULT_ALPHA_SHADER; case SpecularMode: - return DEEFAULT_SPECULAR_SHADER; + return DEFAULT_SPECULAR_SHADER; case RoughnessMode: - return DEEFAULT_ROUGHNESS_SHADER; + return DEFAULT_ROUGHNESS_SHADER; case NormalMode: - return DEEFAULT_NORMAL_SHADER; + return DEFAULT_NORMAL_SHADER; case DepthMode: - return DEEFAULT_DEPTH_SHADER; + return DEFAULT_DEPTH_SHADER; case LightingMode: - return DEEFAULT_LIGHTING_SHADER; + return DEFAULT_LIGHTING_SHADER; + case ShadowMode: + return DEFAULT_SHADOW_SHADER; case CustomMode: - return getFileContent(customFile, DEEFAULT_CUSTOM_SHADER); + return getFileContent(customFile, DEFAULT_CUSTOM_SHADER); } Q_UNREACHABLE(); return std::string(); @@ -158,6 +169,7 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Modes mode, std::st slotBindings.insert(gpu::Shader::Binding("specularMap", Specular)); slotBindings.insert(gpu::Shader::Binding("depthMap", Depth)); slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting)); + slotBindings.insert(gpu::Shader::Binding("shadowMapColor", Shadow)); gpu::Shader::makeProgram(*program, slotBindings); auto pipeline = gpu::Pipeline::create(program, std::make_shared()); @@ -193,7 +205,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { const auto geometryBuffer = DependencyManager::get(); const auto framebufferCache = DependencyManager::get(); - + const auto& lightStage = DependencyManager::get()->getLightStage(); glm::mat4 projMat; Transform viewMat; @@ -213,6 +225,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture()); batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture()); batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture()); + batch.setResourceTexture(Shadow, lightStage.lights[0]->shadow.framebuffer->getRenderBuffer(0)); const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); const glm::vec2 bottomLeft(renderContext->_deferredDebugSize.x, renderContext->_deferredDebugSize.y); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index c9ea24644a..eba48cd0c3 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -33,6 +33,7 @@ private: NormalMode, DepthMode, LightingMode, + ShadowMode, CustomMode // Needs to stay last }; diff --git a/libraries/render-utils/src/model_shadow.slf b/libraries/render-utils/src/model_shadow.slf index d691104bdd..fd35ec11d7 100755 --- a/libraries/render-utils/src/model_shadow.slf +++ b/libraries/render-utils/src/model_shadow.slf @@ -12,9 +12,9 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -out vec4 _fragColor; +layout(location = 0) out vec4 _fragColor; void main(void) { - // fixed color for now (we may eventually want to use texture alpha) - _fragColor = vec4(1.0, 1.0, 1.0, 0.0); + // stencil in solid color for debugging + _fragColor = vec4(0.0, 0.0, 1.0, 1.0); } diff --git a/libraries/render-utils/src/skin_model_shadow.slf b/libraries/render-utils/src/skin_model_shadow.slf new file mode 100644 index 0000000000..85d1b7424b --- /dev/null +++ b/libraries/render-utils/src/skin_model_shadow.slf @@ -0,0 +1,20 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_shadow.frag +// fragment shader +// +// Created by Andrzej Kapolka on 3/24/14. +// Copyright 2013 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 +// + +layout(location = 0) out vec4 _fragColor; + +void main(void) { + // stencil in solid color for debugging + _fragColor = vec4(1.0, 0.0, 0.0, 1.0); +} From c704a8d8c56f8455960e7cc96a0ac99cf25c24d1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 13:53:11 -0800 Subject: [PATCH 12/32] 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) {} From ec496f1907c0e103db10f28513518612421d18b4 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 14:06:07 -0800 Subject: [PATCH 13/32] Return copy of Light from LightStage --- libraries/render-utils/src/LightStage.cpp | 2 +- libraries/render-utils/src/LightStage.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 0e79d7239c..de0041ae00 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -71,7 +71,7 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBac _projection = ortho; } -const LightStage::LightPointer& LightStage::addLight(model::LightPointer light) { +const LightStage::LightPointer LightStage::addLight(model::LightPointer light) { Shadow stageShadow{light}; LightPointer stageLight = std::make_shared(std::move(stageShadow)); lights.push_back(stageLight); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index de6e138ace..28ffd2ca0f 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -53,7 +53,7 @@ public: using LightPointer = std::shared_ptr; using Lights = std::vector; - const LightPointer& addLight(model::LightPointer light); + const LightPointer addLight(model::LightPointer light); // TODO: removeLight Lights lights; From e2158e48a1995bb5913d42fa56e016ba5b90609b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 18:03:58 -0800 Subject: [PATCH 14/32] Declare Corners explicitly --- libraries/octree/src/ViewFrustum.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 1c033cc38c..da7822e1a6 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -61,7 +61,7 @@ public: float getFarClip() const { return _farClip; } float getFocalLength() const { return _focalLength; } - const class Corners{ + class Corners { public: Corners(glm::vec3&& topLeft, glm::vec3&& topRight, glm::vec3&& bottomLeft, glm::vec3&& bottomRight) : topLeft{ topLeft }, topRight{ topRight }, bottomLeft{ bottomLeft }, bottomRight{ bottomRight } {} @@ -70,7 +70,8 @@ public: glm::vec3 bottomLeft; glm::vec3 bottomRight; // Get the corners depth units from frustum position, along frustum orientation - } getCorners(const float& depth); + }; + const Corners getCorners(const float& depth); // getters for corners const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; } From 710fb5df53b79a69337522241c985e9c75bf3ced Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 10:18:29 -0800 Subject: [PATCH 15/32] Fix shadowed orientation in LightStage --- libraries/render-utils/src/LightStage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index de0041ae00..d2b76a279a 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -27,7 +27,7 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBac } else { auto side = glm::normalize(glm::cross(direction, IDENTITY_UP)); auto up = glm::normalize(glm::cross(side, direction)); - auto orientation = glm::quat(glm::mat3(direction, up, side)); + orientation = glm::quat(glm::mat3(direction, up, side)); } _frustum->setOrientation(orientation); From e914f024450c817adf9b2eb29b6b76dd40a4ccec Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 10:28:52 -0800 Subject: [PATCH 16/32] Use near/far in LightStage setFrustum --- libraries/render-utils/src/LightStage.cpp | 8 ++++---- libraries/render-utils/src/LightStage.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index d2b76a279a..0ff83ca93e 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -18,7 +18,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum map = framebuffer->getDepthStencilBuffer(); } -void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBack, float zFront) { +void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near, float far) { // Orient the keylight frustum const auto& direction = glm::normalize(_light->getDirection()); glm::quat orientation; @@ -32,7 +32,7 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBac _frustum->setOrientation(orientation); // Position the keylight frustum - _frustum->setPosition(viewFrustum->getPosition() - 21.0f * direction); + _frustum->setPosition(viewFrustum->getPosition() - (glm::abs(near) + glm::abs(far))*direction); _view = _frustum->getView(); const Transform viewInverse{ _view.getInverseMatrix() }; @@ -40,8 +40,8 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float zBac viewFrustum->calculate(); //const auto nearCorners = viewFrustum->getCorners(0); const auto nearClip = viewFrustum->getNearClip(); - const auto nearCorners = viewFrustum->getCorners(nearClip - 1); - const auto farCorners = viewFrustum->getCorners(nearClip + 20); + const auto nearCorners = viewFrustum->getCorners(near); + const auto farCorners = viewFrustum->getCorners(far); vec3 min{ viewInverse.transform(nearCorners.bottomLeft) }; vec3 max{ min }; diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 28ffd2ca0f..d95f82230d 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -27,7 +27,7 @@ public: Shadow(model::LightPointer light); - void setKeylightFrustum(ViewFrustum* viewFrustum, float zBack, float zFront); + void setKeylightFrustum(ViewFrustum* viewFrustum, float near, float far); const std::shared_ptr getFrustum() const { return _frustum; } const glm::mat4& getProjection() const { return _projection; } From b423bc38ba83d19437d3f8b82731bd690f5b6c36 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 10:46:01 -0800 Subject: [PATCH 17/32] Remove magic numbers --- libraries/render-utils/src/LightStage.cpp | 10 ++++++---- libraries/render-utils/src/RenderShadowTask.cpp | 8 +++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 0ff83ca93e..3b8eddd3b4 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -18,7 +18,9 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum map = framebuffer->getDepthStencilBuffer(); } -void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near, float far) { +void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) { + assert(nearDepth >= 0 && farDepth > 0); + // Orient the keylight frustum const auto& direction = glm::normalize(_light->getDirection()); glm::quat orientation; @@ -32,7 +34,7 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near _frustum->setOrientation(orientation); // Position the keylight frustum - _frustum->setPosition(viewFrustum->getPosition() - (glm::abs(near) + glm::abs(far))*direction); + _frustum->setPosition(viewFrustum->getPosition() - (nearDepth + farDepth)*direction); _view = _frustum->getView(); const Transform viewInverse{ _view.getInverseMatrix() }; @@ -40,8 +42,8 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near viewFrustum->calculate(); //const auto nearCorners = viewFrustum->getCorners(0); const auto nearClip = viewFrustum->getNearClip(); - const auto nearCorners = viewFrustum->getCorners(near); - const auto farCorners = viewFrustum->getCorners(far); + const auto nearCorners = viewFrustum->getCorners(nearDepth); + const auto farCorners = viewFrustum->getCorners(farDepth); vec3 min{ viewInverse.transform(nearCorners.bottomLeft) }; vec3 max{ min }; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 1447da624d..5735fe8318 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -102,7 +102,6 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const Render return; } - // TODO: If we're not using the global keylight, bail const auto& lightStage = DependencyManager::get()->getLightStage(); const auto globalLight = lightStage.lights[0]; @@ -113,8 +112,11 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const Render ViewFrustum* viewFrustum = args->_viewFrustum; - const auto nearClip = viewFrustum->getNearClip(); - globalLight->shadow.setKeylightFrustum(viewFrustum, nearClip - 1, nearClip + 20); + auto nearClip = viewFrustum->getNearClip(); + const int SHADOW_NEAR_DEPTH = -1; + const int SHADOW_FAR_DEPTH = 20; + globalLight->shadow.setKeylightFrustum(viewFrustum, + glm::max(0.0f, nearClip - SHADOW_NEAR_DEPTH), nearClip + SHADOW_FAR_DEPTH); // Set the keylight frustum args->_viewFrustum = globalLight->shadow.getFrustum().get(); From 986af50b7139e300b113846f380d08e219bc1f9d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 10:50:42 -0800 Subject: [PATCH 18/32] Remove unneccessary const --- libraries/octree/src/ViewFrustum.cpp | 4 ++-- libraries/render-utils/src/LightStage.cpp | 7 ++----- libraries/render-utils/src/RenderDeferredTask.cpp | 12 ++++++------ 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 0e7df1d9a4..85df5a0c93 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -740,8 +740,8 @@ const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) { glm::vec3 normal = glm::normalize(_direction); auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) { - const auto dir = glm::normalize(_cornersWorld[nearCorner] - _cornersWorld[farCorner]); - const auto factor = depth / glm::dot(dir, normal); + auto dir = glm::normalize(_cornersWorld[nearCorner] - _cornersWorld[farCorner]); + auto factor = depth / glm::dot(dir, normal); return _position + factor * dir; }; diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 3b8eddd3b4..708c136eab 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -40,10 +40,8 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near const Transform viewInverse{ _view.getInverseMatrix() }; viewFrustum->calculate(); - //const auto nearCorners = viewFrustum->getCorners(0); - const auto nearClip = viewFrustum->getNearClip(); - const auto nearCorners = viewFrustum->getCorners(nearDepth); - const auto farCorners = viewFrustum->getCorners(farDepth); + auto nearCorners = viewFrustum->getCorners(nearDepth); + auto farCorners = viewFrustum->getCorners(farDepth); vec3 min{ viewInverse.transform(nearCorners.bottomLeft) }; vec3 max{ min }; @@ -59,7 +57,6 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near max.y = glm::max(max.y, corner.y); max.z = glm::max(max.z, corner.z); }; - fitFrustum(nearCorners.bottomLeft); fitFrustum(nearCorners.bottomRight); fitFrustum(nearCorners.topLeft); fitFrustum(nearCorners.topRight); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d0d0338742..c458a23812 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -78,21 +78,21 @@ RenderDeferredTask::RenderDeferredTask() : Task() { initDeferredPipelines(*shapePlumber); // CPU: Fetch the renderOpaques - const auto fetchedOpaques = addJob("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { + auto fetchedOpaques = addJob("FetchOpaque", FetchItems([](const RenderContextPointer& context, int count) { context->getItemsConfig().opaque.numFeed = count; })); - const auto culledOpaques = addJob>("CullOpaque", fetchedOpaques); - const auto opaques = addJob("DepthSortOpaque", culledOpaques); + auto culledOpaques = addJob>("CullOpaque", fetchedOpaques); + auto opaques = addJob("DepthSortOpaque", culledOpaques); // CPU only, create the list of renderedTransparents items - const auto fetchedTransparents = addJob("FetchTransparent", FetchItems( + auto fetchedTransparents = addJob("FetchTransparent", FetchItems( ItemFilter::Builder::transparentShape().withoutLayered(), [](const RenderContextPointer& context, int count) { context->getItemsConfig().transparent.numFeed = count; } )); - const auto culledTransparents = addJob>("CullTransparent", fetchedTransparents); - const auto transparents = addJob("DepthSortTransparent", culledTransparents, DepthSortItems(false)); + auto culledTransparents = addJob>("CullTransparent", fetchedTransparents); + auto transparents = addJob("DepthSortTransparent", culledTransparents, DepthSortItems(false)); // GPU Jobs: Start preparing the deferred and lighting buffer addJob("PrepareDeferred"); From d6e5e2de815079a2f0d25617c77aa3b430cdf11a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 12:43:45 -0800 Subject: [PATCH 19/32] Fix orientation of shadow frustum --- libraries/render-utils/src/LightStage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 708c136eab..f6c2e14f2b 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -25,11 +25,11 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near const auto& direction = glm::normalize(_light->getDirection()); glm::quat orientation; if (direction == IDENTITY_UP) { - orientation = glm::quat(glm::mat3(IDENTITY_UP, -IDENTITY_FRONT, IDENTITY_RIGHT)); + orientation = glm::quat(glm::mat3(IDENTITY_RIGHT, IDENTITY_UP, IDENTITY_FRONT)); } else { auto side = glm::normalize(glm::cross(direction, IDENTITY_UP)); auto up = glm::normalize(glm::cross(side, direction)); - orientation = glm::quat(glm::mat3(direction, up, side)); + orientation = glm::quat_cast(glm::mat3(side, up, -direction)); } _frustum->setOrientation(orientation); From 5c1c1e3a3b5600b97178e06d69105ad66f367f6d Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 12:57:31 -0800 Subject: [PATCH 20/32] Change LightStage setFrustum signature to near/farDepth --- libraries/render-utils/src/LightStage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index d95f82230d..3d59de6164 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -27,7 +27,7 @@ public: Shadow(model::LightPointer light); - void setKeylightFrustum(ViewFrustum* viewFrustum, float near, float far); + void setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth); const std::shared_ptr getFrustum() const { return _frustum; } const glm::mat4& getProjection() const { return _projection; } From fad38c0bfbf8b4f4ce53a3305ed502963774ff88 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 15:16:05 -0800 Subject: [PATCH 21/32] Add uniform buffer to LightStage --- libraries/render-utils/src/LightStage.cpp | 19 ++++++++++++++++--- libraries/render-utils/src/LightStage.h | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index f6c2e14f2b..2217de6f28 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -16,6 +16,8 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } { framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); map = framebuffer->getDepthStencilBuffer(); + Schema schema{glm::mat4(), glm::mat4(), 0, MAP_SIZE}; + _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) { @@ -36,8 +38,8 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near // Position the keylight frustum _frustum->setPosition(viewFrustum->getPosition() - (nearDepth + farDepth)*direction); - _view = _frustum->getView(); - const Transform viewInverse{ _view.getInverseMatrix() }; + const Transform view{ _frustum->getView()}; + const Transform viewInverse{ view.getInverseMatrix() }; viewFrustum->calculate(); auto nearCorners = viewFrustum->getCorners(nearDepth); @@ -67,7 +69,18 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near glm::mat4 ortho = glm::ortho(min.x, max.x, min.y, max.y, -max.z, -min.z); _frustum->setProjection(ortho); - _projection = ortho; + + // Update the buffer + _schemaBuffer.edit().projection = ortho; + _schemaBuffer.edit().view = view.getMatrix(); +} + +const glm::mat4& LightStage::Shadow::getView() const { + return _frustum->getView(); +} + +const glm::mat4& LightStage::Shadow::getProjection() const { + return _frustum->getProjection(); } const LightStage::LightPointer LightStage::addLight(model::LightPointer light) { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 3d59de6164..10c8227ff3 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -23,6 +23,7 @@ class LightStage { public: class Shadow { public: + using UniformBufferView = gpu::BufferView; const int MAP_SIZE = 2048; Shadow(model::LightPointer light); @@ -30,16 +31,27 @@ public: void setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth); const std::shared_ptr getFrustum() const { return _frustum; } - const glm::mat4& getProjection() const { return _projection; } - const Transform& getView() const { return _view; } + + const glm::mat4& getView() const; + const glm::mat4& getProjection() const; + + const UniformBufferView& getBuffer() const { return _schemaBuffer; } gpu::FramebufferPointer framebuffer; gpu::TexturePointer map; protected: model::LightPointer _light; std::shared_ptr _frustum; - glm::mat4 _projection; - Transform _view; + + class Schema { + public: + glm::mat4 projection; + glm::mat4 view; + + glm::float32 bias; + glm::float32 scale; + }; + UniformBufferView _schemaBuffer = nullptr; }; using ShadowPointer = std::shared_ptr; From bc379e920b6a1045717a1d257c7fc5e6f5808e58 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 15:28:11 -0800 Subject: [PATCH 22/32] Update shadow programs --- .../src/DeferredLightingEffect.cpp | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b5f866166e..ac18348528 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -42,6 +42,7 @@ struct LightLocations { int texcoordMat; int coneParam; int deferredTransformBuffer; + int shadowTransformBuffer; }; static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); @@ -55,12 +56,9 @@ void DeferredLightingEffect::init() { _spotLightLocations = std::make_shared(); loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations); - loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations); - loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations); - loadLightProgram(deferred_light_limited_vert, point_light_frag, true, _pointLight, _pointLightLocations); loadLightProgram(deferred_light_spot_vert, spot_light_frag, true, _spotLight, _spotLightLocations); @@ -174,6 +172,12 @@ void DeferredLightingEffect::render(RenderArgs* args) { batch.setResourceTexture(2, framebufferCache->getDeferredSpecularTexture()); batch.setResourceTexture(3, framebufferCache->getPrimaryDepthTexture()); + assert(_lightStage.lights.size() > 0); + const auto& globalShadow = _lightStage.lights[0]->shadow; + + // Bind the shadow buffer + batch.setResourceTexture(4, globalShadow.map); + // THe main viewport is assumed to be the mono viewport (or the 2 stereo faces side by side within that viewport) auto monoViewport = args->_viewport; float sMin = args->_viewport.x / (float)framebufferSize.width(); @@ -293,6 +297,10 @@ void DeferredLightingEffect::render(RenderArgs* args) { program = _directionalAmbientSphereLight; locations = _directionalAmbientSphereLightLocations; } + + if (locations->shadowTransformBuffer >= 0) { + batch.setUniformBuffer(locations->shadowTransformBuffer, globalShadow.getBuffer()); + } batch.setPipeline(program); } @@ -480,17 +488,18 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), 3)); + slotBindings.insert(gpu::Shader::Binding(std::string("shadowMap"), 4)); slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), 5)); + static const int LIGHT_GPU_SLOT = 3; - slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); static const int ATMOSPHERE_GPU_SLOT = 4; - slotBindings.insert(gpu::Shader::Binding(std::string("atmosphereBufferUnit"), ATMOSPHERE_GPU_SLOT)); static const int DEFERRED_TRANSFORM_BUFFER_SLOT = 2; + slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), LIGHT_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("atmosphereBufferUnit"), ATMOSPHERE_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("deferredTransformBuffer"), DEFERRED_TRANSFORM_BUFFER_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); - locations->radius = program->getUniforms().findLocation("radius"); locations->ambientSphere = program->getUniforms().findLocation("ambientSphere.L00"); @@ -500,6 +509,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); locations->atmosphereBufferUnit = program->getBuffers().findLocation("atmosphereBufferUnit"); locations->deferredTransformBuffer = program->getBuffers().findLocation("deferredTransformBuffer"); + locations->shadowTransformBuffer = program->getBuffers().findLocation("shadowTransformBuffer"); auto state = std::make_shared(); state->setColorWriteMask(true, true, true, false); From 2b27e48bf9395a0dd3429bcf4534f4712c52f774 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Thu, 14 Jan 2016 15:46:59 -0800 Subject: [PATCH 23/32] Update shadow shaders --- libraries/render-utils/src/Shadow.slh | 101 +++++++----------- .../src/directional_ambient_light.slf | 10 +- .../render-utils/src/directional_light.slf | 10 +- .../src/directional_skybox_light.slf | 10 +- 4 files changed, 59 insertions(+), 72 deletions(-) diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 525abf60b7..850be95cde 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -14,35 +14,46 @@ // the shadow texture uniform sampler2DShadow shadowMap; -struct EyePlanes { - vec4 _S[1]; - vec4 _T[1]; - vec4 _R[1]; - vec4 _Q[1]; +struct ShadowTransform { + mat4 projection; + mat4 view; + + float bias; + float scale; }; -uniform eyePlanes { - EyePlanes _eyePlanes; +uniform shadowTransformBuffer { + ShadowTransform _shadowTransform; }; -EyePlanes getEyePlanes() { - return _eyePlanes; +mat4 getShadowView() { + return _shadowTransform.view; } +mat4 getShadowProjection() { + return _shadowTransform.projection; +} + +float getShadowScale() { + return 1.0; + //_shadowTransform.scale; +} + +// Compute the texture coordinates from world coordinates +vec4 evalShadowTexcoord(vec4 position) { + mat4 bias = mat4( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0); + return bias * getShadowProjection() * inverse(getShadowView()) * position; +} // Fetching it -float fetchShadow(vec3 texcoord) { - return texture(shadowMap, texcoord); +float fetchShadow(vec3 shadowTexcoord) { + return texture(shadowMap, shadowTexcoord); } -// the distances to the cascade sections -uniform vec3 shadowDistances; - -// the inverse of the size of the shadow map -uniform float shadowScale; - -uniform mat4 shadowMatrices[4]; - vec2 samples[8] = vec2[8]( vec2(-2.0, -2.0), vec2(2.0, -2.0), @@ -54,28 +65,10 @@ vec2 samples[8] = vec2[8]( vec2(0.0, -1.0) ); -vec4 evalShadowTexcoord(vec4 position) { - // compute the corresponding texture coordinates - EyePlanes eyePlanes = getEyePlanes(); - vec3 shadowTexcoord = vec3(dot(eyePlanes._S[0], position), dot(eyePlanes._T[0], position), dot(eyePlanes._R[0], position)); - return vec4(shadowTexcoord, 0.0); -} - -vec4 evalCascadedShadowTexcoord(vec4 position) { - EyePlanes eyePlanes = getEyePlanes(); - - // compute the index of the cascade to use and the corresponding texture coordinates - int shadowIndex = int(dot(step(vec3(position.z), shadowDistances), vec3(1.0, 1.0, 1.0))); - vec3 shadowTexcoord = vec3( - dot(eyePlanes._S[shadowIndex], position), - dot(eyePlanes._T[shadowIndex], position), - dot(eyePlanes._R[shadowIndex], position)); - - return vec4(shadowTexcoord, shadowIndex); -} - float evalShadowAttenuationPCF(vec4 shadowTexcoord) { float radiusScale = (shadowTexcoord.w + 1.0); + float shadowScale = getShadowScale(); + float shadowAttenuation = (0.25 * ( fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + @@ -98,36 +91,24 @@ float evalShadowAttenuationPCF(vec4 shadowTexcoord) { float evalShadowAttenuationBasic(vec4 shadowTexcoord) { float radiusScale = 0.5; + float shadowScale = getShadowScale(); + float shadowAttenuation = (0.25 * ( fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) )); + return shadowAttenuation; } -float evalShadowAttenuation(vec4 shadowTexcoord) { - return evalShadowAttenuationBasic(shadowTexcoord); +float evalShadowAttenuation(vec4 position) { + vec4 shadowTexcoord = evalShadowTexcoord(position); + + return fetchShadow(shadowTexcoord.xyz); + // return evalShadowAttenuationBasic(shadowTexcoord); + // return evalShadowAttenuationPCF(shadowTexcoord); } - - <@endif@> diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index a905dbdfd5..5b936f566f 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -12,9 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// Everything about deferred buffer +<@include Shadow.slh@> <@include DeferredBuffer.slh@> - <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -27,10 +26,13 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); + float shadowAttenuation = evalShadowAttenuation(worldPos); + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, - 1.0, + shadowAttenuation, frag.normal, frag.diffuse, frag.specularVal.xyz); @@ -38,7 +40,7 @@ void main(void) { } else { vec3 color = evalAmbientSphereGlobalColor( deferredTransform.viewInverse, - 1.0, + shadowAttenuation, frag.position.xyz, frag.normal, frag.diffuse, diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index eff40df255..f057f9cc35 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -12,9 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// Everything about deferred buffer +<@include Shadow.slh@> <@include DeferredBuffer.slh@> - <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -27,11 +26,14 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); + float shadowAttenuation = evalShadowAttenuation(worldPos); + // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, - 1.0, + shadowAttenuation, frag.normal, frag.diffuse, frag.specularVal.xyz); @@ -39,7 +41,7 @@ void main(void) { } else { vec3 color = evalAmbientGlobalColor( deferredTransform.viewInverse, - 1.0, + shadowAttenuation, frag.position.xyz, frag.normal, frag.diffuse, diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index ca3efef047..871cb32337 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -12,9 +12,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html //!> -// Everything about deferred buffer +<@include Shadow.slh@> <@include DeferredBuffer.slh@> - <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -27,11 +26,14 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); + float shadowAttenuation = evalShadowAttenuation(worldPos); + // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, - 1.0, + shadowAttenuation, frag.normal, frag.diffuse, frag.specularVal.xyz); @@ -39,7 +41,7 @@ void main(void) { } else { vec3 color = evalSkyboxGlobalColor( deferredTransform.viewInverse, - 1.0, + shadowAttenuation, frag.position.xyz, frag.normal, frag.diffuse, From b2c9cf7452af3b2fa19f35299e1a8e7e779b95dd Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 13:30:29 -0800 Subject: [PATCH 24/32] Fit shadowmap to viewFrustum better --- libraries/render-utils/src/LightStage.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 2217de6f28..72b2ec478f 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -21,7 +21,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum } void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) { - assert(nearDepth >= 0 && farDepth > 0); + assert(nearDepth < farDepth); // Orient the keylight frustum const auto& direction = glm::normalize(_light->getDirection()); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 5735fe8318..148b08d4ef 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -115,8 +115,7 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const Render auto nearClip = viewFrustum->getNearClip(); const int SHADOW_NEAR_DEPTH = -1; const int SHADOW_FAR_DEPTH = 20; - globalLight->shadow.setKeylightFrustum(viewFrustum, - glm::max(0.0f, nearClip - SHADOW_NEAR_DEPTH), nearClip + SHADOW_FAR_DEPTH); + globalLight->shadow.setKeylightFrustum(viewFrustum, nearClip + SHADOW_NEAR_DEPTH, nearClip + SHADOW_FAR_DEPTH); // Set the keylight frustum args->_viewFrustum = globalLight->shadow.getFrustum().get(); From 562c909ad8eb22fe4c765ed3240b36d61b52465e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 15:47:01 -0800 Subject: [PATCH 25/32] Update shadow shaders --- libraries/render-utils/src/LightStage.cpp | 4 +- libraries/render-utils/src/LightStage.h | 8 +-- .../render-utils/src/RenderShadowTask.cpp | 2 +- libraries/render-utils/src/Shadow.slh | 63 ++++++++----------- 4 files changed, 33 insertions(+), 44 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 72b2ec478f..0392f16594 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -16,7 +16,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } { framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); map = framebuffer->getDepthStencilBuffer(); - Schema schema{glm::mat4(), glm::mat4(), 0, MAP_SIZE}; + Schema schema; _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } @@ -72,7 +72,7 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near // Update the buffer _schemaBuffer.edit().projection = ortho; - _schemaBuffer.edit().view = view.getMatrix(); + _schemaBuffer.edit().viewInverse = viewInverse.getMatrix(); } const glm::mat4& LightStage::Shadow::getView() const { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 10c8227ff3..82d4784c90 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -24,7 +24,7 @@ public: class Shadow { public: using UniformBufferView = gpu::BufferView; - const int MAP_SIZE = 2048; + static const int MAP_SIZE = 2048; Shadow(model::LightPointer light); @@ -46,10 +46,10 @@ public: class Schema { public: glm::mat4 projection; - glm::mat4 view; + glm::mat4 viewInverse; - glm::float32 bias; - glm::float32 scale; + glm::float32 bias = 0.005f; + glm::float32 scale = 1 / MAP_SIZE; }; UniformBufferView _schemaBuffer = nullptr; }; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 148b08d4ef..c889fae110 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -113,7 +113,7 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const Render ViewFrustum* viewFrustum = args->_viewFrustum; auto nearClip = viewFrustum->getNearClip(); - const int SHADOW_NEAR_DEPTH = -1; + const int SHADOW_NEAR_DEPTH = -2; const int SHADOW_FAR_DEPTH = 20; globalLight->shadow.setKeylightFrustum(viewFrustum, nearClip + SHADOW_NEAR_DEPTH, nearClip + SHADOW_FAR_DEPTH); diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 850be95cde..c0ca4be0fe 100755 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -16,7 +16,7 @@ uniform sampler2DShadow shadowMap; struct ShadowTransform { mat4 projection; - mat4 view; + mat4 viewInverse; float bias; float scale; @@ -26,8 +26,8 @@ uniform shadowTransformBuffer { ShadowTransform _shadowTransform; }; -mat4 getShadowView() { - return _shadowTransform.view; +mat4 getShadowViewInverse() { + return _shadowTransform.viewInverse; } mat4 getShadowProjection() { @@ -35,21 +35,27 @@ mat4 getShadowProjection() { } float getShadowScale() { - return 1.0; - //_shadowTransform.scale; + return _shadowTransform.scale; +} + +float getShadowBias() { + return _shadowTransform.bias; } // Compute the texture coordinates from world coordinates vec4 evalShadowTexcoord(vec4 position) { - mat4 bias = mat4( + mat4 biasMatrix = mat4( 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, + 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0); - return bias * getShadowProjection() * inverse(getShadowView()) * position; + float bias = -getShadowBias(); + + vec4 shadowCoord = biasMatrix * getShadowProjection() * getShadowViewInverse() * position; + return vec4(shadowCoord.xy, shadowCoord.z + bias, 1.0); } -// Fetching it +// Sample the shadowMap with PCF (built-in) float fetchShadow(vec3 shadowTexcoord) { return texture(shadowMap, shadowTexcoord); } @@ -65,50 +71,33 @@ vec2 samples[8] = vec2[8]( vec2(0.0, -1.0) ); -float evalShadowAttenuationPCF(vec4 shadowTexcoord) { - float radiusScale = (shadowTexcoord.w + 1.0); +float evalShadowAttenuationSampling(vec4 shadowTexcoord) { float shadowScale = getShadowScale(); float shadowAttenuation = (0.25 * ( - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[0], 0.0)) + + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[1], 0.0)) + + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[2], 0.0)) + + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[3], 0.0)) )); + // Check for early bailing if ((shadowAttenuation > 0) && (shadowAttenuation < 1.0)) { - radiusScale *= 0.5; shadowAttenuation = 0.5 * shadowAttenuation + (0.125 * ( - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[4], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[5], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[6], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[7], 0.0)) + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[4], 0.0)) + + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[5], 0.0)) + + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[6], 0.0)) + + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(samples[7], 0.0)) )); } return shadowAttenuation; } -float evalShadowAttenuationBasic(vec4 shadowTexcoord) { - float radiusScale = 0.5; - float shadowScale = getShadowScale(); - - float shadowAttenuation = (0.25 * ( - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[0], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[1], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[2], 0.0)) + - fetchShadow(shadowTexcoord.xyz + radiusScale * shadowScale * vec3(samples[3], 0.0)) - )); - - return shadowAttenuation; -} - float evalShadowAttenuation(vec4 position) { vec4 shadowTexcoord = evalShadowTexcoord(position); - return fetchShadow(shadowTexcoord.xyz); - // return evalShadowAttenuationBasic(shadowTexcoord); - // return evalShadowAttenuationPCF(shadowTexcoord); + return evalShadowAttenuationSampling(shadowTexcoord); } <@endif@> From f3a5be9ec0e12cb53d096e6173e3d30052c6d404 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 16:12:37 -0800 Subject: [PATCH 26/32] Decrease shadowMap res to 1024 --- libraries/render-utils/src/LightStage.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 82d4784c90..f776d8d817 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -24,7 +24,7 @@ public: class Shadow { public: using UniformBufferView = gpu::BufferView; - static const int MAP_SIZE = 2048; + static const int MAP_SIZE = 1024; Shadow(model::LightPointer light); From 625eee2b9c2c6b836ca54bdcebc410380e955d87 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 16:15:44 -0800 Subject: [PATCH 27/32] Clean RenderShadowTask ctor --- libraries/render-utils/src/RenderShadowTask.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index c889fae110..f58d47683e 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -81,16 +81,16 @@ RenderShadowTask::RenderShadowTask() : Task() { } // CPU: Fetch shadow-casting opaques - addJob("FetchShadowMap"); + auto fetchedItems = addJob("FetchShadowMap"); // CPU: Cull against KeyLight frustum (nearby viewing camera) - addJob>("CullShadowMap", _jobs.back().getOutput()); + auto culledItems = addJob>("CullShadowMap", fetchedItems); // CPU: Sort front to back - addJob("DepthSortShadowMap", _jobs.back().getOutput()); + auto shadowItems = addJob("DepthSortShadowMap", culledItems); // GPU: Render to shadow map - addJob("RenderShadowMap", _jobs.back().getOutput(), shapePlumber); + addJob("RenderShadowMap", shadowItems, shapePlumber); } void RenderShadowTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { From 4bbf206f643cb4de608757d092f157e5cb28cd33 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 16:34:30 -0800 Subject: [PATCH 28/32] Clean up DrawTask --- libraries/render/src/render/DrawTask.cpp | 55 +++++++++++------------- libraries/render/src/render/DrawTask.h | 13 ++---- 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 88aeb55ffc..93cb42c2fd 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -18,7 +18,6 @@ #include #include - using namespace render; void render::cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { @@ -62,27 +61,6 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont renderDetails->_rendered += outItems.size(); } - -void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems) { - auto& scene = sceneContext->_scene; - - outItems.clear(); - - const auto& bucket = scene->getMasterBucket(); - const auto& items = bucket.find(_filter); - if (items != bucket.end()) { - outItems.reserve(items->second.size()); - for (auto& id : items->second) { - auto& item = scene->getItem(id); - outItems.emplace_back(ItemIDAndBounds(id, item.getBound())); - } - } - - if (_probeNumItems) { - _probeNumItems(renderContext, (int)outItems.size()); - } -} - struct ItemBound { float _centerDepth = 0.0f; float _nearDepth = 0.0f; @@ -146,13 +124,6 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende } } - -void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - outItems.clear(); - outItems.reserve(inItems.size()); - depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); -} - void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); @@ -190,6 +161,32 @@ void render::renderShapes(const SceneContextPointer& sceneContext, const RenderC } } +void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems) { + auto& scene = sceneContext->_scene; + + outItems.clear(); + + const auto& bucket = scene->getMasterBucket(); + const auto& items = bucket.find(_filter); + if (items != bucket.end()) { + outItems.reserve(items->second.size()); + for (auto& id : items->second) { + auto& item = scene->getItem(id); + outItems.emplace_back(ItemIDAndBounds(id, item.getBound())); + } + } + + if (_probeNumItems) { + _probeNumItems(renderContext, (int)outItems.size()); + } +} + +void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { + outItems.clear(); + outItems.reserve(inItems.size()); + depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); +} + void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { assert(renderContext->getArgs()); assert(renderContext->getArgs()->_viewFrustum); diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 3c2c0973b2..e043d5f69e 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -19,12 +19,11 @@ namespace render { -void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); -void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); +void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); +void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); void renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); - class FetchItems { public: typedef std::function ProbeNumItems; @@ -36,7 +35,6 @@ public: ProbeNumItems _probeNumItems; void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemIDsBounds& outItems); - using JobModel = Task::Job::ModelO; }; @@ -55,19 +53,16 @@ public: class DepthSortItems { public: - bool _frontToBack = true; - + bool _frontToBack; DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {} - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outITems); - + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); using JobModel = Task::Job::ModelIO; }; class DrawLight { public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext); - using JobModel = Task::Job::Model; }; From 331d32ef78ea3a8a5b7cf04d375b05d22002ea96 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 17:17:00 -0800 Subject: [PATCH 29/32] Add render Jobs for Shape sorting --- libraries/render/src/render/DrawTask.cpp | 34 ++++++++++++++++++++++-- libraries/render/src/render/DrawTask.h | 15 +++++++++++ libraries/render/src/render/Scene.h | 6 ++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 93cb42c2fd..a2af639c02 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -182,8 +182,6 @@ void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContex } void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems) { - outItems.clear(); - outItems.reserve(inItems.size()); depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); } @@ -215,3 +213,35 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext args->_batch = nullptr; }); } + +void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ShapesIDsBounds& outShapes) { + auto& scene = sceneContext->_scene; + outShapes.clear(); + + for (const auto& item : inItems) { + auto key = scene->getItem(item.id).getShapeKey(); + auto outItems = outShapes.find(key); + if (outItems == outShapes.end()) { + outItems = outShapes.insert(std::make_pair(key, ItemIDsBounds{})).first; + outItems->second.reserve(inItems.size()); + } + + outItems->second.push_back(item); + } + + for (auto& items : outShapes) { + items.second.shrink_to_fit(); + } +} + +void DepthSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes) { + for (auto& pipeline : inShapes) { + auto& inItems = pipeline.second; + auto outItems = outShapes.find(pipeline.first); + if (outItems == outShapes.end()) { + outItems = outShapes.insert(std::make_pair(pipeline.first, ItemIDsBounds{})).first; + } + + depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems->second); + } +} \ No newline at end of file diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index e043d5f69e..47ce5c8476 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -66,6 +66,21 @@ public: using JobModel = Task::Job::Model; }; +class PipelineSortShapes { +public: + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ShapesIDsBounds& outShapes); + using JobModel = Task::Job::ModelIO; +}; + +class DepthSortShapes { +public: + bool _frontToBack; + DepthSortShapes(bool frontToBack = true) : _frontToBack(frontToBack) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes); + using JobModel = Task::Job::ModelIO; +}; + } #endif // hifi_render_DrawTask_h diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 567e054a8a..e28225a899 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -432,7 +432,11 @@ public: AABox bounds; }; -typedef std::vector< ItemIDAndBounds > ItemIDsBounds; +// A list of items to be passed between rendering jobs +using ItemIDsBounds = std::vector; + +// A map of items by ShapeKey to optimize rendering pipeline assignments +using ShapesIDsBounds = std::unordered_map; // A map of ItemIDSets allowing to create bucket lists of items which are filtering correctly From 7fd20bb036ea05458c9597161399dbf9602a7d7b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 17:43:17 -0800 Subject: [PATCH 30/32] Set shadow pipelines manually to avoid duplication --- .../render-utils/src/RenderShadowTask.cpp | 31 ++++++++++++++++--- libraries/render-utils/src/RenderShadowTask.h | 4 +-- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index f58d47683e..7ccc4bacda 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -27,7 +27,7 @@ using namespace render; void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, - const render::ItemIDsBounds& inItems) { + const render::ShapesIDsBounds& inShapes) { assert(renderContext->getArgs()); assert(renderContext->getArgs()->_viewFrustum); @@ -52,7 +52,27 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const batch.setProjectionTransform(shadow.getProjection()); batch.setViewTransform(shadow.getView()); - renderShapes(sceneContext, renderContext, _shapePlumber, inItems); + auto shadowPipeline = _shapePlumber->pickPipeline(args, ShapeKey()); + auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, ShapeKey::Builder().withSkinned()); + args->_pipeline = shadowPipeline; + batch.setPipeline(shadowPipeline->pipeline); + + std::vector skinnedShapeKeys{}; + for (auto items : inShapes) { + if (items.first.isSkinned()) { + skinnedShapeKeys.push_back(items.first); + } else { + renderLights(sceneContext, renderContext, items.second); + } + } + + args->_pipeline = shadowSkinnedPipeline; + batch.setPipeline(shadowSkinnedPipeline->pipeline); + for (const auto& key : skinnedShapeKeys) { + renderLights(sceneContext, renderContext, inShapes.at(key)); + } + + args->_pipeline = nullptr; args->_batch = nullptr; }); } @@ -86,11 +106,14 @@ RenderShadowTask::RenderShadowTask() : Task() { // CPU: Cull against KeyLight frustum (nearby viewing camera) auto culledItems = addJob>("CullShadowMap", fetchedItems); + // CPU: Sort by pipeline + auto sortedShapes = addJob("PipelineSortShadowSort", culledItems); + // CPU: Sort front to back - auto shadowItems = addJob("DepthSortShadowMap", culledItems); + auto shadowShapes = addJob("DepthSortShadowMap", sortedShapes); // GPU: Render to shadow map - addJob("RenderShadowMap", shadowItems, shapePlumber); + addJob("RenderShadowMap", shadowShapes, shapePlumber); } void RenderShadowTask::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 333ed18c84..4853022359 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -24,9 +24,9 @@ class RenderShadowMap { public: RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, - const render::ItemIDsBounds& inItems); + const render::ShapesIDsBounds& inShapes); - using JobModel = render::Task::Job::ModelI; + using JobModel = render::Task::Job::ModelI; protected: render::ShapePlumberPointer _shapePlumber; }; From 7f3e102b5ed820206df47f99129cf0adcd4d4489 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Jan 2016 17:47:37 -0800 Subject: [PATCH 31/32] Rename renderLights to renderItems --- libraries/render-utils/src/RenderDeferredTask.cpp | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 4 ++-- libraries/render/src/render/DrawTask.cpp | 4 ++-- libraries/render/src/render/DrawTask.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c458a23812..dc3e5c652b 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -391,7 +391,7 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderLights(sceneContext, renderContext, inItems); + renderItems(sceneContext, renderContext, inItems); }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 7ccc4bacda..b6b9f15f60 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -62,14 +62,14 @@ void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const if (items.first.isSkinned()) { skinnedShapeKeys.push_back(items.first); } else { - renderLights(sceneContext, renderContext, items.second); + renderItems(sceneContext, renderContext, items.second); } } args->_pipeline = shadowSkinnedPipeline; batch.setPipeline(shadowSkinnedPipeline->pipeline); for (const auto& key : skinnedShapeKeys) { - renderLights(sceneContext, renderContext, inShapes.at(key)); + renderItems(sceneContext, renderContext, inShapes.at(key)); } args->_pipeline = nullptr; diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index a2af639c02..68e1841345 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -124,7 +124,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende } } -void render::renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { +void render::renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) { auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->getArgs(); @@ -209,7 +209,7 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - renderLights(sceneContext, renderContext, culledItems); + renderItems(sceneContext, renderContext, culledItems); args->_batch = nullptr; }); } diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 47ce5c8476..5ad1bbf8d4 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -21,7 +21,7 @@ namespace render { void cullItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemIDsBounds& inItems, ItemIDsBounds& outItems); -void renderLights(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); +void renderItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems); void renderShapes(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapePlumberPointer& shapeContext, const ItemIDsBounds& inItems, int maxDrawnItems = -1); class FetchItems { From 6434d983657cf47b7cf09dd7e32dfa9b02f6f15b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 18 Jan 2016 11:11:28 -0800 Subject: [PATCH 32/32] Separate directional shaders with(out) shadowmaps --- .../src/DeferredLightingEffect.cpp | 7 ++- .../src/directional_ambient_light.slf | 6 +-- .../src/directional_ambient_light_shadow.slf | 51 ++++++++++++++++++ .../render-utils/src/directional_light.slf | 6 +-- .../src/directional_light_shadow.slf | 52 ++++++++++++++++++ .../src/directional_skybox_light.slf | 10 ++-- .../src/directional_skybox_light_shadow.slf | 53 +++++++++++++++++++ 7 files changed, 170 insertions(+), 15 deletions(-) create mode 100644 libraries/render-utils/src/directional_ambient_light_shadow.slf create mode 100644 libraries/render-utils/src/directional_light_shadow.slf create mode 100644 libraries/render-utils/src/directional_skybox_light_shadow.slf diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index ac18348528..5af89e7afc 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -31,6 +31,10 @@ #include "directional_ambient_light_frag.h" #include "directional_skybox_light_frag.h" +#include "directional_light_shadow_frag.h" +#include "directional_ambient_light_shadow_frag.h" +#include "directional_skybox_light_shadow_frag.h" + #include "point_light_frag.h" #include "spot_light_frag.h" @@ -47,14 +51,15 @@ struct LightLocations { static void loadLightProgram(const char* vertSource, const char* fragSource, bool lightVolume, gpu::PipelinePointer& program, LightLocationsPtr& locations); - void DeferredLightingEffect::init() { _directionalLightLocations = std::make_shared(); _directionalAmbientSphereLightLocations = std::make_shared(); _directionalSkyboxLightLocations = std::make_shared(); + _pointLightLocations = std::make_shared(); _spotLightLocations = std::make_shared(); + // TODO: To use shadowmaps, replace directional_*_light_frag with directional_*_light_shadow_frag shaders. loadLightProgram(deferred_light_vert, directional_light_frag, false, _directionalLight, _directionalLightLocations); loadLightProgram(deferred_light_vert, directional_ambient_light_frag, false, _directionalAmbientSphereLight, _directionalAmbientSphereLightLocations); loadLightProgram(deferred_light_vert, directional_skybox_light_frag, false, _directionalSkyboxLight, _directionalSkyboxLightLocations); diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 5b936f566f..5c0a5c8331 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -6,13 +6,12 @@ // fragment shader // // Created by Andrzej Kapolka on 9/3/14. -// Copyright 2014 High Fidelity, Inc. +// 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 Shadow.slh@> <@include DeferredBuffer.slh@> <@include DeferredGlobalLight.slh@> @@ -26,8 +25,7 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); - float shadowAttenuation = evalShadowAttenuation(worldPos); + float shadowAttenuation = 1.0; if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { vec3 color = evalLightmappedColor( diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf new file mode 100644 index 0000000000..1cb425c881 --- /dev/null +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -0,0 +1,51 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// directional_light_shadow.frag +// fragment shader +// +// Created by Zach Pomerantz on 1/18/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 Shadow.slh@> +<@include DeferredBuffer.slh@> +<@include DeferredGlobalLight.slh@> + +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientSphereGlobalColor()$> + +in vec2 _texCoord0; +out vec4 _fragColor; + +void main(void) { + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + + vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); + float shadowAttenuation = evalShadowAttenuation(worldPos); + + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.normal, + frag.diffuse, + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); + } else { + vec3 color = evalAmbientSphereGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); + _fragColor = vec4(color, frag.normalVal.a); + } +} diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index f057f9cc35..9318f07f5a 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -6,13 +6,12 @@ // fragment shader // // Created by Andrzej Kapolka on 9/3/14. -// Copyright 2014 High Fidelity, Inc. +// 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 Shadow.slh@> <@include DeferredBuffer.slh@> <@include DeferredGlobalLight.slh@> @@ -26,8 +25,7 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); - float shadowAttenuation = evalShadowAttenuation(worldPos); + float shadowAttenuation = 1.0; // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { diff --git a/libraries/render-utils/src/directional_light_shadow.slf b/libraries/render-utils/src/directional_light_shadow.slf new file mode 100644 index 0000000000..6c7c450bc5 --- /dev/null +++ b/libraries/render-utils/src/directional_light_shadow.slf @@ -0,0 +1,52 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// directional_light_shadow.frag +// fragment shader +// +// Created by Zach Pomerantz on 1/18/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 Shadow.slh@> +<@include DeferredBuffer.slh@> +<@include DeferredGlobalLight.slh@> + +<$declareEvalLightmappedColor()$> +<$declareEvalAmbientGlobalColor()$> + +in vec2 _texCoord0; +out vec4 _fragColor; + +void main(void) { + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + + vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); + float shadowAttenuation = evalShadowAttenuation(worldPos); + + // Light mapped or not ? + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.normal, + frag.diffuse, + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); + } else { + vec3 color = evalAmbientGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); + _fragColor = vec4(color, frag.normalVal.a); + } +} diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 871cb32337..d149a78a14 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -3,16 +3,15 @@ // Generated on <$_SCRIBE_DATE$> // // directional_light.frag - +// -<@include Shadow.slh@> <@include DeferredBuffer.slh@> <@include DeferredGlobalLight.slh@> @@ -26,8 +25,7 @@ void main(void) { DeferredTransform deferredTransform = getDeferredTransform(); DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); - vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); - float shadowAttenuation = evalShadowAttenuation(worldPos); + float shadowAttenuation = 1.0; // Light mapped or not ? if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf new file mode 100644 index 0000000000..1b7ef76035 --- /dev/null +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -0,0 +1,53 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// directional_light_shadow.frag +// fragment shader +// +// Created by Zach Pomerantz on 1/18/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 Shadow.slh@> +<@include DeferredBuffer.slh@> +<@include DeferredGlobalLight.slh@> + +<$declareEvalLightmappedColor()$> +<$declareEvalSkyboxGlobalColor()$> + +in vec2 _texCoord0; +out vec4 _fragColor; + +void main(void) { + DeferredTransform deferredTransform = getDeferredTransform(); + DeferredFragment frag = unpackDeferredFragment(deferredTransform, _texCoord0); + + vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); + float shadowAttenuation = evalShadowAttenuation(worldPos); + + // Light mapped or not ? + if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + vec3 color = evalLightmappedColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.normal, + frag.diffuse, + frag.specularVal.xyz); + _fragColor = vec4(color, 1.0); + } else { + vec3 color = evalSkyboxGlobalColor( + deferredTransform.viewInverse, + shadowAttenuation, + frag.position.xyz, + frag.normal, + frag.diffuse, + frag.specular, + frag.gloss); + + _fragColor = vec4(color, frag.normalVal.a); + } +}