From f47a3e7d2ced239fdf16b259112b7ee23e228a74 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 15 Nov 2017 09:42:57 +0100 Subject: [PATCH] Moved draw frustum job to render DrawTask and made generic. A couple of fixes as requested by @samcake --- .../render-utils/src/RenderDeferredTask.cpp | 100 ++++-------------- .../render-utils/src/RenderDeferredTask.h | 36 ++----- libraries/render/src/render/DrawTask.cpp | 84 ++++++++++++++- libraries/render/src/render/DrawTask.h | 37 +++++++ libraries/render/src/render/SortTask.cpp | 6 +- libraries/shared/src/Transform.h | 6 +- scripts/developer/utilities/render/shadow.qml | 14 ++- 7 files changed, 165 insertions(+), 118 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 3dccef4a54..4261b14a9b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -44,8 +44,6 @@ #include "DrawHaze.h" #include "HighlightEffect.h" -#include - #include using namespace render; @@ -193,14 +191,18 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("HighlightRangeTimer", outlineRangeTimer); - { // DEbug the bounds of the rendered items, still look at the zbuffer + { // Debug the bounds of the rendered items, still look at the zbuffer task.addJob("DrawMetaBounds", metas); task.addJob("DrawOpaqueBounds", opaques); task.addJob("DrawTransparentBounds", transparents); task.addJob("DrawLightBounds", lights); task.addJob("DrawZones", zones); - task.addJob("DrawFrustums"); + const auto frustums = task.addJob("ExtractFrustums"); + const auto viewFrustum = frustums.getN(ExtractFrustums::VIEW_FRUSTUM); + const auto shadowFrustum = frustums.getN(ExtractFrustums::SHADOW_FRUSTUM); + task.addJob("DrawViewFrustum", viewFrustum, glm::vec3(1.0f, 1.0f, 0.0f)); + task.addJob("DrawShadowFrustum", shadowFrustum, glm::vec3(0.0f, 0.0f, 1.0f)); // Render.getConfig("RenderMainView.DrawSelectionBounds").enabled = true task.addJob("DrawSelectionBounds", selectedItems); @@ -533,88 +535,32 @@ void Blit::run(const RenderContextPointer& renderContext, const gpu::Framebuffer }); } -void DrawFrustums::configure(const Config& configuration) { - _updateFrustums = !configuration.isFrozen; -} - -void DrawFrustums::run(const render::RenderContextPointer& renderContext) { +void ExtractFrustums::run(const render::RenderContextPointer& renderContext, Output& output) { assert(renderContext->args); assert(renderContext->args->_context); RenderArgs* args = renderContext->args; - static uint8_t indexData[] = { 0, 1, 2, 3, 0, 4, 5, 6, 7, 4, 5, 1, 2, 6, 7, 3 }; - if (!_frustumMeshIndices._buffer) { - auto indices = std::make_shared(sizeof(indexData), indexData); - _frustumMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX)); - _viewFrustumMeshVertices = gpu::BufferView(std::make_shared(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ); - _viewFrustumMeshStream.addBuffer(_viewFrustumMeshVertices._buffer, _viewFrustumMeshVertices._offset, _viewFrustumMeshVertices._stride); - _shadowFrustumMeshVertices = gpu::BufferView(std::make_shared(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ); - _shadowFrustumMeshStream.addBuffer(_shadowFrustumMeshVertices._buffer, _shadowFrustumMeshVertices._offset, _shadowFrustumMeshVertices._stride); + // Return view frustum + auto& viewFrustum = output[VIEW_FRUSTUM].edit(); + if (!viewFrustum) { + viewFrustum = std::make_shared(args->getViewFrustum()); + } else { + *viewFrustum = args->getViewFrustum(); } - if (_updateFrustums) { - updateFrustum(args->getViewFrustum(), _viewFrustumMeshVertices); + // Return shadow frustum + auto& shadowFrustum = output[SHADOW_FRUSTUM].edit(); + auto lightStage = args->_scene->getStage(LightStage::getName()); + if (lightStage) { + auto globalShadow = lightStage->getCurrentKeyShadow(); - auto lightStage = renderContext->_scene->getStage(); - assert(lightStage); - - const auto globalShadow = lightStage->getCurrentKeyShadow(); if (globalShadow) { - updateFrustum(*globalShadow->getFrustum(), _shadowFrustumMeshVertices); + shadowFrustum = globalShadow->getFrustum(); + } else { + shadowFrustum.reset(); } + } else { + shadowFrustum.reset(); } - - if (!_pipeline) { - auto vs = gpu::StandardShaderLib::getDrawTransformVertexPositionVS(); - auto ps = gpu::StandardShaderLib::getDrawColorPS(); - gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("color", 0)); - gpu::Shader::makeProgram(*program, slotBindings); - - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(true, false)); - _pipeline = gpu::Pipeline::create(program, state); - } - - // Render the frustums in wireframe - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - batch.setPipeline(_pipeline); - batch.setIndexBuffer(_frustumMeshIndices); - - batch._glUniform4f(0, 1.0f, 1.0f, 0.0f, 1.0f); - batch.setInputStream(0, _viewFrustumMeshStream); - batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U); - - batch._glUniform4f(0, 1.0f, 0.0f, 0.0f, 1.0f); - batch.setInputStream(0, _shadowFrustumMeshStream); - batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U); - - args->_batch = nullptr; - }); -} - -void DrawFrustums::updateFrustum(const ViewFrustum& frustum, gpu::BufferView& vertexBuffer) { - auto& vertices = vertexBuffer.edit >(); - vertices[0] = frustum.getNearTopLeft(); - vertices[1] = frustum.getNearTopRight(); - vertices[2] = frustum.getNearBottomRight(); - vertices[3] = frustum.getNearBottomLeft(); - vertices[4] = frustum.getFarTopLeft(); - vertices[5] = frustum.getFarTopRight(); - vertices[6] = frustum.getFarBottomRight(); - vertices[7] = frustum.getFarBottomLeft(); } diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index bf457d7fcb..40ae503fb7 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -170,38 +170,20 @@ public: void run(const render::RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer); }; -class DrawFrustumsConfig : public render::Job::Config { - Q_OBJECT - Q_PROPERTY(bool isFrozen MEMBER isFrozen NOTIFY dirty) +class ExtractFrustums { public: - DrawFrustumsConfig(bool enabled = false) : JobConfig(enabled) {} + enum Frustum { + VIEW_FRUSTUM, + SHADOW_FRUSTUM, - bool isFrozen{ false }; -signals: - void dirty(); + FRUSTUM_COUNT + }; -}; + using Output = render::VaryingArray; + using JobModel = render::Job::ModelO; -class DrawFrustums { -public: - using Config = DrawFrustumsConfig; - using JobModel = render::Job::Model; - - void configure(const Config& configuration); - void run(const render::RenderContextPointer& renderContext); - -private: - - bool _updateFrustums{ true }; - gpu::PipelinePointer _pipeline; - gpu::BufferView _frustumMeshIndices; - gpu::BufferView _viewFrustumMeshVertices; - gpu::BufferView _shadowFrustumMeshVertices; - gpu::BufferStream _viewFrustumMeshStream; - gpu::BufferStream _shadowFrustumMeshStream; - - static void updateFrustum(const ViewFrustum& frustum, gpu::BufferView& vertexBuffer); + void run(const render::RenderContextPointer& renderContext, Output& output); }; class RenderDeferredTaskConfig : public render::Task::Config { diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 710507bd79..0f4137e38d 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -20,7 +20,7 @@ #include #include #include - +#include #include #include @@ -215,3 +215,85 @@ void DrawBounds::run(const RenderContextPointer& renderContext, }); } +gpu::PipelinePointer DrawFrustum::_pipeline; +gpu::BufferView DrawFrustum::_frustumMeshIndices; + +DrawFrustum::DrawFrustum(const glm::vec3& color) : + _color{ color } { + _frustumMeshVertices = gpu::BufferView(std::make_shared(sizeof(glm::vec3) * 8, nullptr), gpu::Element::VEC3F_XYZ); + _frustumMeshStream.addBuffer(_frustumMeshVertices._buffer, _frustumMeshVertices._offset, _frustumMeshVertices._stride); +} + +void DrawFrustum::configure(const Config& configuration) { + _updateFrustum = !configuration.isFrozen; +} + +void DrawFrustum::run(const render::RenderContextPointer& renderContext, const Input& input) { + assert(renderContext->args); + assert(renderContext->args->_context); + + RenderArgs* args = renderContext->args; + if (input) { + const auto& frustum = *input; + + static uint8_t indexData[] = { 0, 1, 2, 3, 0, 4, 5, 6, 7, 4, 5, 1, 2, 6, 7, 3 }; + + if (!_frustumMeshIndices._buffer) { + auto indices = std::make_shared(sizeof(indexData), indexData); + _frustumMeshIndices = gpu::BufferView(indices, gpu::Element(gpu::SCALAR, gpu::UINT8, gpu::INDEX)); + } + + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawTransformVertexPositionVS(); + auto ps = gpu::StandardShaderLib::getDrawColorPS(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("color", 0)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(true, false)); + _pipeline = gpu::Pipeline::create(program, state); + } + + if (_updateFrustum) { + updateFrustum(frustum); + } + + // Render the frustums in wireframe + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setPipeline(_pipeline); + batch.setIndexBuffer(_frustumMeshIndices); + + batch._glUniform4f(0, _color.x, _color.y, _color.z, 1.0f); + batch.setInputStream(0, _frustumMeshStream); + batch.drawIndexed(gpu::LINE_STRIP, sizeof(indexData) / sizeof(indexData[0]), 0U); + + args->_batch = nullptr; + }); + } +} + +void DrawFrustum::updateFrustum(const ViewFrustum& frustum) { + auto& vertices = _frustumMeshVertices.edit >(); + vertices[0] = frustum.getNearTopLeft(); + vertices[1] = frustum.getNearTopRight(); + vertices[2] = frustum.getNearBottomRight(); + vertices[3] = frustum.getNearBottomLeft(); + vertices[4] = frustum.getFarTopLeft(); + vertices[5] = frustum.getFarTopRight(); + vertices[6] = frustum.getFarBottomRight(); + vertices[7] = frustum.getFarBottomLeft(); +} diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 896ccef842..5d98c37c21 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -70,6 +70,43 @@ private: int _colorLocation { -1 }; }; +class DrawFrustumConfig : public render::JobConfig { + Q_OBJECT + Q_PROPERTY(bool isFrozen MEMBER isFrozen NOTIFY dirty) +public: + + DrawFrustumConfig(bool enabled = false) : JobConfig(enabled) {} + + bool isFrozen{ false }; +signals: + void dirty(); + +}; + +class DrawFrustum { +public: + using Config = DrawFrustumConfig; + using Input = ViewFrustumPointer; + using JobModel = render::Job::ModelI; + + DrawFrustum(const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f)); + + void configure(const Config& configuration); + void run(const render::RenderContextPointer& renderContext, const Input& input); + +private: + + static gpu::PipelinePointer _pipeline; + static gpu::BufferView _frustumMeshIndices; + + bool _updateFrustum{ true }; + gpu::BufferView _frustumMeshVertices; + gpu::BufferStream _frustumMeshStream; + glm::vec3 _color; + + void updateFrustum(const ViewFrustum& frustum); +}; + } #endif // hifi_render_DrawTask_h diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index a97d795736..63673a71a5 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -151,11 +151,7 @@ void DepthSortShapesAndComputeBounds::run(const RenderContextPointer& renderCont AABox bounds; depthSortItems(renderContext, _frontToBack, inItems, outItems->second, &bounds); - if (!outBounds.isNull()) { - outBounds += bounds; - } else { - outBounds = bounds; - } + outBounds += bounds; } } diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 71d8b6c915..7a39314f4d 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -149,7 +149,7 @@ public: Vec4 transform(const Vec4& pos) const; Vec3 transform(const Vec3& pos) const; - Vec3 transformDirection(const Vec3& pos) const; + Vec3 transformDirection(const Vec3& dir) const; bool containsNaN() const { return isNaN(_rotation) || isNaN(glm::dot(_scale, _translation)); } @@ -542,10 +542,10 @@ inline Transform::Vec3 Transform::transform(const Vec3& pos) const { return Vec3(result.x / result.w, result.y / result.w, result.z / result.w); } -inline Transform::Vec3 Transform::transformDirection(const Vec3& pos) const { +inline Transform::Vec3 Transform::transformDirection(const Vec3& dir) const { Mat4 m; getMatrix(m); - Vec4 result = m * Vec4(pos, 0.0f); + Vec4 result = m * Vec4(dir, 0.0f); return Vec3(result.x, result.y, result.z); } diff --git a/scripts/developer/utilities/render/shadow.qml b/scripts/developer/utilities/render/shadow.qml index 1b4e647c77..8548ba4119 100644 --- a/scripts/developer/utilities/render/shadow.qml +++ b/scripts/developer/utilities/render/shadow.qml @@ -14,20 +14,24 @@ import QtQuick.Controls 1.4 Column { id: root spacing: 8 - property var config: Render.getConfig("RenderMainView.DrawFrustums"); + property var viewConfig: Render.getConfig("RenderMainView.DrawViewFrustum"); + property var shadowConfig: Render.getConfig("RenderMainView.DrawShadowFrustum"); Component.onCompleted: { - config.enabled = true; + viewConfig.enabled = true; + shadowConfig.enabled = true; } Component.onDestruction: { - config.enabled = false; + viewConfig.enabled = false; + shadowConfig.enabled = false; } CheckBox { text: "Freeze Frustums" checked: false onCheckedChanged: { - config.isFrozen = checked; + viewConfig.isFrozen = checked; + shadowConfig.isFrozen = checked; } } Row { @@ -39,7 +43,7 @@ Column { } Label { text: "Shadow" - color: "red" + color: "blue" font.italic: true } }