From e406e3d47e129acf1c35c294b3ce4b20406a518b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 14:46:51 -0500 Subject: [PATCH 01/13] Make Forward DrawBounds enableable --- .../render-utils/src/RenderForwardTask.h | 26 ++++++++++++------- libraries/render/src/render/Task.h | 3 ++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 000210c761..9d93c7d5c3 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -33,11 +33,25 @@ private: gpu::FramebufferPointer _framebuffer; }; -class DrawBounds { +class DrawBackground { public: using Inputs = render::ItemBounds; - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& background); +}; + +class DrawBounds { +public: + class Config : public render::JobConfig { + public: + Config() : JobConfig(false) {} + }; + + using Inputs = render::ItemBounds; + using JobModel = render::Job::ModelI; + + void configure(const Config& configuration) {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& items); private: @@ -47,12 +61,4 @@ private: int _scaleLocation { -1 }; }; -class DrawBackground { -public: - using Inputs = render::ItemBounds; - using JobModel = render::Job::ModelI; - - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& background); -}; - #endif // hifi_RenderForwardTask_h diff --git a/libraries/render/src/render/Task.h b/libraries/render/src/render/Task.h index 49273d79a5..4e3aa79c8d 100644 --- a/libraries/render/src/render/Task.h +++ b/libraries/render/src/render/Task.h @@ -371,6 +371,7 @@ protected: class JobConfig : public QObject { Q_OBJECT Q_PROPERTY(double cpuRunTime READ getCPURunTime NOTIFY newStats()) //ms + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) double _msCPURunTime{ 0.0 }; public: @@ -380,7 +381,7 @@ public: JobConfig(bool enabled) : alwaysEnabled{ false }, enabled{ enabled } {} bool isEnabled() { return alwaysEnabled || enabled; } - void setEnabled(bool enable) { enabled = enable; } + void setEnabled(bool enable) { enabled = alwaysEnabled || enable; } bool alwaysEnabled{ true }; bool enabled{ true }; From 01cf48807c7af9f37e834908ad0a2bc9392bb1f2 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 14:47:48 -0500 Subject: [PATCH 02/13] change Render.RenderForwardTask to Render.Forward --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b58bedb363..8372e7f609 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1824,7 +1824,7 @@ void Application::initializeGL() { assert(items.canCast()); static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD"; if (QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD)) { - _renderEngine->addJob("RenderForwardTask", items.get()); + _renderEngine->addJob("Forward", items.get()); } else { _renderEngine->addJob("RenderDeferredTask", items.get()); } From 2e274b026da979abcb5c6d64865b028260f5e4e2 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 14:54:44 -0500 Subject: [PATCH 03/13] fix line lengths --- libraries/render-utils/src/RenderForwardTask.cpp | 11 +++++++---- libraries/render-utils/src/RenderForwardTask.h | 12 ++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index e78d457666..be47abeeab 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -49,7 +49,8 @@ RenderForwardTask::RenderForwardTask(RenderFetchCullSortTask::Output items) { addJob("Blit", framebuffer); } -void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer) { +void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + gpu::FramebufferPointer& framebuffer) { auto framebufferCache = DependencyManager::get(); auto framebufferSize = framebufferCache->getFrameBufferSize(); glm::uvec2 frameSize(framebufferSize.width(), framebufferSize.height()); @@ -112,7 +113,8 @@ const gpu::PipelinePointer DrawBounds::getPipeline() { return _boundsPipeline; } -void DrawBounds::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& items) { +void DrawBounds::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + const Inputs& items) { RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -143,7 +145,8 @@ void DrawBounds::run(const SceneContextPointer& sceneContext, const RenderContex }); } -void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& items) { +void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + const Inputs& background) { RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { @@ -161,7 +164,7 @@ void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderCo batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - renderItems(sceneContext, renderContext, items); + renderItems(sceneContext, renderContext, background); }); args->_batch = nullptr; } diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 9d93c7d5c3..21fe43af64 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -25,9 +25,11 @@ public: class PrepareFramebuffer { public: - using JobModel = render::Job::ModelO; + using Inputs = gpu::FramebufferPointer; + using JobModel = render::Job::ModelO; - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, gpu::FramebufferPointer& framebuffer); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, + gpu::FramebufferPointer& framebuffer); private: gpu::FramebufferPointer _framebuffer; @@ -38,7 +40,8 @@ public: using Inputs = render::ItemBounds; using JobModel = render::Job::ModelI; - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& background); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, + const Inputs& background); }; class DrawBounds { @@ -52,7 +55,8 @@ public: using JobModel = render::Job::ModelI; void configure(const Config& configuration) {} - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const Inputs& items); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, + const Inputs& items); private: const gpu::PipelinePointer getPipeline(); From f8e8065e93a39170824eae2f30d85952f1e9a892 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 14:56:47 -0500 Subject: [PATCH 04/13] mv DrawBounds to end of ForwardTask --- .../render-utils/src/RenderForwardTask.cpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index be47abeeab..51dc2dcd47 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -90,6 +90,30 @@ void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const Rend framebuffer = _framebuffer; } +void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + const Inputs& background) { + RenderArgs* args = renderContext->args; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + batch.enableSkybox(true); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + // Setup projection + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + + renderItems(sceneContext, renderContext, background); + }); + args->_batch = nullptr; +} + const gpu::PipelinePointer DrawBounds::getPipeline() { if (!_boundsPipeline) { auto vs = gpu::Shader::createVertex(std::string(drawItemBounds_vert)); @@ -144,27 +168,3 @@ void DrawBounds::run(const SceneContextPointer& sceneContext, const RenderContex } }); } - -void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, - const Inputs& background) { - RenderArgs* args = renderContext->args; - - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - args->_batch = &batch; - - batch.enableSkybox(true); - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - - // Setup projection - glm::mat4 projMat; - Transform viewMat; - args->getViewFrustum().evalProjectionMatrix(projMat); - args->getViewFrustum().evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - - renderItems(sceneContext, renderContext, background); - }); - args->_batch = nullptr; -} From 89917b41fd08d9936c133a8e71cdfd596249f0d0 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 15:18:22 -0500 Subject: [PATCH 05/13] add Forward Draw for opaques (no pipelines) --- .../render-utils/src/RenderForwardTask.cpp | 26 +++++++++++++++++++ .../render-utils/src/RenderForwardTask.h | 13 ++++++++++ 2 files changed, 39 insertions(+) diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 51dc2dcd47..ebc9ac5b94 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -30,6 +30,9 @@ using namespace render; RenderForwardTask::RenderForwardTask(RenderFetchCullSortTask::Output items) { + // Prepare the ShapePipelines + ShapePlumberPointer shapePlumber = std::make_shared(); + // Extract opaques / transparents / lights / overlays const auto opaques = items[0]; const auto transparents = items[1]; @@ -40,6 +43,7 @@ RenderForwardTask::RenderForwardTask(RenderFetchCullSortTask::Output items) { const auto framebuffer = addJob("PrepareFramebuffer"); + addJob("DrawOpaques", opaques, shapePlumber); addJob("DrawBackground", background); // bounds do not draw on stencil buffer, so they must come last @@ -90,6 +94,28 @@ void PrepareFramebuffer::run(const SceneContextPointer& sceneContext, const Rend framebuffer = _framebuffer; } +void Draw::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, + const Inputs& items) { + RenderArgs* args = renderContext->args; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + // Setup projection + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); + + // Render items + renderStateSortShapes(sceneContext, renderContext, _shapePlumber, items, -1); + }); + args->_batch = nullptr; +} + void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& background) { RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 21fe43af64..5f9386ceba 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -35,6 +35,19 @@ private: gpu::FramebufferPointer _framebuffer; }; +class Draw { +public: + using Inputs = render::ItemBounds; + using JobModel = render::Job::ModelI; + + Draw(const render::ShapePlumberPointer& shapePlumber) : _shapePlumber(shapePlumber) {} + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, + const Inputs& items); + +private: + render::ShapePlumberPointer _shapePlumber; +}; + class DrawBackground { public: using Inputs = render::ItemBounds; From 62eeb0c8072e1f64580a81523bca251f66c43a9b Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 18:33:14 -0500 Subject: [PATCH 06/13] clean RenderPipelines with forward decls --- .../render-utils/src/RenderPipelines.cpp | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 1f4b7ca445..506a6b87f0 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -48,40 +48,11 @@ using namespace render; -gpu::BufferView getDefaultMaterialBuffer() { - model::Material::Schema schema; - schema._albedo = vec3(1.0f); - schema._opacity = 1.0f; - schema._metallic = 0.1f; - schema._roughness = 0.9f; - return gpu::BufferView(std::make_shared(sizeof(model::Material::Schema), (const gpu::Byte*) &schema)); -} +void initOverlay3DPipelines(ShapePlumber& plumber); +void initDeferredPipelines(render::ShapePlumber& plumber); -void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { - // Set a default albedo map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, - DependencyManager::get()->getWhiteTexture()); - // Set a default normal map - batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, - DependencyManager::get()->getNormalFittingTexture()); - - // Set a default material - if (pipeline.locations->materialBufferUnit >= 0) { - static const gpu::BufferView OPAQUE_SCHEMA_BUFFER = getDefaultMaterialBuffer(); - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, OPAQUE_SCHEMA_BUFFER); - } -} - -void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { - batchSetter(pipeline, batch); - // Set the light - if (pipeline.locations->lightBufferUnit >= 0) { - DependencyManager::get()->setupKeyLightBatch(batch, - pipeline.locations->lightBufferUnit, - pipeline.locations->lightAmbientBufferUnit, - pipeline.locations->lightAmbientMapUnit); - } -} +void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); +void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); @@ -283,3 +254,42 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { skinModelShadowVertex, modelShadowPixel); } + +void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { + // Set a default albedo map + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, + DependencyManager::get()->getWhiteTexture()); + // Set a default normal map + batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, + DependencyManager::get()->getNormalFittingTexture()); + + // Set a default material + if (pipeline.locations->materialBufferUnit >= 0) { + // Create a default schema + static bool isMaterialSet = false; + static model::Material material; + if (!isMaterialSet) { + material.setAlbedo(vec3(1.0f)); + material.setOpacity(1.0f); + material.setMetallic(0.1f); + material.setRoughness(0.9f); + isMaterialSet = true; + } + + // Set a default schema + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, material.getSchemaBuffer()); + } +} + +void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { + // Set the batch + batchSetter(pipeline, batch); + + // Set the light + if (pipeline.locations->lightBufferUnit >= 0) { + DependencyManager::get()->setupKeyLightBatch(batch, + pipeline.locations->lightBufferUnit, + pipeline.locations->lightAmbientBufferUnit, + pipeline.locations->lightAmbientMapUnit); + } +} From a414ba4cb50286261e0afb6c0b4d4e99985685e8 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 18:54:34 -0500 Subject: [PATCH 07/13] take addPipeline lambda out of initDeferredPipelines --- .../render-utils/src/RenderPipelines.cpp | 95 ++++++++++--------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 506a6b87f0..d28e1aa0a2 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -10,6 +10,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include @@ -47,9 +49,13 @@ using namespace render; +using namespace std::placeholders; void initOverlay3DPipelines(ShapePlumber& plumber); -void initDeferredPipelines(render::ShapePlumber& plumber); +void initDeferredPipelines(ShapePlumber& plumber); + +void addPlumberPipeline(ShapePlumber& plumber, + const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel); void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); @@ -101,50 +107,6 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { } void initDeferredPipelines(render::ShapePlumber& plumber) { - using Key = render::ShapeKey; - using ShaderPointer = gpu::ShaderPointer; - - auto addPipeline = [&plumber](const Key& key, const ShaderPointer& vertexShader, const ShaderPointer& pixelShader) { - // These keyvalues' pipelines will be added by this lamdba in addition to the key passed - assert(!key.isWireFrame()); - assert(!key.isDepthBiased()); - assert(key.isCullFace()); - - ShaderPointer program = gpu::Shader::createProgram(vertexShader, pixelShader); - - for (int i = 0; i < 8; i++) { - bool isCulled = (i & 1); - bool isBiased = (i & 2); - bool isWireframed = (i & 4); - - ShapeKey::Builder builder(key); - auto state = std::make_shared(); - - // Depth test depends on transparency - state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); - state->setBlendFunction(key.isTranslucent(), - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - if (!isCulled) { - builder.withoutCullFace(); - } - state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE); - if (isWireframed) { - builder.withWireframe(); - state->setFillMode(gpu::State::FILL_LINE); - } - if (isBiased) { - builder.withDepthBias(); - state->setDepthBias(1.0f); - state->setDepthBiasSlopeScale(1.0f); - } - - plumber.addPipeline(builder.build(), program, state, - key.isTranslucent() ? &lightBatchSetter : &batchSetter); - } - }; - // Vertex shaders auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); @@ -169,6 +131,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { auto modelLightmapSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag)); auto modelLightmapNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag)); + using Key = render::ShapeKey; + auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); // TODO: Refactor this to use a filter // Opaques addPipeline( @@ -252,7 +216,48 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withSkinned().withDepthOnly(), skinModelShadowVertex, modelShadowPixel); +} +void addPlumberPipeline(ShapePlumber& plumber, + const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) { + // These key-values' pipelines are added by this functor in addition to the key passed + assert(!key.isWireFrame()); + assert(!key.isDepthBiased()); + assert(key.isCullFace()); + + gpu::ShaderPointer program = gpu::Shader::createProgram(vertex, pixel); + + for (int i = 0; i < 8; i++) { + bool isCulled = (i & 1); + bool isBiased = (i & 2); + bool isWireframed = (i & 4); + + auto state = std::make_shared(); + + // Depth test depends on transparency + state->setDepthTest(true, !key.isTranslucent(), gpu::LESS_EQUAL); + state->setBlendFunction(key.isTranslucent(), + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + ShapeKey::Builder builder(key); + if (!isCulled) { + builder.withoutCullFace(); + } + state->setCullMode(isCulled ? gpu::State::CULL_BACK : gpu::State::CULL_NONE); + if (isWireframed) { + builder.withWireframe(); + state->setFillMode(gpu::State::FILL_LINE); + } + if (isBiased) { + builder.withDepthBias(); + state->setDepthBias(1.0f); + state->setDepthBiasSlopeScale(1.0f); + } + + plumber.addPipeline(builder.build(), program, state, + key.isTranslucent() ? &lightBatchSetter : &batchSetter); + } } void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { From f7cb2ec85baaf41cffa3ff4e050680e5059d443c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Tue, 3 Jan 2017 20:41:57 -0500 Subject: [PATCH 08/13] add plain forward model shaders --- .../render-utils/src/RenderForwardTask.cpp | 42 ++++++++++++++++++- .../render-utils/src/RenderForwardTask.h | 11 +++++ .../render-utils/src/RenderPipelines.cpp | 16 +++++++ libraries/render-utils/src/nop.slf | 16 +++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 libraries/render-utils/src/nop.slf diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index ebc9ac5b94..c7a3433c96 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -26,12 +26,15 @@ #include #include +#include "nop_frag.h" using namespace render; +extern void initForwardPipelines(ShapePlumber& plumber); RenderForwardTask::RenderForwardTask(RenderFetchCullSortTask::Output items) { // Prepare the ShapePipelines ShapePlumberPointer shapePlumber = std::make_shared(); + initForwardPipelines(*shapePlumber); // Extract opaques / transparents / lights / overlays const auto opaques = items[0]; @@ -44,9 +47,10 @@ RenderForwardTask::RenderForwardTask(RenderFetchCullSortTask::Output items) { const auto framebuffer = addJob("PrepareFramebuffer"); addJob("DrawOpaques", opaques, shapePlumber); + addJob("Stencil"); addJob("DrawBackground", background); - // bounds do not draw on stencil buffer, so they must come last + // Bounds do not draw on stencil buffer, so they must come last addJob("DrawBounds", opaques); // Blit! @@ -116,6 +120,42 @@ void Draw::run(const SceneContextPointer& sceneContext, const RenderContextPoint args->_batch = nullptr; } +const gpu::PipelinePointer Stencil::getPipeline() { + if (!_stencilPipeline) { + auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(nop_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram(*program); + + auto state = std::make_shared(); + state->setDepthTest(true, false, gpu::LESS_EQUAL); + const gpu::int8 STENCIL_OPAQUE = 1; + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(STENCIL_OPAQUE, 0xFF, gpu::ALWAYS, + gpu::State::STENCIL_OP_REPLACE, + gpu::State::STENCIL_OP_REPLACE, + gpu::State::STENCIL_OP_KEEP)); + + _stencilPipeline = gpu::Pipeline::create(program, state); + } + return _stencilPipeline; +} + +void Stencil::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { + RenderArgs* args = renderContext->args; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; + + batch.enableStereo(false); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); + + batch.setPipeline(getPipeline()); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + args->_batch = nullptr; +} + void DrawBackground::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const Inputs& background) { RenderArgs* args = renderContext->args; diff --git a/libraries/render-utils/src/RenderForwardTask.h b/libraries/render-utils/src/RenderForwardTask.h index 5f9386ceba..a957f7493e 100755 --- a/libraries/render-utils/src/RenderForwardTask.h +++ b/libraries/render-utils/src/RenderForwardTask.h @@ -48,6 +48,17 @@ private: render::ShapePlumberPointer _shapePlumber; }; +class Stencil { +public: + using JobModel = render::Job::Model; + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + +private: + const gpu::PipelinePointer getPipeline(); + gpu::PipelinePointer _stencilPipeline; +}; + class DrawBackground { public: using Inputs = render::ItemBounds; diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d28e1aa0a2..2f04d778e2 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -53,6 +53,7 @@ using namespace std::placeholders; void initOverlay3DPipelines(ShapePlumber& plumber); void initDeferredPipelines(ShapePlumber& plumber); +void initForwardPipelines(ShapePlumber& plumber); void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel); @@ -218,6 +219,21 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { skinModelShadowVertex, modelShadowPixel); } +void initForwardPipelines(render::ShapePlumber& plumber) { + // Vertex shaders + auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); + + // Pixel shaders + auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); + + using Key = render::ShapeKey; + auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); + // Opaques + addPipeline( + Key::Builder(), + modelVertex, modelPixel); + } + void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) { // These key-values' pipelines are added by this functor in addition to the key passed diff --git a/libraries/render-utils/src/nop.slf b/libraries/render-utils/src/nop.slf new file mode 100644 index 0000000000..f87db4e138 --- /dev/null +++ b/libraries/render-utils/src/nop.slf @@ -0,0 +1,16 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// nop.frag +// fragment shader +// +// Created by Zach Pomerantz on 1/3/2017. +// Copyright 2017 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 +// + +void main(void) { +} From 6b984d38d3415a8f86dcd8261c72381fa0a1b701 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 4 Jan 2017 15:37:17 -0500 Subject: [PATCH 09/13] add opaque forward model shaders --- .../render-utils/src/RenderPipelines.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 2f04d778e2..d65db9b818 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -222,9 +222,14 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { void initForwardPipelines(render::ShapePlumber& plumber) { // Vertex shaders auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); + auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); // Pixel shaders auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); + auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag)); + auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); + auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); + auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); using Key = render::ShapeKey; auto addPipeline = std::bind(&addPlumberPipeline, std::ref(plumber), _1, _2, _3); @@ -232,7 +237,20 @@ void initForwardPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder(), modelVertex, modelPixel); - } + addPipeline( + Key::Builder().withUnlit(), + modelVertex, modelUnlitPixel); + addPipeline( + Key::Builder().withTangents(), + modelNormalMapVertex, modelNormalMapPixel); + addPipeline( + Key::Builder().withSpecular(), + modelVertex, modelSpecularMapPixel); + addPipeline( + Key::Builder().withTangents().withSpecular(), + modelNormalMapVertex, modelNormalSpecularMapPixel); + +} void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel) { From 1b948c7a05393016f19e58892b846a102e559182 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 4 Jan 2017 15:49:29 -0500 Subject: [PATCH 10/13] add skinned forward model shaders --- libraries/render-utils/src/RenderPipelines.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index d65db9b818..b0d676ef78 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -223,6 +223,8 @@ void initForwardPipelines(render::ShapePlumber& plumber) { // Vertex shaders auto modelVertex = gpu::Shader::createVertex(std::string(model_vert)); auto modelNormalMapVertex = gpu::Shader::createVertex(std::string(model_normal_map_vert)); + auto skinModelVertex = gpu::Shader::createVertex(std::string(skin_model_vert)); + auto skinModelNormalMapVertex = gpu::Shader::createVertex(std::string(skin_model_normal_map_vert)); // Pixel shaders auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); @@ -249,7 +251,19 @@ void initForwardPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withTangents().withSpecular(), modelNormalMapVertex, modelNormalSpecularMapPixel); - + // Skinned + addPipeline( + Key::Builder().withSkinned(), + skinModelVertex, modelPixel); + addPipeline( + Key::Builder().withSkinned().withTangents(), + skinModelNormalMapVertex, modelNormalMapPixel); + addPipeline( + Key::Builder().withSkinned().withSpecular(), + skinModelVertex, modelSpecularMapPixel); + addPipeline( + Key::Builder().withSkinned().withTangents().withSpecular(), + skinModelNormalMapVertex, modelNormalSpecularMapPixel); } void addPlumberPipeline(ShapePlumber& plumber, From 2383592678c8db6e4a2da782f70ea3d9232e9da0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 12 Jan 2017 13:51:45 -0800 Subject: [PATCH 11/13] Improve FBX parsing performance by bulk loading of arrays --- libraries/fbx/src/FBXReader_Node.cpp | 69 ++++++++++++++++++---------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXReader_Node.cpp index 85850a748e..435c4d830b 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXReader_Node.cpp @@ -43,31 +43,54 @@ template QVariant readBinaryArray(QDataStream& in, int& position) { position += sizeof(quint32) * 3; QVector values; - const unsigned int DEFLATE_ENCODING = 1; - if (encoding == DEFLATE_ENCODING) { - // preface encoded data with uncompressed length - QByteArray compressed(sizeof(quint32) + compressedLength, 0); - *((quint32*)compressed.data()) = qToBigEndian(arrayLength * sizeof(T)); - in.readRawData(compressed.data() + sizeof(quint32), compressedLength); - position += compressedLength; - QByteArray uncompressed = qUncompress(compressed); - if (uncompressed.isEmpty()) { // answers empty byte array if corrupt - throw QString("corrupt fbx file"); - } - QDataStream uncompressedIn(uncompressed); - uncompressedIn.setByteOrder(QDataStream::LittleEndian); - uncompressedIn.setVersion(QDataStream::Qt_4_5); // for single/double precision switch - for (quint32 i = 0; i < arrayLength; i++) { - T value; - uncompressedIn >> value; - values.append(value); + if ((int)QSysInfo::ByteOrder == (int)in.byteOrder()) { + values.resize(arrayLength); + const unsigned int DEFLATE_ENCODING = 1; + QByteArray arrayData; + if (encoding == DEFLATE_ENCODING) { + // preface encoded data with uncompressed length + QByteArray compressed(sizeof(quint32) + compressedLength, 0); + *((quint32*)compressed.data()) = qToBigEndian(arrayLength * sizeof(T)); + in.readRawData(compressed.data() + sizeof(quint32), compressedLength); + position += compressedLength; + arrayData = qUncompress(compressed); + if (arrayData.isEmpty() || arrayData.size() != (sizeof(T) * arrayLength)) { // answers empty byte array if corrupt + throw QString("corrupt fbx file"); + } + } else { + arrayData.resize(sizeof(T) * arrayLength); + position += sizeof(T) * arrayLength; + in.readRawData(arrayData.data(), arrayData.size()); } + memcpy(&values[0], arrayData.constData(), arrayData.size()); } else { - for (quint32 i = 0; i < arrayLength; i++) { - T value; - in >> value; - position += streamSize(); - values.append(value); + values.reserve(arrayLength); + const unsigned int DEFLATE_ENCODING = 1; + if (encoding == DEFLATE_ENCODING) { + // preface encoded data with uncompressed length + QByteArray compressed(sizeof(quint32) + compressedLength, 0); + *((quint32*)compressed.data()) = qToBigEndian(arrayLength * sizeof(T)); + in.readRawData(compressed.data() + sizeof(quint32), compressedLength); + position += compressedLength; + QByteArray uncompressed = qUncompress(compressed); + if (uncompressed.isEmpty()) { // answers empty byte array if corrupt + throw QString("corrupt fbx file"); + } + QDataStream uncompressedIn(uncompressed); + uncompressedIn.setByteOrder(QDataStream::LittleEndian); + uncompressedIn.setVersion(QDataStream::Qt_4_5); // for single/double precision switch + for (quint32 i = 0; i < arrayLength; i++) { + T value; + uncompressedIn >> value; + values.append(value); + } + } else { + for (quint32 i = 0; i < arrayLength; i++) { + T value; + in >> value; + position += streamSize(); + values.append(value); + } } } return QVariant::fromValue(values); From 29b160d685ee5b5b38656d8d89ea4cf1ec5f38d9 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 12 Jan 2017 16:16:02 -0800 Subject: [PATCH 12/13] Reduce temp qvariant creation and qvariant conversion --- libraries/fbx/src/FBXReader.cpp | 172 ++++++++++++++++++--------- libraries/fbx/src/FBXReader_Mesh.cpp | 14 ++- 2 files changed, 123 insertions(+), 63 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 0171b95a3d..5272969e6b 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -555,8 +555,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } else if (subobject.name == "Properties70") { foreach (const FBXNode& subsubobject, subobject.children) { + static const QVariant APPLICATION_NAME = QVariant(QByteArray("Original|ApplicationName")); if (subsubobject.name == "P" && subsubobject.properties.size() >= 5 && - subsubobject.properties.at(0) == "Original|ApplicationName") { + subsubobject.properties.at(0) == APPLICATION_NAME) { geometry.applicationName = subsubobject.properties.at(4).toString(); } } @@ -571,10 +572,12 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS int index = 4; foreach (const FBXNode& subobject, object.children) { if (subobject.name == propertyName) { - QString subpropName = subobject.properties.at(0).toString(); - if (subpropName == "UnitScaleFactor") { + static const QVariant UNIT_SCALE_FACTOR = QByteArray("UnitScaleFactor"); + static const QVariant AMBIENT_COLOR = QByteArray("AmbientColor"); + const auto& subpropName = subobject.properties.at(0); + if (subpropName == UNIT_SCALE_FACTOR) { unitScaleFactor = subobject.properties.at(index).toFloat(); - } else if (subpropName == "AmbientColor") { + } else if (subpropName == AMBIENT_COLOR) { ambientColor = getVec3(subobject.properties, index); } } @@ -672,66 +675,87 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS index = 4; } if (properties) { - foreach (const FBXNode& property, subobject.children) { + static const QVariant GEOMETRIC_TRANSLATION = QByteArray("GeometricTranslation"); + static const QVariant GEOMETRIC_ROTATION = QByteArray("GeometricRotation"); + static const QVariant GEOMETRIC_SCALING = QByteArray("GeometricScaling"); + static const QVariant LCL_TRANSLATION = QByteArray("Lcl Translation"); + static const QVariant LCL_ROTATION = QByteArray("Lcl Rotation"); + static const QVariant LCL_SCALING = QByteArray("Lcl Scaling"); + static const QVariant ROTATION_MAX = QByteArray("RotationMax"); + static const QVariant ROTATION_MAX_X = QByteArray("RotationMaxX"); + static const QVariant ROTATION_MAX_Y = QByteArray("RotationMaxY"); + static const QVariant ROTATION_MAX_Z = QByteArray("RotationMaxZ"); + static const QVariant ROTATION_MIN = QByteArray("RotationMin"); + static const QVariant ROTATION_MIN_X = QByteArray("RotationMinX"); + static const QVariant ROTATION_MIN_Y = QByteArray("RotationMinY"); + static const QVariant ROTATION_MIN_Z = QByteArray("RotationMinZ"); + static const QVariant ROTATION_OFFSET = QByteArray("RotationOffset"); + static const QVariant ROTATION_PIVOT = QByteArray("RotationPivot"); + static const QVariant SCALING_OFFSET = QByteArray("ScalingOffset"); + static const QVariant SCALING_PIVOT = QByteArray("ScalingPivot"); + static const QVariant PRE_ROTATION = QByteArray("PreRotation"); + static const QVariant POST_ROTATION = QByteArray("PostRotation"); + foreach(const FBXNode& property, subobject.children) { + const auto& childProperty = property.properties.at(0); if (property.name == propertyName) { - if (property.properties.at(0) == "Lcl Translation") { + if (childProperty == LCL_TRANSLATION) { translation = getVec3(property.properties, index); - } else if (property.properties.at(0) == "RotationOffset") { + } else if (childProperty == ROTATION_OFFSET) { rotationOffset = getVec3(property.properties, index); - } else if (property.properties.at(0) == "RotationPivot") { + } else if (childProperty == ROTATION_PIVOT) { rotationPivot = getVec3(property.properties, index); - } else if (property.properties.at(0) == "PreRotation") { + } else if (childProperty == PRE_ROTATION) { preRotation = getVec3(property.properties, index); - } else if (property.properties.at(0) == "Lcl Rotation") { + } else if (childProperty == LCL_ROTATION) { rotation = getVec3(property.properties, index); - } else if (property.properties.at(0) == "PostRotation") { + } else if (childProperty == POST_ROTATION) { postRotation = getVec3(property.properties, index); - } else if (property.properties.at(0) == "ScalingPivot") { + } else if (childProperty == SCALING_PIVOT) { scalePivot = getVec3(property.properties, index); - } else if (property.properties.at(0) == "Lcl Scaling") { + } else if (childProperty == LCL_SCALING) { scale = getVec3(property.properties, index); - } else if (property.properties.at(0) == "ScalingOffset") { + } else if (childProperty == SCALING_OFFSET) { scaleOffset = getVec3(property.properties, index); // NOTE: these rotation limits are stored in degrees (NOT radians) - } else if (property.properties.at(0) == "RotationMin") { + } else if (childProperty == ROTATION_MIN) { rotationMin = getVec3(property.properties, index); - } else if (property.properties.at(0) == "RotationMax") { + } else if (childProperty == ROTATION_MAX) { rotationMax = getVec3(property.properties, index); - } else if (property.properties.at(0) == "RotationMinX") { + } else if (childProperty == ROTATION_MIN_X) { rotationMinX = property.properties.at(index).toBool(); - } else if (property.properties.at(0) == "RotationMinY") { + } else if (childProperty == ROTATION_MIN_Y) { rotationMinY = property.properties.at(index).toBool(); - } else if (property.properties.at(0) == "RotationMinZ") { + } else if (childProperty == ROTATION_MIN_Z) { rotationMinZ = property.properties.at(index).toBool(); - } else if (property.properties.at(0) == "RotationMaxX") { + } else if (childProperty == ROTATION_MAX_X) { rotationMaxX = property.properties.at(index).toBool(); - } else if (property.properties.at(0) == "RotationMaxY") { + } else if (childProperty == ROTATION_MAX_Y) { rotationMaxY = property.properties.at(index).toBool(); - } else if (property.properties.at(0) == "RotationMaxZ") { + } else if (childProperty == ROTATION_MAX_Z) { rotationMaxZ = property.properties.at(index).toBool(); - } else if (property.properties.at(0) == "GeometricTranslation") { + } else if (childProperty == GEOMETRIC_TRANSLATION) { geometricTranslation = getVec3(property.properties, index); hasGeometricOffset = true; - } else if (property.properties.at(0) == "GeometricRotation") { + } else if (childProperty == GEOMETRIC_ROTATION) { geometricRotation = getVec3(property.properties, index); hasGeometricOffset = true; - } else if (property.properties.at(0) == "GeometricScaling") { + } else if (childProperty == GEOMETRIC_SCALING) { geometricScaling = getVec3(property.properties, index); hasGeometricOffset = true; } @@ -842,20 +866,26 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS propertyName = "P"; index = 4; foreach (const FBXNode& property, subobject.children) { + static const QVariant UV_SET = QByteArray("UVSet"); + static const QVariant CURRENT_TEXTURE_BLEND_MODE = QByteArray("CurrentTextureBlendMode"); + static const QVariant USE_MATERIAL = QByteArray("UseMaterial"); + static const QVariant TRANSLATION = QByteArray("Translation"); + static const QVariant ROTATION = QByteArray("Rotation"); + static const QVariant SCALING = QByteArray("Scaling"); if (property.name == propertyName) { QString v = property.properties.at(0).toString(); - if (property.properties.at(0) == "UVSet") { + if (property.properties.at(0) == UV_SET) { std::string uvName = property.properties.at(index).toString().toStdString(); tex.assign(tex.UVSet, property.properties.at(index).toString()); - } else if (property.properties.at(0) == "CurrentTextureBlendMode") { + } else if (property.properties.at(0) == CURRENT_TEXTURE_BLEND_MODE) { tex.assign(tex.currentTextureBlendMode, property.properties.at(index).value()); - } else if (property.properties.at(0) == "UseMaterial") { + } else if (property.properties.at(0) == USE_MATERIAL) { tex.assign(tex.useMaterial, property.properties.at(index).value()); - } else if (property.properties.at(0) == "Translation") { + } else if (property.properties.at(0) == TRANSLATION) { tex.assign(tex.translation, getVec3(property.properties, index)); - } else if (property.properties.at(0) == "Rotation") { + } else if (property.properties.at(0) == ROTATION) { tex.assign(tex.rotation, getVec3(property.properties, index)); - } else if (property.properties.at(0) == "Scaling") { + } else if (property.properties.at(0) == SCALING) { tex.assign(tex.scaling, getVec3(property.properties, index)); if (tex.scaling.x == 0.0f) { tex.scaling.x = 1.0f; @@ -931,87 +961,114 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (properties) { std::vector unknowns; + static const QVariant DIFFUSE_COLOR = QByteArray("DiffuseColor"); + static const QVariant DIFFUSE_FACTOR = QByteArray("DiffuseFactor"); + static const QVariant DIFFUSE = QByteArray("Diffuse"); + static const QVariant SPECULAR_COLOR = QByteArray("SpecularColor"); + static const QVariant SPECULAR_FACTOR = QByteArray("SpecularFactor"); + static const QVariant SPECULAR = QByteArray("Specular"); + static const QVariant EMISSIVE_COLOR = QByteArray("EmissiveColor"); + static const QVariant EMISSIVE_FACTOR = QByteArray("EmissiveFactor"); + static const QVariant EMISSIVE = QByteArray("Emissive"); + static const QVariant AMBIENT_FACTOR = QByteArray("AmbientFactor"); + static const QVariant SHININESS = QByteArray("Shininess"); + static const QVariant OPACITY = QByteArray("Shininess"); + static const QVariant MAYA_USE_NORMAL_MAP = QByteArray("Maya|use_normal_map"); + static const QVariant MAYA_BASE_COLOR = QByteArray("Maya|base_color"); + static const QVariant MAYA_USE_COLOR_MAP = QByteArray("Maya|use_color_map"); + static const QVariant MAYA_ROUGHNESS = QByteArray("Maya|roughness"); + static const QVariant MAYA_USE_ROUGHNESS_MAP = QByteArray("Maya|use_roughness_map"); + static const QVariant MAYA_METALLIC = QByteArray("Maya|metallic"); + static const QVariant MAYA_USE_METALLIC_MAP = QByteArray("Maya|use_metallic_map"); + static const QVariant MAYA_EMISSIVE = QByteArray("Maya|emissive"); + static const QVariant MAYA_EMISSIVE_INTENSITY = QByteArray("Maya|emissive_intensity"); + static const QVariant MAYA_USE_EMISSIVE_MAP = QByteArray("Maya|use_emissive_map"); + static const QVariant MAYA_USE_AO_MAP = QByteArray("Maya|use_ao_map"); + + + + foreach(const FBXNode& property, subobject.children) { if (property.name == propertyName) { - if (property.properties.at(0) == "DiffuseColor") { + if (property.properties.at(0) == DIFFUSE_COLOR) { material.diffuseColor = getVec3(property.properties, index); - } else if (property.properties.at(0) == "DiffuseFactor") { + } else if (property.properties.at(0) == DIFFUSE_FACTOR) { material.diffuseFactor = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Diffuse") { + } else if (property.properties.at(0) == DIFFUSE) { // NOTE: this is uneeded but keep it for now for debug // material.diffuseColor = getVec3(property.properties, index); // material.diffuseFactor = 1.0; - } else if (property.properties.at(0) == "SpecularColor") { + } else if (property.properties.at(0) == SPECULAR_COLOR) { material.specularColor = getVec3(property.properties, index); - } else if (property.properties.at(0) == "SpecularFactor") { + } else if (property.properties.at(0) == SPECULAR_FACTOR) { material.specularFactor = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Specular") { + } else if (property.properties.at(0) == SPECULAR) { // NOTE: this is uneeded but keep it for now for debug // material.specularColor = getVec3(property.properties, index); // material.specularFactor = 1.0; - } else if (property.properties.at(0) == "EmissiveColor") { + } else if (property.properties.at(0) == EMISSIVE_COLOR) { material.emissiveColor = getVec3(property.properties, index); - } else if (property.properties.at(0) == "EmissiveFactor") { + } else if (property.properties.at(0) == EMISSIVE_FACTOR) { material.emissiveFactor = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Emissive") { + } else if (property.properties.at(0) == EMISSIVE) { // NOTE: this is uneeded but keep it for now for debug // material.emissiveColor = getVec3(property.properties, index); // material.emissiveFactor = 1.0; - } else if (property.properties.at(0) == "AmbientFactor") { + } else if (property.properties.at(0) == AMBIENT_FACTOR) { material.ambientFactor = property.properties.at(index).value(); // Detected just for BLender AO vs lightmap - } else if (property.properties.at(0) == "Shininess") { + } else if (property.properties.at(0) == SHININESS) { material.shininess = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Opacity") { + } else if (property.properties.at(0) == OPACITY) { material.opacity = property.properties.at(index).value(); } // Sting Ray Material Properties!!!! - else if (property.properties.at(0) == "Maya|use_normal_map") { + else if (property.properties.at(0) == MAYA_USE_NORMAL_MAP) { material.isPBSMaterial = true; material.useNormalMap = (bool)property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|base_color") { + } else if (property.properties.at(0) == MAYA_BASE_COLOR) { material.isPBSMaterial = true; material.diffuseColor = getVec3(property.properties, index); - } else if (property.properties.at(0) == "Maya|use_color_map") { + } else if (property.properties.at(0) == MAYA_USE_COLOR_MAP) { material.isPBSMaterial = true; material.useAlbedoMap = (bool) property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|roughness") { + } else if (property.properties.at(0) == MAYA_ROUGHNESS) { material.isPBSMaterial = true; material.roughness = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|use_roughness_map") { + } else if (property.properties.at(0) == MAYA_USE_ROUGHNESS_MAP) { material.isPBSMaterial = true; material.useRoughnessMap = (bool)property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|metallic") { + } else if (property.properties.at(0) == MAYA_METALLIC) { material.isPBSMaterial = true; material.metallic = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|use_metallic_map") { + } else if (property.properties.at(0) == MAYA_USE_METALLIC_MAP) { material.isPBSMaterial = true; material.useMetallicMap = (bool)property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|emissive") { + } else if (property.properties.at(0) == MAYA_EMISSIVE) { material.isPBSMaterial = true; material.emissiveColor = getVec3(property.properties, index); - } else if (property.properties.at(0) == "Maya|emissive_intensity") { + } else if (property.properties.at(0) == MAYA_EMISSIVE_INTENSITY) { material.isPBSMaterial = true; material.emissiveIntensity = property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|use_emissive_map") { + } else if (property.properties.at(0) == MAYA_USE_EMISSIVE_MAP) { material.isPBSMaterial = true; material.useEmissiveMap = (bool)property.properties.at(index).value(); - } else if (property.properties.at(0) == "Maya|use_ao_map") { + } else if (property.properties.at(0) == MAYA_USE_AO_MAP) { material.isPBSMaterial = true; material.useOcclusionMap = (bool)property.properties.at(index).value(); @@ -1116,9 +1173,11 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS #endif } } else if (child.name == "Connections") { + static const QVariant OO = QByteArray("OO"); + static const QVariant OP = QByteArray("OP"); foreach (const FBXNode& connection, child.children) { if (connection.name == "C" || connection.name == "Connect") { - if (connection.properties.at(0) == "OO") { + if (connection.properties.at(0) == OO) { QString childID = getID(connection.properties, 1); QString parentID = getID(connection.properties, 2); ooChildToParent.insert(childID, parentID); @@ -1132,8 +1191,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS _lightmapOffset = glm::clamp((*lightIt).second.color.x, 0.f, 1.f); } } - } - if (connection.properties.at(0) == "OP") { + } else if (connection.properties.at(0) == OP) { int counter = 0; QByteArray type = connection.properties.at(3).toByteArray().toLower(); if (type.contains("DiffuseFactor")) { diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index 5a824aa284..8eb31b0731 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -171,7 +171,8 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn QVector materials; QVector textures; bool isMaterialPerPolygon = false; - + static const QVariant BY_VERTICE = QByteArray("ByVertice"); + static const QVariant INDEX_TO_DIRECT = QByteArray("IndexToDirect"); foreach (const FBXNode& child, object.children) { if (child.name == "Vertices") { data.vertices = createVec3Vector(getDoubleVector(child)); @@ -189,10 +190,10 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn } else if (subdata.name == "NormalsIndex") { data.normalIndices = getIntVector(subdata); - } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == "ByVertice") { + } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == BY_VERTICE) { data.normalsByVertex = true; - } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == "IndexToDirect") { + } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == INDEX_TO_DIRECT) { indexToDirect = true; } } @@ -209,10 +210,10 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn } else if (subdata.name == "ColorsIndex") { data.colorIndices = getIntVector(subdata); - } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == "ByVertice") { + } else if (subdata.name == "MappingInformationType" && subdata.properties.at(0) == BY_VERTICE) { data.colorsByVertex = true; - } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == "IndexToDirect") { + } else if (subdata.name == "ReferenceInformationType" && subdata.properties.at(0) == INDEX_TO_DIRECT) { indexToDirect = true; } } @@ -298,11 +299,12 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn } } } else if (child.name == "LayerElementMaterial") { + static const QVariant BY_POLYGON = QByteArray("ByPolygon"); foreach (const FBXNode& subdata, child.children) { if (subdata.name == "Materials") { materials = getIntVector(subdata); } else if (subdata.name == "MappingInformationType") { - if (subdata.properties.at(0) == "ByPolygon") + if (subdata.properties.at(0) == BY_POLYGON) isMaterialPerPolygon = true; } else { isMaterialPerPolygon = false; From 42e13d1e9771107be1a9574cca0b3d8b8f761940 Mon Sep 17 00:00:00 2001 From: Ken Cooke Date: Sat, 14 Jan 2017 10:26:13 -0800 Subject: [PATCH 13/13] Fix audio failures on systems that return incorrect/unsupported mixFormat --- libraries/audio-client/src/AudioClient.cpp | 42 +++++++++------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 1aa4439de9..1e3dc11338 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -424,35 +424,25 @@ bool adjustedFormatForAudioDevice(const QAudioDeviceInfo& audioDevice, adjustedAudioFormat = desiredAudioFormat; // - // Attempt the device sample rate in decreasing order of preference. + // Attempt the device sample rate and channel count in decreasing order of preference. // - if (audioDevice.supportedSampleRates().contains(48000)) { - adjustedAudioFormat.setSampleRate(48000); - } else if (audioDevice.supportedSampleRates().contains(44100)) { - adjustedAudioFormat.setSampleRate(44100); - } else if (audioDevice.supportedSampleRates().contains(32000)) { - adjustedAudioFormat.setSampleRate(32000); - } else if (audioDevice.supportedSampleRates().contains(24000)) { - adjustedAudioFormat.setSampleRate(24000); - } else if (audioDevice.supportedSampleRates().contains(16000)) { - adjustedAudioFormat.setSampleRate(16000); - } else if (audioDevice.supportedSampleRates().contains(96000)) { - adjustedAudioFormat.setSampleRate(96000); - } else if (audioDevice.supportedSampleRates().contains(192000)) { - adjustedAudioFormat.setSampleRate(192000); - } else if (audioDevice.supportedSampleRates().contains(88200)) { - adjustedAudioFormat.setSampleRate(88200); - } else if (audioDevice.supportedSampleRates().contains(176400)) { - adjustedAudioFormat.setSampleRate(176400); + const int sampleRates[] = { 48000, 44100, 32000, 24000, 16000, 96000, 192000, 88200, 176400 }; + const int inputChannels[] = { 1, 2, 4, 6, 8 }; // prefer mono + const int outputChannels[] = { 2, 4, 6, 8, 1 }; // prefer stereo, downmix as last resort + + for (int channelCount : (desiredAudioFormat.channelCount() == 1 ? inputChannels : outputChannels)) { + for (int sampleRate : sampleRates) { + + adjustedAudioFormat.setChannelCount(channelCount); + adjustedAudioFormat.setSampleRate(sampleRate); + + if (audioDevice.isFormatSupported(adjustedAudioFormat)) { + return true; + } + } } - if (adjustedAudioFormat != desiredAudioFormat) { - // return the nearest in case it needs 2 channels - adjustedAudioFormat = audioDevice.nearestFormat(adjustedAudioFormat); - return true; - } else { - return false; - } + return false; // a supported format could not be found } bool sampleChannelConversion(const int16_t* sourceSamples, int16_t* destinationSamples, unsigned int numSourceSamples,