From bcec3680b6ac0676262d755f588bfd0c6f0455b8 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 25 Sep 2017 11:51:23 +0200 Subject: [PATCH 01/55] First draft --- libraries/render-utils/src/BloomEffect.cpp | 36 ++++++++++++++ libraries/render-utils/src/BloomEffect.h | 47 +++++++++++++++++++ .../render-utils/src/RenderDeferredTask.cpp | 5 ++ 3 files changed, 88 insertions(+) create mode 100644 libraries/render-utils/src/BloomEffect.cpp create mode 100644 libraries/render-utils/src/BloomEffect.h diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp new file mode 100644 index 0000000000..a0a36a2194 --- /dev/null +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -0,0 +1,36 @@ +// +// BloomEffect.cpp +// render-utils/src/ +// +// Created by Olivier Prat on 09/25/17. +// 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 +// +#include "BloomEffect.h" + +#include + +void BloomConfig::setMix(float value) { + +} + +void BloomConfig::setSize(float value) { + auto blurConfig = getConfig("Blur"); + assert(blurConfig); + blurConfig->setProperty("filterScale", value*10.0f); +} + +Bloom::Bloom() { + +} + +void Bloom::configure(const Config& config) { + +} + +void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { + const auto& blurInput = inputs; + task.addJob("Blur", blurInput); +} diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h new file mode 100644 index 0000000000..278236d2e9 --- /dev/null +++ b/libraries/render-utils/src/BloomEffect.h @@ -0,0 +1,47 @@ +// +// BloomEffect.h +// render-utils/src/ +// +// Created by Olivier Prat on 09/25/17. +// 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 +// + +#ifndef hifi_render_utils_BloomEffect_h +#define hifi_render_utils_BloomEffect_h + +#include + +class BloomConfig : public render::Task::Config { + Q_OBJECT + Q_PROPERTY(float mix MEMBER mix WRITE setMix NOTIFY dirty) + Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) + +public: + + float mix{ 0.2f }; + float size{ 0.1f }; + + void setMix(float value); + void setSize(float value); + +signals: + void dirty(); +}; + +class Bloom { +public: + using Inputs = gpu::FramebufferPointer; + using Config = BloomConfig; + using JobModel = render::Task::ModelI; + + Bloom(); + + void configure(const Config& config); + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + +}; + +#endif // hifi_render_utils_BloomEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index c67a1c7875..682d5db435 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -41,6 +41,7 @@ #include "ToneMappingEffect.h" #include "SubsurfaceScattering.h" #include "OutlineEffect.h" +#include "BloomEffect.h" #include @@ -168,6 +169,10 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); + // Add bloom + const auto bloomInputs = lightingFramebuffer; + task.addJob("Bloom", bloomInputs); + // Lighting Buffer ready for tone mapping const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, primaryFramebuffer).asVarying(); task.addJob("ToneMapping", toneMappingInputs); From 443d6dfacb1716d45ae8a03bd1a8e7987cb209fa Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 25 Sep 2017 14:24:40 +0200 Subject: [PATCH 02/55] Added user definable taps in blur task --- libraries/render/src/render/BlurTask.cpp | 56 ++++++++++++- libraries/render/src/render/BlurTask.h | 11 ++- libraries/render/src/render/BlurTask.slh | 83 ++++++++----------- .../render/src/render/BlurTask_shared.slh | 10 +++ 4 files changed, 107 insertions(+), 53 deletions(-) create mode 100644 libraries/render/src/render/BlurTask_shared.slh diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 73a8e0a0dd..2d51fd1271 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -29,11 +29,10 @@ enum BlurShaderMapSlots { BlurTask_DepthSlot, }; -const float BLUR_NUM_SAMPLES = 7.0f; - BlurParams::BlurParams() { Params params; _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Params), (const gpu::Byte*) ¶ms)); + setGaussianFilterTaps(3); } void BlurParams::setWidthHeight(int width, int height, bool isStereo) { @@ -60,7 +59,58 @@ void BlurParams::setFilterRadiusScale(float scale) { auto filterInfo = _parametersBuffer.get().filterInfo; if (scale != filterInfo.x) { _parametersBuffer.edit().filterInfo.x = scale; - _parametersBuffer.edit().filterInfo.y = scale / BLUR_NUM_SAMPLES; + } +} + +void BlurParams::setFilterNumTaps(int count) { + assert(count <= BLUR_MAX_NUM_TAPS); + auto filterInfo = _parametersBuffer.get().filterInfo; + if (count != (int)filterInfo.y) { + _parametersBuffer.edit().filterInfo.y = count; + } +} + +void BlurParams::setFilterTap(int index, float offset, float value) { + auto filterTaps = _parametersBuffer.edit().filterTaps; + assert(index < BLUR_MAX_NUM_TAPS); + filterTaps[index].x = offset; + filterTaps[index].y = value; +} + +void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma, bool normalize) { + auto& params = _parametersBuffer.edit(); + const int numTaps = 2 * numHalfTaps + 1; + assert(numTaps <= BLUR_MAX_NUM_TAPS); + assert(sigma > 0.0f); + const float inverseTwoSigmaSquared = float(0.5 / (sigma*sigma)); + float totalWeight = 1.0f; + float weight; + float offset; + int i; + + params.filterInfo.y = numTaps; + params.filterTaps[0].x = 0.0f; + params.filterTaps[0].y = 1.0f; + + for (i = 0; i < numHalfTaps; i++) { + offset = i + 1; + weight = (float)exp(-offset*offset * inverseTwoSigmaSquared); + params.filterTaps[i + 1].x = offset; + params.filterTaps[i + 1].y = weight; + params.filterTaps[i + 1 + numHalfTaps].x = -offset; + params.filterTaps[i + 1 + numHalfTaps].y = weight; + totalWeight += 2 * weight; + } + + float normalizer; + if (normalize) { + normalizer = float(1.0 / totalWeight); + } else { + normalizer = float(1.0 / (sqrt(2 * M_PI)*sigma)); + } + + for (i = 0; i < numTaps; i++) { + params.filterTaps[i].y *= normalizer; } } diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h index f023aabfe7..011da6ab68 100644 --- a/libraries/render/src/render/BlurTask.h +++ b/libraries/render/src/render/BlurTask.h @@ -14,6 +14,8 @@ #include "Engine.h" +#include "BlurTask_shared.slh" + namespace render { @@ -25,6 +27,10 @@ public: void setTexcoordTransform(const glm::vec4 texcoordTransformViewport); void setFilterRadiusScale(float scale); + void setFilterNumTaps(int count); + // Tap 0 is considered the center of the kernel + void setFilterTap(int index, float offset, float value); + void setGaussianFilterTaps(int numHalfTaps, float sigma = 1.47f, bool normalize = true); void setDepthPerspective(float oneOverTan2FOV); void setDepthThreshold(float threshold); @@ -40,7 +46,7 @@ public: // Viewport to Texcoord info, if the region of the blur (viewport) is smaller than the full frame glm::vec4 texcoordTransform{ 0.0f, 0.0f, 1.0f, 1.0f }; - // Filter info (radius scale + // Filter info (radius scale, number of taps, mix) glm::vec4 filterInfo{ 1.0f, 0.0f, 0.0f, 0.0f }; // Depth info (radius scale @@ -52,6 +58,9 @@ public: // LinearDepth info is { f } glm::vec4 linearDepthInfo{ 0.0f }; + // Taps (offset, weight) + glm::vec2 filterTaps[BLUR_MAX_NUM_TAPS]; + Params() {} }; gpu::BufferView _parametersBuffer; diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh index de2614eb51..b871b59bed 100644 --- a/libraries/render/src/render/BlurTask.slh +++ b/libraries/render/src/render/BlurTask.slh @@ -9,17 +9,7 @@ <@func declareBlurUniforms()@> -#define NUM_TAPS 7 -#define NUM_TAPS_OFFSET 3.0f - -float uniformFilterWidth = 0.05f; - -const float gaussianDistributionCurve[NUM_TAPS] = float[]( - 0.383f, 0.006f, 0.061f, 0.242f, 0.242f, 0.061f, 0.006f -); -const float gaussianDistributionOffset[NUM_TAPS] = float[]( - 0.0f, -3.0f, -2.0f, -1.0f, 1.0f, 2.0f, 3.0f -); +<@include BlurTask_shared.slh@> struct BlurParameters { vec4 resolutionInfo; @@ -28,6 +18,7 @@ struct BlurParameters { vec4 depthInfo; vec4 stereoInfo; vec4 linearDepthInfo; + vec2 taps[BLUR_MAX_NUM_TAPS]; }; uniform blurParamsBuffer { @@ -46,6 +37,25 @@ float getFilterScale() { return parameters.filterInfo.x; } +int getFilterNumTaps() { + return int(parameters.filterInfo.y); +} + +float getFilterMix() { + return parameters.filterInfo.z; +} + +vec2 getFilterTap(int index) { + return parameters.taps[index]; +} + +float getFilterTapOffset(vec2 tap) { + return tap.x; +} + +float getFilterTapWeight(vec2 tap) { + return tap.y; +} float getDepthThreshold() { return parameters.depthInfo.x; @@ -70,17 +80,18 @@ uniform sampler2D sourceMap; vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { texcoord = evalTexcoordTransformed(texcoord); - vec4 sampleCenter = texture(sourceMap, texcoord); vec2 finalStep = getFilterScale() * direction * pixelStep; vec4 srcBlurred = vec4(0.0); + int numTaps = getFilterNumTaps(); - for(int i = 0; i < NUM_TAPS; i++) { + for(int i = 0; i < numTaps; i++) { + vec2 tapInfo = getFilterTap(i); // Fetch color and depth for current sample. - vec2 sampleCoord = texcoord + (gaussianDistributionOffset[i] * finalStep); + vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep); vec4 srcSample = texture(sourceMap, sampleCoord); // Accumulate. - srcBlurred += gaussianDistributionCurve[i] * srcSample; + srcBlurred += getFilterTapWeight(tapInfo) * srcSample; } return srcBlurred; @@ -95,15 +106,6 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { uniform sampler2D sourceMap; uniform sampler2D depthMap; -#define NUM_HALF_TAPS 4 - -const float gaussianDistributionCurveHalf[NUM_HALF_TAPS] = float[]( - 0.383f, 0.242f, 0.061f, 0.006f -); -const float gaussianDistributionOffsetHalf[NUM_HALF_TAPS] = float[]( - 0.0f, 1.0f, 2.0f, 3.0f -); - vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep) { texcoord = evalTexcoordTransformed(texcoord); float sampleDepth = texture(depthMap, texcoord).x; @@ -122,13 +124,17 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep float scale = distanceToProjectionWindow / sampleDepth; vec2 finalStep = filterScale * scale * direction * pixelStep; + int numTaps = getFilterNumTaps(); // Accumulate the center sample - vec4 srcBlurred = gaussianDistributionCurve[0] * sampleCenter; + vec2 tapInfo = getFilterTap(0); + vec4 srcBlurred = getFilterTapWeight(tapInfo) * sampleCenter; + + for(int i = 1; i < numTaps; i++) { + tapInfo = getFilterTap(i); - for(int i = 1; i < NUM_TAPS; i++) { // Fetch color and depth for current sample. - vec2 sampleCoord = texcoord + (gaussianDistributionOffset[i] * finalStep); + vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep); float srcDepth = texture(depthMap, sampleCoord).x; vec4 srcSample = texture(sourceMap, sampleCoord); @@ -137,29 +143,8 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep srcSample = mix(srcSample, sampleCenter, s); // Accumulate. - srcBlurred += gaussianDistributionCurve[i] * srcSample; + srcBlurred += getFilterTapWeight(tapInfo) * srcSample; } - - /* - for(int i = 1; i < NUM_HALF_TAPS; i++) { - // Fetch color and depth for current sample. - vec2 texcoordOffset = (gaussianDistributionOffsetHalf[i] * finalStep); - - float srcDepthN = texture(depthMap, texcoord - texcoordOffset).x; - float srcDepthP = texture(depthMap, texcoord + texcoordOffset).x; - vec4 srcSampleN = texture(sourceMap, texcoord - texcoordOffset); - vec4 srcSampleP = texture(sourceMap, texcoord + texcoordOffset); - - // If the difference in depth is huge, we lerp color back. - float sN = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepthN - sampleDepth), 0.0, 1.0); - float sP = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepthP - sampleDepth), 0.0, 1.0); - - srcSampleN = mix(srcSampleN, sampleCenter, sN); - srcSampleP = mix(srcSampleP, sampleCenter, sP); - - // Accumulate. - srcBlurred += gaussianDistributionCurveHalf[i] * (srcSampleP + srcSampleN); - }*/ return srcBlurred; } diff --git a/libraries/render/src/render/BlurTask_shared.slh b/libraries/render/src/render/BlurTask_shared.slh new file mode 100644 index 0000000000..94417fa939 --- /dev/null +++ b/libraries/render/src/render/BlurTask_shared.slh @@ -0,0 +1,10 @@ +// Generated on <$_SCRIBE_DATE$> +// +// Created by Olivier Prat on 09/25/17. +// 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 +// + +#define BLUR_MAX_NUM_TAPS 21 From 22b1507597e1aafea88ece8beb5d2d18c6e6f1eb Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 25 Sep 2017 16:41:20 +0200 Subject: [PATCH 03/55] Fixed blur to work correctly on four sides of screen --- .../src/RenderableModelEntityItem.cpp | 4 +- libraries/render-utils/src/BloomEffect.cpp | 10 +++-- libraries/render/src/render/BlurTask.cpp | 16 ++------ libraries/render/src/render/BlurTask.h | 4 +- libraries/render/src/render/BlurTask.slh | 40 +++++++++++++------ .../render/src/render/BlurTask_shared.slh | 2 +- 6 files changed, 44 insertions(+), 32 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 799a84aaee..b88ef5f8fb 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -319,7 +319,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { // should never fall in here when collision model not fully loaded // hence we assert that all geometries exist and are loaded - assert(_model && _model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded()); + assert(model && model->isLoaded() && _compoundShapeResource && _compoundShapeResource->isLoaded()); const FBXGeometry& collisionGeometry = _compoundShapeResource->getFBXGeometry(); ShapeInfo::PointCollection& pointCollection = shapeInfo.getPointCollection(); @@ -408,7 +408,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { shapeInfo.setParams(type, dimensions, getCompoundShapeURL()); } else if (type >= SHAPE_TYPE_SIMPLE_HULL && type <= SHAPE_TYPE_STATIC_MESH) { // should never fall in here when model not fully loaded - assert(_model && _model->isLoaded()); + assert(model && model->isLoaded()); updateModelBounds(); model->updateGeometry(); diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index a0a36a2194..eb02c4fa57 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -17,9 +17,10 @@ void BloomConfig::setMix(float value) { } void BloomConfig::setSize(float value) { - auto blurConfig = getConfig("Blur"); - assert(blurConfig); - blurConfig->setProperty("filterScale", value*10.0f); + auto& blurJob = static_cast(_task)->_jobs.front(); + auto& gaussianBlur = blurJob.edit(); + auto gaussianBlurParams = gaussianBlur.getParameters(); + gaussianBlurParams->setGaussianFilterTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f); } Bloom::Bloom() { @@ -27,7 +28,8 @@ Bloom::Bloom() { } void Bloom::configure(const Config& config) { - + auto blurConfig = config.getConfig(); + blurConfig->setProperty("filterScale", 2.5f); } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 2d51fd1271..2e3cf8138f 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -77,7 +77,7 @@ void BlurParams::setFilterTap(int index, float offset, float value) { filterTaps[index].y = value; } -void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma, bool normalize) { +void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma) { auto& params = _parametersBuffer.edit(); const int numTaps = 2 * numHalfTaps + 1; assert(numTaps <= BLUR_MAX_NUM_TAPS); @@ -102,16 +102,8 @@ void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma, bool normal totalWeight += 2 * weight; } - float normalizer; - if (normalize) { - normalizer = float(1.0 / totalWeight); - } else { - normalizer = float(1.0 / (sqrt(2 * M_PI)*sigma)); - } - - for (i = 0; i < numTaps; i++) { - params.filterTaps[i].y *= normalizer; - } + // Tap weights will be normalized in shader because side cases on edges of screen + // won't have the same number of taps as in the center. } void BlurParams::setDepthPerspective(float oneOverTan2FOV) { @@ -158,7 +150,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra // _blurredFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat()); //} auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - auto blurringTarget = gpu::Texture::create2D(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); + auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); _blurredFramebuffer->setRenderBuffer(0, blurringTarget); } diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h index 011da6ab68..4df5a09576 100644 --- a/libraries/render/src/render/BlurTask.h +++ b/libraries/render/src/render/BlurTask.h @@ -30,7 +30,7 @@ public: void setFilterNumTaps(int count); // Tap 0 is considered the center of the kernel void setFilterTap(int index, float offset, float value); - void setGaussianFilterTaps(int numHalfTaps, float sigma = 1.47f, bool normalize = true); + void setGaussianFilterTaps(int numHalfTaps, float sigma = 1.47f); void setDepthPerspective(float oneOverTan2FOV); void setDepthThreshold(float threshold); @@ -116,6 +116,8 @@ public: void configure(const Config& config); void run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& blurredFramebuffer); + BlurParamsPointer getParameters() const { return _parameters; } + protected: BlurParamsPointer _parameters; diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh index b871b59bed..5a41a0b1c6 100644 --- a/libraries/render/src/render/BlurTask.slh +++ b/libraries/render/src/render/BlurTask.slh @@ -83,17 +83,25 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { vec2 finalStep = getFilterScale() * direction * pixelStep; vec4 srcBlurred = vec4(0.0); + float totalWeight = 0.f; int numTaps = getFilterNumTaps(); for(int i = 0; i < numTaps; i++) { vec2 tapInfo = getFilterTap(i); - // Fetch color and depth for current sample. + // Fetch color for current sample. vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep); - vec4 srcSample = texture(sourceMap, sampleCoord); - // Accumulate. - srcBlurred += getFilterTapWeight(tapInfo) * srcSample; + if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) { + vec4 srcSample = texture(sourceMap, sampleCoord); + float weight = getFilterTapWeight(tapInfo); + // Accumulate. + srcBlurred += srcSample * weight; + totalWeight += weight; + } } + if (totalWeight>0.0) { + srcBlurred /= totalWeight; + } return srcBlurred; } @@ -128,24 +136,32 @@ vec4 pixelShaderGaussianDepthAware(vec2 texcoord, vec2 direction, vec2 pixelStep // Accumulate the center sample vec2 tapInfo = getFilterTap(0); - vec4 srcBlurred = getFilterTapWeight(tapInfo) * sampleCenter; + float totalWeight = getFilterTapWeight(tapInfo); + vec4 srcBlurred = sampleCenter * totalWeight; for(int i = 1; i < numTaps; i++) { tapInfo = getFilterTap(i); // Fetch color and depth for current sample. vec2 sampleCoord = texcoord + (getFilterTapOffset(tapInfo) * finalStep); - float srcDepth = texture(depthMap, sampleCoord).x; - vec4 srcSample = texture(sourceMap, sampleCoord); + if (all(greaterThanEqual(sampleCoord, vec2(0,0))) && all(lessThanEqual(sampleCoord, vec2(1.0,1.0)))) { + float srcDepth = texture(depthMap, sampleCoord).x; + vec4 srcSample = texture(sourceMap, sampleCoord); + float weight = getFilterTapWeight(tapInfo); - // If the difference in depth is huge, we lerp color back. - float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0); - srcSample = mix(srcSample, sampleCenter, s); + // If the difference in depth is huge, we lerp color back. + float s = clamp(depthThreshold * distanceToProjectionWindow * filterScale * abs(srcDepth - sampleDepth), 0.0, 1.0); + srcSample = mix(srcSample, sampleCenter, s); - // Accumulate. - srcBlurred += getFilterTapWeight(tapInfo) * srcSample; + // Accumulate. + srcBlurred += srcSample * weight; + totalWeight += weight; + } } + if (totalWeight>0.0) { + srcBlurred /= totalWeight; + } return srcBlurred; } diff --git a/libraries/render/src/render/BlurTask_shared.slh b/libraries/render/src/render/BlurTask_shared.slh index 94417fa939..84c633d74c 100644 --- a/libraries/render/src/render/BlurTask_shared.slh +++ b/libraries/render/src/render/BlurTask_shared.slh @@ -7,4 +7,4 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#define BLUR_MAX_NUM_TAPS 21 +#define BLUR_MAX_NUM_TAPS 25 From 27b9f3516df5dc2395a4d71b69bfa91b94279f23 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 25 Sep 2017 18:05:30 +0200 Subject: [PATCH 04/55] Added mix parameter to blur and bloom --- libraries/render-utils/src/BloomEffect.cpp | 9 +++++---- libraries/render-utils/src/BloomEffect.h | 8 ++++---- libraries/render/src/render/BlurTask.cpp | 19 ++++++++++++++++--- libraries/render/src/render/BlurTask.h | 10 +++++++--- libraries/render/src/render/BlurTask.slh | 3 ++- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index eb02c4fa57..24cdd5fca3 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -12,15 +12,16 @@ #include -void BloomConfig::setMix(float value) { - +void BloomConfig::setIntensity(float value) { + auto blurConfig = getConfig(); + blurConfig->setProperty("mix", value*0.5f); } void BloomConfig::setSize(float value) { auto& blurJob = static_cast(_task)->_jobs.front(); auto& gaussianBlur = blurJob.edit(); auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setGaussianFilterTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f); + gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f); } Bloom::Bloom() { @@ -29,7 +30,7 @@ Bloom::Bloom() { void Bloom::configure(const Config& config) { auto blurConfig = config.getConfig(); - blurConfig->setProperty("filterScale", 2.5f); + blurConfig->setProperty("filterScale", 3.0f); } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 278236d2e9..c8588c7a15 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -16,15 +16,15 @@ class BloomConfig : public render::Task::Config { Q_OBJECT - Q_PROPERTY(float mix MEMBER mix WRITE setMix NOTIFY dirty) + Q_PROPERTY(float intensity MEMBER intensity WRITE setIntensity NOTIFY dirty) Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) public: - float mix{ 0.2f }; - float size{ 0.1f }; + float intensity{ 0.2f }; + float size{ 0.4f }; - void setMix(float value); + void setIntensity(float value); void setSize(float value); signals: diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 2e3cf8138f..66f098302d 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -32,7 +32,7 @@ enum BlurShaderMapSlots { BlurParams::BlurParams() { Params params; _parametersBuffer = gpu::BufferView(std::make_shared(sizeof(Params), (const gpu::Byte*) ¶ms)); - setGaussianFilterTaps(3); + setFilterGaussianTaps(3); } void BlurParams::setWidthHeight(int width, int height, bool isStereo) { @@ -77,7 +77,7 @@ void BlurParams::setFilterTap(int index, float offset, float value) { filterTaps[index].y = value; } -void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma) { +void BlurParams::setFilterGaussianTaps(int numHalfTaps, float sigma) { auto& params = _parametersBuffer.edit(); const int numTaps = 2 * numHalfTaps + 1; assert(numTaps <= BLUR_MAX_NUM_TAPS); @@ -106,6 +106,14 @@ void BlurParams::setGaussianFilterTaps(int numHalfTaps, float sigma) { // won't have the same number of taps as in the center. } +void BlurParams::setOutputAlpha(float value) { + value = glm::clamp(value, 0.0f, 1.0f); + auto filterInfo = _parametersBuffer.get().filterInfo; + if (value != filterInfo.z) { + _parametersBuffer.edit().filterInfo.z = value; + } +} + void BlurParams::setDepthPerspective(float oneOverTan2FOV) { auto depthInfo = _parametersBuffer.get().depthInfo; if (oneOverTan2FOV != depthInfo.w) { @@ -238,7 +246,13 @@ gpu::PipelinePointer BlurGaussian::getBlurHPipeline() { } void BlurGaussian::configure(const Config& config) { + auto blurHPipeline = getBlurHPipeline(); + _parameters->setFilterRadiusScale(config.filterScale); + _parameters->setOutputAlpha(config.mix); + + blurHPipeline->getState()->setBlendFunction(config.mix < 1.0f, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); } @@ -248,7 +262,6 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra RenderArgs* args = renderContext->args; - BlurInOutResource::Resources blurringResources; if (!_inOutResources.updateResources(sourceFramebuffer, blurringResources)) { // early exit if no valid blurring resources diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h index 4df5a09576..cbee3e35f1 100644 --- a/libraries/render/src/render/BlurTask.h +++ b/libraries/render/src/render/BlurTask.h @@ -30,7 +30,8 @@ public: void setFilterNumTaps(int count); // Tap 0 is considered the center of the kernel void setFilterTap(int index, float offset, float value); - void setGaussianFilterTaps(int numHalfTaps, float sigma = 1.47f); + void setFilterGaussianTaps(int numHalfTaps, float sigma = 1.47f); + void setOutputAlpha(float value); void setDepthPerspective(float oneOverTan2FOV); void setDepthThreshold(float threshold); @@ -46,7 +47,7 @@ public: // Viewport to Texcoord info, if the region of the blur (viewport) is smaller than the full frame glm::vec4 texcoordTransform{ 0.0f, 0.0f, 1.0f, 1.0f }; - // Filter info (radius scale, number of taps, mix) + // Filter info (radius scale, number of taps, output alpha) glm::vec4 filterInfo{ 1.0f, 0.0f, 0.0f, 0.0f }; // Depth info (radius scale @@ -93,12 +94,15 @@ public: class BlurGaussianConfig : public Job::Config { Q_OBJECT Q_PROPERTY(bool enabled WRITE setEnabled READ isEnabled NOTIFY dirty) // expose enabled flag - Q_PROPERTY(float filterScale MEMBER filterScale NOTIFY dirty) // expose enabled flag + Q_PROPERTY(float filterScale MEMBER filterScale NOTIFY dirty) + Q_PROPERTY(float mix MEMBER mix NOTIFY dirty) public: BlurGaussianConfig() : Job::Config(true) {} float filterScale{ 0.2f }; + float mix{ 1.0f }; + signals : void dirty(); diff --git a/libraries/render/src/render/BlurTask.slh b/libraries/render/src/render/BlurTask.slh index 5a41a0b1c6..37f29496bd 100644 --- a/libraries/render/src/render/BlurTask.slh +++ b/libraries/render/src/render/BlurTask.slh @@ -41,7 +41,7 @@ int getFilterNumTaps() { return int(parameters.filterInfo.y); } -float getFilterMix() { +float getOutputAlpha() { return parameters.filterInfo.z; } @@ -102,6 +102,7 @@ vec4 pixelShaderGaussian(vec2 texcoord, vec2 direction, vec2 pixelStep) { if (totalWeight>0.0) { srcBlurred /= totalWeight; } + srcBlurred.a = getOutputAlpha(); return srcBlurred; } From 27a0fb62d31c8f0e68f1fb48309926c386abb03d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 9 Oct 2017 09:35:38 +0200 Subject: [PATCH 05/55] Multiple gaussians as Unreal. First draft --- libraries/render-utils/src/BloomEffect.cpp | 145 +++++++++++++++++- libraries/render-utils/src/BloomEffect.h | 76 ++++++++- libraries/render-utils/src/BloomThreshold.slf | 40 +++++ .../render-utils/src/RenderDeferredTask.cpp | 2 +- scripts/developer/utilities/render/bloom.qml | 66 ++++++++ .../developer/utilities/render/debugBloom.js | 20 +++ 6 files changed, 332 insertions(+), 17 deletions(-) create mode 100644 libraries/render-utils/src/BloomThreshold.slf create mode 100644 scripts/developer/utilities/render/bloom.qml create mode 100644 scripts/developer/utilities/render/debugBloom.js diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 24cdd5fca3..f083bf7e6b 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -10,18 +10,145 @@ // #include "BloomEffect.h" +#include "gpu/Context.h" +#include "gpu/StandardShaderLib.h" + #include +#include "BloomThreshold_frag.h" + +ThresholdAndDownsampleJob::ThresholdAndDownsampleJob() { + +} + +void ThresholdAndDownsampleJob::configure(const Config& config) { + _threshold = config.threshold; +} + +void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + + RenderArgs* args = renderContext->args; + + const auto frameTransform = inputs.get0(); + const auto inputFrameBuffer = inputs.get1(); + + assert(inputFrameBuffer->hasColor()); + + auto inputColor = inputFrameBuffer->getRenderBuffer(0); + auto sourceViewport = args->_viewport; + auto fullSize = glm::ivec2(inputColor->getDimensions()); + auto halfSize = fullSize / 2; + auto halfViewport = args->_viewport >> 1; + + if (!_downsampledBuffer || _downsampledBuffer->getSize().x != halfSize.x || _downsampledBuffer->getSize().y != halfSize.y) { + auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputColor->getTexelFormat(), halfSize.x, halfSize.y, + gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR))); + + _downsampledBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomBlur0")); + _downsampledBuffer->setRenderBuffer(0, colorTexture); + } + + static const int COLOR_MAP_SLOT = 0; + static const int THRESHOLD_SLOT = 1; + + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto ps = gpu::Shader::createPixel(std::string(BloomThreshold_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("colorMap", COLOR_MAP_SLOT)); + slotBindings.insert(gpu::Shader::Binding("threshold", THRESHOLD_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + _pipeline = gpu::Pipeline::create(program, state); + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + +/* batch.setViewportTransform(halfViewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(inputFrameBuffer->getSize(), args->_viewport)); + batch.setPipeline(_pipeline);*/ + + batch.setFramebuffer(_downsampledBuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, gpu::Vec4(1.0f, 0.2f, 0.9f, 1.f)); + /*batch.setResourceTexture(COLOR_MAP_SLOT, inputColor); + batch._glUniform1f(THRESHOLD_SLOT, _threshold); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + batch.setViewportTransform(args->_viewport); + batch.setResourceTexture(COLOR_MAP_SLOT, nullptr); + batch.setFramebuffer(nullptr);*/ + }); + + outputs = _downsampledBuffer; +} + +DebugBloom::DebugBloom() { +} + +DebugBloom::~DebugBloom() { +} + +void DebugBloom::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + RenderArgs* args = renderContext->args; + + const auto frameBuffer = inputs.get0(); + const auto level0FB = inputs.get1(); + const gpu::TexturePointer levelTextures[1] = { + level0FB->getRenderBuffer(0) + }; + + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); + auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(false)); + _pipeline = gpu::Pipeline::create(program, state); + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + + //batch.setFramebuffer(frameBuffer); + batch.setViewportTransform(args->_viewport); + + glm::mat4 projMat; + Transform viewMat; + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat, false); + batch.setPipeline(_pipeline); + batch.setResourceTexture(0, levelTextures[0]); + + batch.draw(gpu::TRIANGLE_STRIP, 4); + + batch.setResourceTexture(0, nullptr); + }); +} + void BloomConfig::setIntensity(float value) { - auto blurConfig = getConfig(); - blurConfig->setProperty("mix", value*0.5f); + /* auto blurConfig = getConfig(); + blurConfig->setProperty("mix", value*0.5f);*/ } void BloomConfig::setSize(float value) { - auto& blurJob = static_cast(_task)->_jobs.front(); + /* auto& blurJob = static_cast(_task)->_jobs.front(); auto& gaussianBlur = blurJob.edit(); auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f); + gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f);*/ } Bloom::Bloom() { @@ -29,11 +156,13 @@ Bloom::Bloom() { } void Bloom::configure(const Config& config) { - auto blurConfig = config.getConfig(); - blurConfig->setProperty("filterScale", 3.0f); +/* auto blurConfig = config.getConfig(); + blurConfig->setProperty("filterScale", 3.0f);*/ } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - const auto& blurInput = inputs; - task.addJob("Blur", blurInput); + const auto halfSizeBuffer = task.addJob("BloomThreshold", inputs); + + const auto debugInput = DebugBloom::Inputs(inputs.get().get1(), halfSizeBuffer).asVarying(); + task.addJob("DebugBloom", debugInput); } diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index c8588c7a15..ec14a6ad9f 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -14,27 +14,87 @@ #include +#include "DeferredFrameTransform.h" + class BloomConfig : public render::Task::Config { - Q_OBJECT - Q_PROPERTY(float intensity MEMBER intensity WRITE setIntensity NOTIFY dirty) - Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) + Q_OBJECT + Q_PROPERTY(float intensity MEMBER intensity WRITE setIntensity NOTIFY dirty) + Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) public: - float intensity{ 0.2f }; - float size{ 0.4f }; + BloomConfig() : render::Task::Config(true) {} + + float intensity{ 0.2f }; + float size{ 0.4f }; void setIntensity(float value); void setSize(float value); signals: - void dirty(); + void dirty(); +}; + +class ThresholdConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) + +public: + + float threshold{ 0.25f }; + +signals: + void dirty(); +}; + +class ThresholdAndDownsampleJob { +public: + using Inputs = render::VaryingSet2; + using Outputs = gpu::FramebufferPointer; + using Config = ThresholdConfig; + using JobModel = render::Job::ModelIO; + + ThresholdAndDownsampleJob(); + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); + +private: + + gpu::FramebufferPointer _downsampledBuffer; + gpu::PipelinePointer _pipeline; + float _threshold; +}; + +class DebugBloomConfig : public render::Job::Config { + Q_OBJECT + +public: + + DebugBloomConfig() : render::Job::Config(true) {} + +}; + +class DebugBloom { +public: + using Inputs = render::VaryingSet2; + using Config = DebugBloomConfig; + using JobModel = render::Job::ModelI; + + DebugBloom(); + ~DebugBloom(); + + void configure(const Config& config) {} + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + +private: + gpu::PipelinePointer _pipeline; }; class Bloom { public: - using Inputs = gpu::FramebufferPointer; - using Config = BloomConfig; + using Inputs = render::VaryingSet2; + using Config = BloomConfig; using JobModel = render::Task::ModelI; Bloom(); diff --git a/libraries/render-utils/src/BloomThreshold.slf b/libraries/render-utils/src/BloomThreshold.slf new file mode 100644 index 0000000000..7c87ed9fcd --- /dev/null +++ b/libraries/render-utils/src/BloomThreshold.slf @@ -0,0 +1,40 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// BloomThreshold.slf +// Perform a soft threshold on an input texture and downsample to half size in one go. +// +// Created by Olivier Prat on 09/26/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 +// + +uniform sampler2D colorMap; +uniform float threshold; + +in vec2 varTexCoord0; +out vec4 outFragColor; + +void main(void) { + // Gather 2 by 2 quads from texture, threshold and downsample + vec4 reds = textureGather(colorMap, varTexCoord0, 0); + vec4 greens = textureGather(colorMap, varTexCoord0, 1); + vec4 blues = textureGather(colorMap, varTexCoord0, 2); + + float hardness = 8; + vec4 rMask = clamp((reds-threshold) * hardness, 0, 1); + vec4 gMask = clamp((greens-threshold) * hardness, 0, 1); + vec4 bMask = clamp((blues-threshold) * hardness, 0, 1); + + reds = smoothstep(vec4(0,0,0,0), reds, rMask); + greens = smoothstep(vec4(0,0,0,0), greens, gMask); + blues = smoothstep(vec4(0,0,0,0), blues, bMask); + + vec3 texel0 = vec3(reds.x, greens.x, blues.x); + vec3 texel1 = vec3(reds.y, greens.y, blues.y); + vec3 texel2 = vec3(reds.z, greens.z, blues.z); + vec3 texel3 = vec3(reds.w, greens.w, blues.w); + + outFragColor = vec4((texel0+texel1+texel2+texel3)/4.0, 1.0); +} diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 682d5db435..c3e0fec3b1 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -170,7 +170,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto toneAndPostRangeTimer = task.addJob("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing"); // Add bloom - const auto bloomInputs = lightingFramebuffer; + const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying(); task.addJob("Bloom", bloomInputs); // Lighting Buffer ready for tone mapping diff --git a/scripts/developer/utilities/render/bloom.qml b/scripts/developer/utilities/render/bloom.qml new file mode 100644 index 0000000000..7deeffc218 --- /dev/null +++ b/scripts/developer/utilities/render/bloom.qml @@ -0,0 +1,66 @@ +// +// bloom.qml +// developer/utilities/render +// +// Olivier Prat, created on 09/25/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "configSlider" + +Item { + id: root + property var config: Render.getConfig("RenderMainView.Bloom") + property var configThreshold: Render.getConfig("RenderMainView.BloomThreshold") + property var configDebug: Render.getConfig("RenderMainView.DebugBloom") + + Column { + spacing: 8 + + CheckBox { + text: "Enable" + checked: root.config["enabled"] + onCheckedChanged: { + root.config["enabled"] = checked; + } + } + CheckBox { + text: "Debug" + checked: root.configDebug["enabled"] + onCheckedChanged: { + root.configDebug["enabled"] = checked; + } + } + ConfigSlider { + label: "Intensity" + integral: false + config: root.config + property: "intensity" + max: 1.0 + min: 0.0 + width: 280 + } + ConfigSlider { + label: "Size" + integral: false + config: root.config + property: "size" + max: 1.0 + min: 0.0 + width: 280 + } + ConfigSlider { + label: "Threshold" + integral: false + config: root.configThreshold + property: "threshold" + max: 1.0 + min: 0.0 + width: 280 + } + } +} diff --git a/scripts/developer/utilities/render/debugBloom.js b/scripts/developer/utilities/render/debugBloom.js new file mode 100644 index 0000000000..2328d524cf --- /dev/null +++ b/scripts/developer/utilities/render/debugBloom.js @@ -0,0 +1,20 @@ +// +// debugBloom.js +// developer/utilities/render +// +// Olivier Prat, created on 09/25/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 +// + +// Set up the qml ui +var qml = Script.resolvePath('bloom.qml'); +var window = new OverlayWindow({ + title: 'Bloom', + source: qml, + width: 285, + height: 170, +}); +window.closed.connect(function() { Script.stop(); }); \ No newline at end of file From 50ab73009a89a00f23459760bca4f24dc2d7d83f Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 9 Oct 2017 11:09:51 +0200 Subject: [PATCH 06/55] Working threshold mask and debug on Bloom --- libraries/render-utils/src/BloomEffect.cpp | 31 +++++++++---------- libraries/render-utils/src/BloomThreshold.slf | 26 ++++++++++------ .../render-utils/src/RenderDeferredTask.cpp | 2 +- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index f083bf7e6b..1c62d031b7 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -70,21 +70,20 @@ void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderCo gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); -/* batch.setViewportTransform(halfViewport); + batch.setViewportTransform(halfViewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(inputFrameBuffer->getSize(), args->_viewport)); - batch.setPipeline(_pipeline);*/ + batch.setPipeline(_pipeline); batch.setFramebuffer(_downsampledBuffer); - batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, gpu::Vec4(1.0f, 0.2f, 0.9f, 1.f)); - /*batch.setResourceTexture(COLOR_MAP_SLOT, inputColor); + batch.setResourceTexture(COLOR_MAP_SLOT, inputColor); batch._glUniform1f(THRESHOLD_SLOT, _threshold); batch.draw(gpu::TRIANGLE_STRIP, 4); batch.setViewportTransform(args->_viewport); batch.setResourceTexture(COLOR_MAP_SLOT, nullptr); - batch.setFramebuffer(nullptr);*/ + batch.setFramebuffer(nullptr); }); outputs = _downsampledBuffer; @@ -102,13 +101,14 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In RenderArgs* args = renderContext->args; const auto frameBuffer = inputs.get0(); + const auto framebufferSize = frameBuffer->getSize(); const auto level0FB = inputs.get1(); const gpu::TexturePointer levelTextures[1] = { level0FB->getRenderBuffer(0) }; if (!_pipeline) { - auto vs = gpu::StandardShaderLib::getDrawUnitQuadTexcoordVS(); + auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); @@ -123,19 +123,16 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); - //batch.setFramebuffer(frameBuffer); - batch.setViewportTransform(args->_viewport); + batch.setFramebuffer(frameBuffer); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(glm::ivec2(framebufferSize.x, framebufferSize.y), args->_viewport)); - glm::mat4 projMat; - Transform viewMat; - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat, false); batch.setPipeline(_pipeline); batch.setResourceTexture(0, levelTextures[0]); - batch.draw(gpu::TRIANGLE_STRIP, 4); - - batch.setResourceTexture(0, nullptr); }); } @@ -162,7 +159,9 @@ void Bloom::configure(const Config& config) { void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { const auto halfSizeBuffer = task.addJob("BloomThreshold", inputs); + const auto& input = inputs.get(); + const auto& frameBuffer = input[1]; - const auto debugInput = DebugBloom::Inputs(inputs.get().get1(), halfSizeBuffer).asVarying(); + const auto debugInput = DebugBloom::Inputs(frameBuffer, halfSizeBuffer).asVarying(); task.addJob("DebugBloom", debugInput); } diff --git a/libraries/render-utils/src/BloomThreshold.slf b/libraries/render-utils/src/BloomThreshold.slf index 7c87ed9fcd..dbc16d892d 100644 --- a/libraries/render-utils/src/BloomThreshold.slf +++ b/libraries/render-utils/src/BloomThreshold.slf @@ -22,19 +22,25 @@ void main(void) { vec4 greens = textureGather(colorMap, varTexCoord0, 1); vec4 blues = textureGather(colorMap, varTexCoord0, 2); - float hardness = 8; - vec4 rMask = clamp((reds-threshold) * hardness, 0, 1); - vec4 gMask = clamp((greens-threshold) * hardness, 0, 1); - vec4 bMask = clamp((blues-threshold) * hardness, 0, 1); - - reds = smoothstep(vec4(0,0,0,0), reds, rMask); - greens = smoothstep(vec4(0,0,0,0), greens, gMask); - blues = smoothstep(vec4(0,0,0,0), blues, bMask); - vec3 texel0 = vec3(reds.x, greens.x, blues.x); vec3 texel1 = vec3(reds.y, greens.y, blues.y); vec3 texel2 = vec3(reds.z, greens.z, blues.z); vec3 texel3 = vec3(reds.w, greens.w, blues.w); - outFragColor = vec4((texel0+texel1+texel2+texel3)/4.0, 1.0); + vec4 luminances; + vec3 luminanceWeights = vec3(0.3,0.5,0.2); + + luminances.x = dot(texel0, luminanceWeights); + luminances.y = dot(texel1, luminanceWeights); + luminances.z = dot(texel2, luminanceWeights); + luminances.w = dot(texel0, luminanceWeights); + + float hardness = 8; + vec4 mask = clamp((luminances-threshold) * hardness, 0, 1); + vec3 color; + + color.x = dot(mask, reds); + color.y = dot(mask, greens); + color.z = dot(mask, blues); + outFragColor = vec4(color/4.0, 1.0); } diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index a27b8f0ab5..f2afae7531 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -161,7 +161,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren const auto transparentsInputs = DrawDeferred::Inputs(transparents, lightingModel).asVarying(); task.addJob("DrawTransparentDeferred", transparentsInputs, shapePlumber); - // LIght Cluster Grid Debuging job + // Light Cluster Grid Debuging job { const auto debugLightClustersInputs = DebugLightClusters::Inputs(deferredFrameTransform, deferredFramebuffer, lightingModel, linearDepthTarget, lightClusters).asVarying(); task.addJob("DebugLightClusters", debugLightClustersInputs); From 0d3d309bceb56c4f212e27c7727af301b3fefbfb Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 9 Oct 2017 11:49:29 +0200 Subject: [PATCH 07/55] Quarter size debug rendering of bloom --- libraries/render-utils/src/BloomEffect.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 1c62d031b7..6ec20d53c7 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -108,7 +108,7 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In }; if (!_pipeline) { - auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS(); auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); @@ -128,7 +128,10 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(glm::ivec2(framebufferSize.x, framebufferSize.y), args->_viewport)); + + Transform modelTransform = gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport / 2); + modelTransform.postTranslate(glm::vec3(-1.0f, 1.0f, 0.0f)); + batch.setModelTransform(modelTransform); batch.setPipeline(_pipeline); batch.setResourceTexture(0, levelTextures[0]); From cda48cbf67e539b1fed6a7aa677351b2228d1134 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 9 Oct 2017 15:13:32 +0200 Subject: [PATCH 08/55] Three blurs working --- libraries/render-utils/src/BloomEffect.cpp | 55 ++++++++++++++++------ libraries/render-utils/src/BloomEffect.h | 2 +- libraries/render/src/render/BlurTask.cpp | 20 ++++---- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 6ec20d53c7..e292199bef 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -17,6 +17,8 @@ #include "BloomThreshold_frag.h" +#define BLOOM_BLUR_LEVEL_COUNT 3 + ThresholdAndDownsampleJob::ThresholdAndDownsampleJob() { } @@ -103,8 +105,12 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In const auto frameBuffer = inputs.get0(); const auto framebufferSize = frameBuffer->getSize(); const auto level0FB = inputs.get1(); - const gpu::TexturePointer levelTextures[1] = { - level0FB->getRenderBuffer(0) + const auto level1FB = inputs.get2(); + const auto level2FB = inputs.get3(); + const gpu::TexturePointer levelTextures[BLOOM_BLUR_LEVEL_COUNT] = { + level0FB->getRenderBuffer(0), + level1FB->getRenderBuffer(0), + level2FB->getRenderBuffer(0) }; if (!_pipeline) { @@ -128,27 +134,36 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); + batch.setPipeline(_pipeline); Transform modelTransform = gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport / 2); modelTransform.postTranslate(glm::vec3(-1.0f, 1.0f, 0.0f)); batch.setModelTransform(modelTransform); - - batch.setPipeline(_pipeline); batch.setResourceTexture(0, levelTextures[0]); batch.draw(gpu::TRIANGLE_STRIP, 4); + + modelTransform.postTranslate(glm::vec3(2.0f, 0.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, levelTextures[1]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + modelTransform.postTranslate(glm::vec3(-2.0f, -2.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, levelTextures[2]); + batch.draw(gpu::TRIANGLE_STRIP, 4); }); } void BloomConfig::setIntensity(float value) { - /* auto blurConfig = getConfig(); - blurConfig->setProperty("mix", value*0.5f);*/ } void BloomConfig::setSize(float value) { - /* auto& blurJob = static_cast(_task)->_jobs.front(); - auto& gaussianBlur = blurJob.edit(); - auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f);*/ + for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { + auto& blurJob = static_cast(_task)->_jobs[i+1]; + auto& gaussianBlur = blurJob.edit(); + auto gaussianBlurParams = gaussianBlur.getParameters(); + gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f); + } } Bloom::Bloom() { @@ -156,15 +171,25 @@ Bloom::Bloom() { } void Bloom::configure(const Config& config) { -/* auto blurConfig = config.getConfig(); - blurConfig->setProperty("filterScale", 3.0f);*/ + std::string blurName{ "BloomBlurN" }; + + for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { + blurName.back() = '0' + i; + auto blurConfig = config.getConfig(blurName); + blurConfig->setProperty("filterScale", 3.0f); + } } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - const auto halfSizeBuffer = task.addJob("BloomThreshold", inputs); + const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs); + + // Level 0 blur + const auto blurFB0 = task.addJob("BloomBlur0", bloomInputBuffer); + const auto blurFB1 = task.addJob("BloomBlur1", blurFB0, true); + const auto blurFB2 = task.addJob("BloomBlur2", blurFB1, true); + const auto& input = inputs.get(); const auto& frameBuffer = input[1]; - - const auto debugInput = DebugBloom::Inputs(frameBuffer, halfSizeBuffer).asVarying(); + const auto debugInput = DebugBloom::Inputs(frameBuffer, blurFB0, blurFB1, blurFB2).asVarying(); task.addJob("DebugBloom", debugInput); } diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index ec14a6ad9f..bd74939ea4 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -77,7 +77,7 @@ public: class DebugBloom { public: - using Inputs = render::VaryingSet2; + using Inputs = render::VaryingSet4; using Config = DebugBloomConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 66f098302d..b42bae3950 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -181,7 +181,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra _outputFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat()); }*/ auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - auto blurringTarget = gpu::Texture::create2D(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); + auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); _outputFramebuffer->setRenderBuffer(0, blurringTarget); } @@ -246,13 +246,16 @@ gpu::PipelinePointer BlurGaussian::getBlurHPipeline() { } void BlurGaussian::configure(const Config& config) { - auto blurHPipeline = getBlurHPipeline(); + auto state = getBlurHPipeline()->getState(); _parameters->setFilterRadiusScale(config.filterScale); _parameters->setOutputAlpha(config.mix); - - blurHPipeline->getState()->setBlendFunction(config.mix < 1.0f, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + if (config.mix < 1.0f) { + state->setBlendFunction(config.mix < 1.0f, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + } else { + state->setBlendFunction(false); + } } @@ -271,14 +274,15 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra auto blurVPipeline = getBlurVPipeline(); auto blurHPipeline = getBlurHPipeline(); + glm::ivec4 viewport = { 0, 0, blurredFramebuffer->getWidth(), blurredFramebuffer->getHeight() }; - _parameters->setWidthHeight(args->_viewport.z, args->_viewport.w, args->isStereo()); + _parameters->setWidthHeight(viewport.z, viewport.w, args->isStereo()); glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); - _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, args->_viewport)); + _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, viewport)); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); - batch.setViewportTransform(args->_viewport); + batch.setViewportTransform(viewport); batch.setUniformBuffer(BlurTask_ParamsSlot, _parameters->_parametersBuffer); From 02612653306c4dcb459aa5c40bbe770c1ce7cf4a Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Mon, 9 Oct 2017 19:17:51 +0200 Subject: [PATCH 09/55] Working bloom but still visually unstable with geometry aliasing --- libraries/render-utils/src/BloomApply.slf | 27 +++++ libraries/render-utils/src/BloomEffect.cpp | 109 ++++++++++++++++-- libraries/render-utils/src/BloomEffect.h | 40 ++++++- libraries/render-utils/src/BloomThreshold.slf | 5 +- .../render-utils/src/DeferredFramebuffer.cpp | 4 +- libraries/render/src/render/BlurTask.cpp | 10 +- .../render/src/render/BlurTask_shared.slh | 2 +- libraries/render/src/render/ResampleTask.cpp | 88 ++++++++++++++ libraries/render/src/render/ResampleTask.h | 40 +++++++ libraries/render/src/task/Task.h | 20 ++++ scripts/developer/utilities/render/bloom.qml | 4 +- 11 files changed, 320 insertions(+), 29 deletions(-) create mode 100644 libraries/render-utils/src/BloomApply.slf create mode 100644 libraries/render/src/render/ResampleTask.cpp create mode 100644 libraries/render/src/render/ResampleTask.h diff --git a/libraries/render-utils/src/BloomApply.slf b/libraries/render-utils/src/BloomApply.slf new file mode 100644 index 0000000000..17f13b1187 --- /dev/null +++ b/libraries/render-utils/src/BloomApply.slf @@ -0,0 +1,27 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// BloomApply.slf +// Mix the three gaussian blur textures. +// +// Created by Olivier Prat on 10/09/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 +// + +uniform sampler2D blurMap0; +uniform sampler2D blurMap1; +uniform sampler2D blurMap2; +uniform float intensity; + +in vec2 varTexCoord0; +out vec4 outFragColor; + +void main(void) { + vec4 blur0 = texture(blurMap0, varTexCoord0); + vec4 blur1 = texture(blurMap1, varTexCoord0); + vec4 blur2 = texture(blurMap2, varTexCoord0); + + outFragColor = vec4((blur0.rgb+blur1.rgb+blur2.rgb)/3.0, intensity); +} diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index e292199bef..f289f59faa 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -14,8 +14,10 @@ #include "gpu/StandardShaderLib.h" #include +#include #include "BloomThreshold_frag.h" +#include "BloomApply_frag.h" #define BLOOM_BLUR_LEVEL_COUNT 3 @@ -46,9 +48,9 @@ void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderCo if (!_downsampledBuffer || _downsampledBuffer->getSize().x != halfSize.x || _downsampledBuffer->getSize().y != halfSize.y) { auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputColor->getTexelFormat(), halfSize.x, halfSize.y, - gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_POINT_MAG_LINEAR))); + gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); - _downsampledBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomBlur0")); + _downsampledBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold")); _downsampledBuffer->setRenderBuffer(0, colorTexture); } @@ -91,6 +93,67 @@ void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderCo outputs = _downsampledBuffer; } +BloomApply::BloomApply() { + +} + +void BloomApply::configure(const Config& config) { + _intensity = config.intensity; +} + +void BloomApply::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + RenderArgs* args = renderContext->args; + + static auto BLUR0_SLOT = 0; + static auto BLUR1_SLOT = 1; + static auto BLUR2_SLOT = 2; + static auto INTENSITY_SLOT = 3; + + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS(); + auto ps = gpu::Shader::createPixel(std::string(BloomApply_frag)); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding("blurMap0", BLUR0_SLOT)); + slotBindings.insert(gpu::Shader::Binding("blurMap1", BLUR1_SLOT)); + slotBindings.insert(gpu::Shader::Binding("blurMap2", BLUR2_SLOT)); + slotBindings.insert(gpu::Shader::Binding("intensity", INTENSITY_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _pipeline = gpu::Pipeline::create(program, state); + } + + const auto frameBuffer = inputs.get0(); + const auto framebufferSize = frameBuffer->getSize(); + const auto blur0FB = inputs.get1(); + const auto blur1FB = inputs.get2(); + const auto blur2FB = inputs.get3(); + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + + batch.setFramebuffer(frameBuffer); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setPipeline(_pipeline); + + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); + batch.setResourceTexture(BLUR0_SLOT, blur0FB->getRenderBuffer(0)); + batch.setResourceTexture(BLUR1_SLOT, blur1FB->getRenderBuffer(0)); + batch.setResourceTexture(BLUR2_SLOT, blur2FB->getRenderBuffer(0)); + batch._glUniform1f(INTENSITY_SLOT, _intensity); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); +} + DebugBloom::DebugBloom() { } @@ -155,14 +218,34 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In } void BloomConfig::setIntensity(float value) { + auto task = static_cast(_task); + auto blurJobIt = task->editJob("BloomApply"); + assert(blurJobIt != task->_jobs.end()); + blurJobIt->getConfiguration()->setProperty("intensity", value); +} + +float BloomConfig::getIntensity() const { + auto task = static_cast(_task); + auto blurJobIt = task->getJob("BloomApply"); + assert(blurJobIt != task->_jobs.end()); + return blurJobIt->getConfiguration()->property("intensity").toFloat(); } void BloomConfig::setSize(float value) { + std::string blurName{ "BloomBlurN" }; + auto sigma = value*3.0f; + for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { - auto& blurJob = static_cast(_task)->_jobs[i+1]; - auto& gaussianBlur = blurJob.edit(); + blurName.back() = '0' + i; + auto task = static_cast(_task); + auto blurJobIt = task->editJob(blurName); + assert(blurJobIt != task->_jobs.end()); + auto& gaussianBlur = blurJobIt->edit(); auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, value*7.0f); + gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, sigma); + // Gaussian blur increases at each level to have a slower rolloff on the edge + // of the response + sigma *= 1.5f; } } @@ -176,20 +259,24 @@ void Bloom::configure(const Config& config) { for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { blurName.back() = '0' + i; auto blurConfig = config.getConfig(blurName); - blurConfig->setProperty("filterScale", 3.0f); + blurConfig->setProperty("filterScale", 1.0f); } } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs); - // Level 0 blur + // Multi-scale blur const auto blurFB0 = task.addJob("BloomBlur0", bloomInputBuffer); - const auto blurFB1 = task.addJob("BloomBlur1", blurFB0, true); - const auto blurFB2 = task.addJob("BloomBlur2", blurFB1, true); + const auto halfBlurFB0 = task.addJob("BloomHalfBlur0", blurFB0); + const auto blurFB1 = task.addJob("BloomBlur1", halfBlurFB0, true); + const auto halfBlurFB1 = task.addJob("BloomHalfBlur1", blurFB1); + const auto blurFB2 = task.addJob("BloomBlur2", halfBlurFB1, true); const auto& input = inputs.get(); const auto& frameBuffer = input[1]; - const auto debugInput = DebugBloom::Inputs(frameBuffer, blurFB0, blurFB1, blurFB2).asVarying(); - task.addJob("DebugBloom", debugInput); + + const auto applyInput = DebugBloom::Inputs(frameBuffer, blurFB0, blurFB1, blurFB2).asVarying(); + task.addJob("BloomApply", applyInput); + task.addJob("DebugBloom", applyInput); } diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index bd74939ea4..7c99555bd3 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -18,17 +18,17 @@ class BloomConfig : public render::Task::Config { Q_OBJECT - Q_PROPERTY(float intensity MEMBER intensity WRITE setIntensity NOTIFY dirty) + Q_PROPERTY(float intensity READ getIntensity WRITE setIntensity NOTIFY dirty) Q_PROPERTY(float size MEMBER size WRITE setSize NOTIFY dirty) public: BloomConfig() : render::Task::Config(true) {} - float intensity{ 0.2f }; - float size{ 0.4f }; + float size{ 0.45f }; void setIntensity(float value); + float getIntensity() const; void setSize(float value); signals: @@ -41,7 +41,7 @@ class ThresholdConfig : public render::Job::Config { public: - float threshold{ 0.25f }; + float threshold{ 1.25f }; signals: void dirty(); @@ -66,12 +66,42 @@ private: float _threshold; }; + +class BloomApplyConfig : public render::Job::Config { + Q_OBJECT + Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty) + +public: + + float intensity{ 0.5f }; + +signals: + void dirty(); +}; + +class BloomApply { +public: + using Inputs = render::VaryingSet4; + using Config = BloomApplyConfig; + using JobModel = render::Job::ModelI; + + BloomApply(); + + void configure(const Config& config); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + +private: + + gpu::PipelinePointer _pipeline; + float _intensity{ 1.0f }; +}; + class DebugBloomConfig : public render::Job::Config { Q_OBJECT public: - DebugBloomConfig() : render::Job::Config(true) {} + DebugBloomConfig() : render::Job::Config(false) {} }; diff --git a/libraries/render-utils/src/BloomThreshold.slf b/libraries/render-utils/src/BloomThreshold.slf index dbc16d892d..d14da4889d 100644 --- a/libraries/render-utils/src/BloomThreshold.slf +++ b/libraries/render-utils/src/BloomThreshold.slf @@ -28,15 +28,14 @@ void main(void) { vec3 texel3 = vec3(reds.w, greens.w, blues.w); vec4 luminances; - vec3 luminanceWeights = vec3(0.3,0.5,0.2); + vec3 luminanceWeights = vec3(0.333,0.333,0.333); luminances.x = dot(texel0, luminanceWeights); luminances.y = dot(texel1, luminanceWeights); luminances.z = dot(texel2, luminanceWeights); luminances.w = dot(texel0, luminanceWeights); - float hardness = 8; - vec4 mask = clamp((luminances-threshold) * hardness, 0, 1); + vec4 mask = clamp(luminances-threshold, 0, 1); vec3 color; color.x = dot(mask, reds); diff --git a/libraries/render-utils/src/DeferredFramebuffer.cpp b/libraries/render-utils/src/DeferredFramebuffer.cpp index 64ea8f0342..2df89b8808 100644 --- a/libraries/render-utils/src/DeferredFramebuffer.cpp +++ b/libraries/render-utils/src/DeferredFramebuffer.cpp @@ -73,9 +73,9 @@ void DeferredFramebuffer::allocate() { _deferredFramebufferDepthColor->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); - auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR); + auto smoothSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - _lightingTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, gpu::Texture::SINGLE_MIP, defaultSampler); + _lightingTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::R11G11B10), width, height, gpu::Texture::SINGLE_MIP, smoothSampler); _lightingFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("lighting")); _lightingFramebuffer->setRenderBuffer(0, _lightingTexture); _lightingFramebuffer->setDepthStencilBuffer(_primaryDepthTexture, depthFormat); diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index b42bae3950..a200e0c8ec 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -48,10 +48,10 @@ void BlurParams::setWidthHeight(int width, int height, bool isStereo) { } } -void BlurParams::setTexcoordTransform(const glm::vec4 texcoordTransformViewport) { - auto texcoordTransform = _parametersBuffer.get().texcoordTransform; - if (texcoordTransformViewport != texcoordTransform) { - _parametersBuffer.edit().texcoordTransform = texcoordTransform; +void BlurParams::setTexcoordTransform(glm::vec4 texcoordTransformViewport) { + auto& params = _parametersBuffer.get(); + if (texcoordTransformViewport != params.texcoordTransform) { + _parametersBuffer.edit().texcoordTransform = texcoordTransformViewport; } } @@ -274,7 +274,7 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra auto blurVPipeline = getBlurVPipeline(); auto blurHPipeline = getBlurHPipeline(); - glm::ivec4 viewport = { 0, 0, blurredFramebuffer->getWidth(), blurredFramebuffer->getHeight() }; + glm::ivec4 viewport { 0, 0, blurredFramebuffer->getWidth(), blurredFramebuffer->getHeight() }; _parameters->setWidthHeight(viewport.z, viewport.w, args->isStereo()); glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); diff --git a/libraries/render/src/render/BlurTask_shared.slh b/libraries/render/src/render/BlurTask_shared.slh index 84c633d74c..beca32c1be 100644 --- a/libraries/render/src/render/BlurTask_shared.slh +++ b/libraries/render/src/render/BlurTask_shared.slh @@ -7,4 +7,4 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#define BLUR_MAX_NUM_TAPS 25 +#define BLUR_MAX_NUM_TAPS 33 diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp new file mode 100644 index 0000000000..5d4b5c18cb --- /dev/null +++ b/libraries/render/src/render/ResampleTask.cpp @@ -0,0 +1,88 @@ +// +// ResampleTask.cpp +// render/src/render +// +// Various to upsample or downsample textures into framebuffers. +// +// Created by Olivier Prat on 10/09/17. +// 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 +// +#include "ResampleTask.h" + +#include "gpu/Context.h" +#include "gpu/StandardShaderLib.h" + +using namespace render; + +HalfDownsample::HalfDownsample() { + +} + +void HalfDownsample::configure(const Config& config) { + +} + +gpu::FramebufferPointer HalfDownsample::getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer) { + auto resampledFramebufferSize = sourceFramebuffer->getSize(); + + resampledFramebufferSize.x /= 2U; + resampledFramebufferSize.y /= 2U; + + if (!_destinationFrameBuffer || resampledFramebufferSize != _destinationFrameBuffer->getSize()) { + _destinationFrameBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("HalfOutput")); + + auto sampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); + auto target = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), resampledFramebufferSize.x, resampledFramebufferSize.y, gpu::Texture::SINGLE_MIP, sampler); + _destinationFrameBuffer->setRenderBuffer(0, target); + } + return _destinationFrameBuffer; +} + +void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& resampledFrameBuffer) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + RenderArgs* args = renderContext->args; + + resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer); + + static auto TEXCOORD_RECT_SLOT = 1; + + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS(); + auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("texcoordRect"), TEXCOORD_RECT_SLOT)); + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(false)); + _pipeline = gpu::Pipeline::create(program, state); + } + + const auto sourceSize = sourceFramebuffer->getSize(); + const auto bufferSize = resampledFrameBuffer->getSize(); + glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + + batch.setFramebuffer(resampledFrameBuffer); + + batch.setViewportTransform(viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setPipeline(_pipeline); + + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport)); + batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0)); + // Add half a texel of offset to be sure to sample in the middle of 4 neighbouring texture pixels + // to perform box filtering. + batch._glUniform4f(TEXCOORD_RECT_SLOT, 0.5f / sourceSize.x, 0.5f / sourceSize.y, 1.f, 1.f); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); +} diff --git a/libraries/render/src/render/ResampleTask.h b/libraries/render/src/render/ResampleTask.h new file mode 100644 index 0000000000..70cb9a54bb --- /dev/null +++ b/libraries/render/src/render/ResampleTask.h @@ -0,0 +1,40 @@ +// +// ResampleTask.h +// render/src/render +// +// Various to upsample or downsample textures into framebuffers. +// +// Created by Olivier Prat on 10/09/17. +// 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 +// + +#ifndef hifi_render_ResampleTask_h +#define hifi_render_ResampleTask_h + +#include "Engine.h" + +namespace render { + + class HalfDownsample { + public: + using Config = JobConfig; + using JobModel = Job::ModelIO; + + HalfDownsample(); + + void configure(const Config& config); + void run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& resampledFrameBuffer); + + protected: + + gpu::PipelinePointer _pipeline; + gpu::FramebufferPointer _destinationFrameBuffer; + + gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer); + }; +} + +#endif // hifi_render_ResampleTask_h diff --git a/libraries/render/src/task/Task.h b/libraries/render/src/task/Task.h index e99b33305c..0f2265b396 100644 --- a/libraries/render/src/task/Task.h +++ b/libraries/render/src/task/Task.h @@ -171,6 +171,8 @@ public: _concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0); } + const std::string& getName() const { return _name; } + protected: ConceptPointer _concept; std::string _name = ""; @@ -206,6 +208,24 @@ public: const Varying getInput() const override { return _input; } const Varying getOutput() const override { return _output; } + typename Jobs::iterator editJob(std::string name) { + typename Jobs::iterator jobIt; + for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) { + if (jobIt->getName() == name) { + return jobIt; + } + } + return jobIt; + } + typename Jobs::const_iterator getJob(std::string name) const { + typename Jobs::const_iterator jobIt; + for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) { + if (jobIt->getName() == name) { + return jobIt; + } + } + return jobIt; + } TaskConcept(const Varying& input, QConfigPointer config) : Concept(config), _input(input) {} diff --git a/scripts/developer/utilities/render/bloom.qml b/scripts/developer/utilities/render/bloom.qml index 7deeffc218..d2a928861c 100644 --- a/scripts/developer/utilities/render/bloom.qml +++ b/scripts/developer/utilities/render/bloom.qml @@ -40,7 +40,7 @@ Item { integral: false config: root.config property: "intensity" - max: 1.0 + max: 5.0 min: 0.0 width: 280 } @@ -58,7 +58,7 @@ Item { integral: false config: root.configThreshold property: "threshold" - max: 1.0 + max: 2.0 min: 0.0 width: 280 } From 76305c5285f6d33e100460677d9549652e8f9c2f Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 10 Oct 2017 14:49:04 +0200 Subject: [PATCH 10/55] Better debugging options for bloom --- libraries/render-utils/src/BloomEffect.cpp | 53 +++++++++++----- libraries/render-utils/src/BloomEffect.h | 18 +++++- scripts/developer/utilities/render/bloom.qml | 63 ++++++++++++++++++-- 3 files changed, 112 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index f289f59faa..c6c30e7ff6 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -157,7 +157,9 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In DebugBloom::DebugBloom() { } -DebugBloom::~DebugBloom() { +void DebugBloom::configure(const Config& config) { + _mode = static_cast(config.mode); + assert(_mode < DebugBloomConfig::MODE_COUNT); } void DebugBloom::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { @@ -176,12 +178,15 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In level2FB->getRenderBuffer(0) }; + static auto TEXCOORD_RECT_SLOT = 1; + if (!_pipeline) { - auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS(); + auto vs = gpu::StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS(); auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("texcoordRect"), TEXCOORD_RECT_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -199,21 +204,39 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In batch.resetViewTransform(); batch.setPipeline(_pipeline); - Transform modelTransform = gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport / 2); - modelTransform.postTranslate(glm::vec3(-1.0f, 1.0f, 0.0f)); - batch.setModelTransform(modelTransform); - batch.setResourceTexture(0, levelTextures[0]); - batch.draw(gpu::TRIANGLE_STRIP, 4); + Transform modelTransform; + if (_mode == DebugBloomConfig::MODE_ALL_LEVELS) { + batch._glUniform4f(TEXCOORD_RECT_SLOT, 0.0f, 0.0f, 1.f, 1.f); - modelTransform.postTranslate(glm::vec3(2.0f, 0.0f, 0.0f)); - batch.setModelTransform(modelTransform); - batch.setResourceTexture(0, levelTextures[1]); - batch.draw(gpu::TRIANGLE_STRIP, 4); + modelTransform = gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport / 2); + modelTransform.postTranslate(glm::vec3(-1.0f, 1.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, levelTextures[0]); + batch.draw(gpu::TRIANGLE_STRIP, 4); - modelTransform.postTranslate(glm::vec3(-2.0f, -2.0f, 0.0f)); - batch.setModelTransform(modelTransform); - batch.setResourceTexture(0, levelTextures[2]); - batch.draw(gpu::TRIANGLE_STRIP, 4); + modelTransform.postTranslate(glm::vec3(2.0f, 0.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, levelTextures[1]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + modelTransform.postTranslate(glm::vec3(-2.0f, -2.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, levelTextures[2]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } else { + auto viewport = args->_viewport; + auto blurLevel = _mode - DebugBloomConfig::MODE_LEVEL0; + + viewport.z /= 2; + + batch._glUniform4f(TEXCOORD_RECT_SLOT, 0.5f, 0.0f, 0.5f, 1.f); + + modelTransform = gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, viewport); + modelTransform.postTranslate(glm::vec3(-1.0f, 0.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, levelTextures[blurLevel]); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } }); } diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 7c99555bd3..637e37aa04 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -98,11 +98,25 @@ private: class DebugBloomConfig : public render::Job::Config { Q_OBJECT + Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) public: + enum Mode { + MODE_LEVEL0 = 0, + MODE_LEVEL1, + MODE_LEVEL2, + MODE_ALL_LEVELS, + + MODE_COUNT + }; + DebugBloomConfig() : render::Job::Config(false) {} + int mode{ MODE_ALL_LEVELS }; + +signals: + void dirty(); }; class DebugBloom { @@ -112,13 +126,13 @@ public: using JobModel = render::Job::ModelI; DebugBloom(); - ~DebugBloom(); - void configure(const Config& config) {} + void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); private: gpu::PipelinePointer _pipeline; + DebugBloomConfig::Mode _mode; }; class Bloom { diff --git a/scripts/developer/utilities/render/bloom.qml b/scripts/developer/utilities/render/bloom.qml index d2a928861c..66e92e0eff 100644 --- a/scripts/developer/utilities/render/bloom.qml +++ b/scripts/developer/utilities/render/bloom.qml @@ -28,11 +28,64 @@ Item { root.config["enabled"] = checked; } } - CheckBox { - text: "Debug" - checked: root.configDebug["enabled"] - onCheckedChanged: { - root.configDebug["enabled"] = checked; + GroupBox { + title: "Debug" + Row { + ExclusiveGroup { id: debugGroup } + RadioButton { + text : "Off" + checked : !root.configDebug["enabled"] + onCheckedChanged: { + if (checked) { + root.configDebug["enabled"] = false + } + } + exclusiveGroup : debugGroup + } + RadioButton { + text : "Lvl 0" + checked :root.configDebug["enabled"] && root.configDebug["mode"]==0 + onCheckedChanged: { + if (checked) { + root.configDebug["enabled"] = true + root.configDebug["mode"] = 0 + } + } + exclusiveGroup : debugGroup + } + RadioButton { + text : "Lvl 1" + checked : root.configDebug["enabled"] && root.configDebug["mode"]==1 + onCheckedChanged: { + if (checked) { + root.configDebug["enabled"] = true + root.configDebug["mode"] = 1 + } + } + exclusiveGroup : debugGroup + } + RadioButton { + text : "Lvl 2" + checked : root.configDebug["enabled"] && root.configDebug["mode"]==2 + onCheckedChanged: { + if (checked) { + root.configDebug["enabled"] = true + root.configDebug["mode"] = 2 + } + } + exclusiveGroup : debugGroup + } + RadioButton { + text : "All" + checked : root.configDebug["enabled"] && root.configDebug["mode"]==3 + onCheckedChanged: { + if (checked) { + root.configDebug["enabled"] = true + root.configDebug["mode"] = 3 + } + } + exclusiveGroup : debugGroup + } } } ConfigSlider { From f55d44dfc33e0b48431ef41ea84ce5edd6fcba71 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 10 Oct 2017 17:49:35 +0200 Subject: [PATCH 11/55] Threshold now doesn't downsample anymore. Done in separate pass --- libraries/render-utils/src/BloomEffect.cpp | 53 +++++++++++-------- libraries/render-utils/src/BloomEffect.h | 16 +++--- libraries/render-utils/src/BloomThreshold.slf | 28 ++-------- libraries/render/src/render/ResampleTask.cpp | 8 +-- 4 files changed, 44 insertions(+), 61 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index c6c30e7ff6..e236b290c2 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -21,15 +21,15 @@ #define BLOOM_BLUR_LEVEL_COUNT 3 -ThresholdAndDownsampleJob::ThresholdAndDownsampleJob() { +BloomThreshold::BloomThreshold() { } -void ThresholdAndDownsampleJob::configure(const Config& config) { +void BloomThreshold::configure(const Config& config) { _threshold = config.threshold; } -void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { +void BloomThreshold::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -40,25 +40,23 @@ void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderCo assert(inputFrameBuffer->hasColor()); - auto inputColor = inputFrameBuffer->getRenderBuffer(0); + auto inputBuffer = inputFrameBuffer->getRenderBuffer(0); auto sourceViewport = args->_viewport; - auto fullSize = glm::ivec2(inputColor->getDimensions()); - auto halfSize = fullSize / 2; - auto halfViewport = args->_viewport >> 1; + auto bufferSize = glm::ivec2(inputBuffer->getDimensions()); - if (!_downsampledBuffer || _downsampledBuffer->getSize().x != halfSize.x || _downsampledBuffer->getSize().y != halfSize.y) { - auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputColor->getTexelFormat(), halfSize.x, halfSize.y, + if (!_outputBuffer || _outputBuffer->getSize() != inputFrameBuffer->getSize()) { + auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputBuffer->getTexelFormat(), bufferSize.x, bufferSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); - _downsampledBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold")); - _downsampledBuffer->setRenderBuffer(0, colorTexture); + _outputBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold")); + _outputBuffer->setRenderBuffer(0, colorTexture); } static const int COLOR_MAP_SLOT = 0; static const int THRESHOLD_SLOT = 1; if (!_pipeline) { - auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS(); + auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS(); auto ps = gpu::Shader::createPixel(std::string(BloomThreshold_frag)); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); @@ -74,23 +72,19 @@ void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderCo gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); - batch.setViewportTransform(halfViewport); + batch.setViewportTransform(args->_viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(inputFrameBuffer->getSize(), args->_viewport)); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, args->_viewport)); batch.setPipeline(_pipeline); - batch.setFramebuffer(_downsampledBuffer); - batch.setResourceTexture(COLOR_MAP_SLOT, inputColor); + batch.setFramebuffer(_outputBuffer); + batch.setResourceTexture(COLOR_MAP_SLOT, inputBuffer); batch._glUniform1f(THRESHOLD_SLOT, _threshold); batch.draw(gpu::TRIANGLE_STRIP, 4); - - batch.setViewportTransform(args->_viewport); - batch.setResourceTexture(COLOR_MAP_SLOT, nullptr); - batch.setFramebuffer(nullptr); }); - outputs = _downsampledBuffer; + outputs = _outputBuffer; } BloomApply::BloomApply() { @@ -287,14 +281,27 @@ void Bloom::configure(const Config& config) { } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs); + const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs); + const auto bloomHalfInputBuffer = task.addJob("BloomHalf", bloomInputBuffer); + const auto bloomQuarterInputBuffer = task.addJob("BloomQuarter", bloomHalfInputBuffer); +#if 1 // Multi-scale blur - const auto blurFB0 = task.addJob("BloomBlur0", bloomInputBuffer); + const auto blurFB0 = task.addJob("BloomBlur0", bloomQuarterInputBuffer); const auto halfBlurFB0 = task.addJob("BloomHalfBlur0", blurFB0); const auto blurFB1 = task.addJob("BloomBlur1", halfBlurFB0, true); const auto halfBlurFB1 = task.addJob("BloomHalfBlur1", blurFB1); const auto blurFB2 = task.addJob("BloomBlur2", halfBlurFB1, true); +#else + // Multi-scale downsampling debug + const auto blurFB0 = bloomQuarterInputBuffer; + const auto blurFB1 = task.addJob("BloomHalfBlur1", blurFB0); + const auto blurFB2 = task.addJob("BloomHalfBlur2", blurFB1); + // This is only needed so as not to crash as we expect to have the three blur jobs + task.addJob("BloomBlur0", bloomHalfInputBuffer, true); + task.addJob("BloomBlur1", blurFB1, true); + task.addJob("BloomBlur2", blurFB2, true); +#endif const auto& input = inputs.get(); const auto& frameBuffer = input[1]; diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 637e37aa04..fdc2d1a0ba 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -25,7 +25,7 @@ public: BloomConfig() : render::Task::Config(true) {} - float size{ 0.45f }; + float size{ 0.8f }; void setIntensity(float value); float getIntensity() const; @@ -35,7 +35,7 @@ signals: void dirty(); }; -class ThresholdConfig : public render::Job::Config { +class BloomThresholdConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty) @@ -47,21 +47,21 @@ signals: void dirty(); }; -class ThresholdAndDownsampleJob { +class BloomThreshold { public: using Inputs = render::VaryingSet2; using Outputs = gpu::FramebufferPointer; - using Config = ThresholdConfig; - using JobModel = render::Job::ModelIO; + using Config = BloomThresholdConfig; + using JobModel = render::Job::ModelIO; - ThresholdAndDownsampleJob(); + BloomThreshold(); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); private: - gpu::FramebufferPointer _downsampledBuffer; + gpu::FramebufferPointer _outputBuffer; gpu::PipelinePointer _pipeline; float _threshold; }; @@ -73,7 +73,7 @@ class BloomApplyConfig : public render::Job::Config { public: - float intensity{ 0.5f }; + float intensity{ 0.8f }; signals: void dirty(); diff --git a/libraries/render-utils/src/BloomThreshold.slf b/libraries/render-utils/src/BloomThreshold.slf index d14da4889d..14d20dd684 100644 --- a/libraries/render-utils/src/BloomThreshold.slf +++ b/libraries/render-utils/src/BloomThreshold.slf @@ -17,29 +17,11 @@ in vec2 varTexCoord0; out vec4 outFragColor; void main(void) { - // Gather 2 by 2 quads from texture, threshold and downsample - vec4 reds = textureGather(colorMap, varTexCoord0, 0); - vec4 greens = textureGather(colorMap, varTexCoord0, 1); - vec4 blues = textureGather(colorMap, varTexCoord0, 2); + vec4 color = texture(colorMap, varTexCoord0); + float luminance = (color.r+color.g+color.b) / 3.0; + float mask = clamp((luminance-threshold)*0.25, 0, 1); - vec3 texel0 = vec3(reds.x, greens.x, blues.x); - vec3 texel1 = vec3(reds.y, greens.y, blues.y); - vec3 texel2 = vec3(reds.z, greens.z, blues.z); - vec3 texel3 = vec3(reds.w, greens.w, blues.w); + color *= mask; - vec4 luminances; - vec3 luminanceWeights = vec3(0.333,0.333,0.333); - - luminances.x = dot(texel0, luminanceWeights); - luminances.y = dot(texel1, luminanceWeights); - luminances.z = dot(texel2, luminanceWeights); - luminances.w = dot(texel0, luminanceWeights); - - vec4 mask = clamp(luminances-threshold, 0, 1); - vec3 color; - - color.x = dot(mask, reds); - color.y = dot(mask, greens); - color.z = dot(mask, blues); - outFragColor = vec4(color/4.0, 1.0); + outFragColor = vec4(color.rgb, 1.0); } diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index 5d4b5c18cb..ef75b54094 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -48,15 +48,12 @@ void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::F resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer); - static auto TEXCOORD_RECT_SLOT = 1; - if (!_pipeline) { - auto vs = gpu::StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS(); + auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS(); auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("texcoordRect"), TEXCOORD_RECT_SLOT)); gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); @@ -80,9 +77,6 @@ void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::F batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport)); batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0)); - // Add half a texel of offset to be sure to sample in the middle of 4 neighbouring texture pixels - // to perform box filtering. - batch._glUniform4f(TEXCOORD_RECT_SLOT, 0.5f / sourceSize.x, 0.5f / sourceSize.y, 1.f, 1.f); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } From d3add89b3c3a8b0cc88f589a55131c269535dccc Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 10 Oct 2017 18:28:42 +0200 Subject: [PATCH 12/55] Adjusted bloom size range --- libraries/render-utils/src/BloomEffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index e236b290c2..239508cd50 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -250,7 +250,7 @@ float BloomConfig::getIntensity() const { void BloomConfig::setSize(float value) { std::string blurName{ "BloomBlurN" }; - auto sigma = value*3.0f; + auto sigma = 0.5f+value*3.5f; for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { blurName.back() = '0' + i; From 055270df9c6bec1d20b97f4f9df0b2bee44d829b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 12 Oct 2017 19:26:05 +0200 Subject: [PATCH 13/55] Removed compilation warnings on Mac and Ubuntu --- libraries/render-utils/src/BloomEffect.cpp | 1 - libraries/render/src/render/BlurTask.cpp | 2 +- libraries/render/src/render/ResampleTask.cpp | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 239508cd50..69bc790c59 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -41,7 +41,6 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons assert(inputFrameBuffer->hasColor()); auto inputBuffer = inputFrameBuffer->getRenderBuffer(0); - auto sourceViewport = args->_viewport; auto bufferSize = glm::ivec2(inputBuffer->getDimensions()); if (!_outputBuffer || _outputBuffer->getSize() != inputFrameBuffer->getSize()) { diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index a200e0c8ec..5b759ca33c 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -82,7 +82,7 @@ void BlurParams::setFilterGaussianTaps(int numHalfTaps, float sigma) { const int numTaps = 2 * numHalfTaps + 1; assert(numTaps <= BLUR_MAX_NUM_TAPS); assert(sigma > 0.0f); - const float inverseTwoSigmaSquared = float(0.5 / (sigma*sigma)); + const float inverseTwoSigmaSquared = float(0.5 / double(sigma*sigma)); float totalWeight = 1.0f; float weight; float offset; diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index ef75b54094..929db50c31 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -61,7 +61,6 @@ void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::F _pipeline = gpu::Pipeline::create(program, state); } - const auto sourceSize = sourceFramebuffer->getSize(); const auto bufferSize = resampledFrameBuffer->getSize(); glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; From ae8a9e68c8229c48645dd96f5a9424b217526dd1 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 25 Oct 2017 11:58:16 +0200 Subject: [PATCH 14/55] Added debug tool to view shadow & view frustums --- .gitignore | 3 + libraries/gpu/src/gpu/DrawColor.slf | 19 ++++ libraries/gpu/src/gpu/StandardShaderLib.cpp | 9 ++ libraries/gpu/src/gpu/StandardShaderLib.h | 2 + .../render-utils/src/RenderDeferredTask.cpp | 86 +++++++++++++++++++ .../render-utils/src/RenderDeferredTask.h | 34 ++++++++ .../developer/utilities/render/debugShadow.js | 20 +++++ scripts/developer/utilities/render/shadow.qml | 46 ++++++++++ 8 files changed, 219 insertions(+) create mode 100644 libraries/gpu/src/gpu/DrawColor.slf create mode 100644 scripts/developer/utilities/render/debugShadow.js create mode 100644 scripts/developer/utilities/render/shadow.qml diff --git a/.gitignore b/.gitignore index 072e6001da..f085b676e4 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,9 @@ gvr-interface/libs/* TAGS *.sw[po] +# ignore QML compilation output +*.qmlc + # ignore node files for the console node_modules npm-debug.log diff --git a/libraries/gpu/src/gpu/DrawColor.slf b/libraries/gpu/src/gpu/DrawColor.slf new file mode 100644 index 0000000000..c24d69d29f --- /dev/null +++ b/libraries/gpu/src/gpu/DrawColor.slf @@ -0,0 +1,19 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// Draw with color uniform +// +// Created by Olivier Prat on 25/10/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 +// +uniform vec4 color; + +out vec4 outFragColor; + +void main(void) { + outFragColor = color; +} diff --git a/libraries/gpu/src/gpu/StandardShaderLib.cpp b/libraries/gpu/src/gpu/StandardShaderLib.cpp index 7143242618..0d8d131e0b 100755 --- a/libraries/gpu/src/gpu/StandardShaderLib.cpp +++ b/libraries/gpu/src/gpu/StandardShaderLib.cpp @@ -22,6 +22,7 @@ const char DrawNada_frag[] = "void main(void) {}"; // DrawNada is really simple... #include "DrawWhite_frag.h" +#include "DrawColor_frag.h" #include "DrawTexture_frag.h" #include "DrawTextureMirroredX_frag.h" #include "DrawTextureOpaque_frag.h" @@ -37,6 +38,7 @@ ShaderPointer StandardShaderLib::_drawVertexPositionVS; ShaderPointer StandardShaderLib::_drawTransformVertexPositionVS; ShaderPointer StandardShaderLib::_drawNadaPS; ShaderPointer StandardShaderLib::_drawWhitePS; +ShaderPointer StandardShaderLib::_drawColorPS; ShaderPointer StandardShaderLib::_drawTexturePS; ShaderPointer StandardShaderLib::_drawTextureMirroredXPS; ShaderPointer StandardShaderLib::_drawTextureOpaquePS; @@ -125,6 +127,13 @@ ShaderPointer StandardShaderLib::getDrawWhitePS() { return _drawWhitePS; } +ShaderPointer StandardShaderLib::getDrawColorPS() { + if (!_drawColorPS) { + _drawColorPS = gpu::Shader::createPixel(std::string(DrawColor_frag)); + } + return _drawColorPS; +} + ShaderPointer StandardShaderLib::getDrawTexturePS() { if (!_drawTexturePS) { _drawTexturePS = gpu::Shader::createPixel(std::string(DrawTexture_frag)); diff --git a/libraries/gpu/src/gpu/StandardShaderLib.h b/libraries/gpu/src/gpu/StandardShaderLib.h index 94885b8ca0..9c11f6cc3a 100755 --- a/libraries/gpu/src/gpu/StandardShaderLib.h +++ b/libraries/gpu/src/gpu/StandardShaderLib.h @@ -46,6 +46,7 @@ public: static ShaderPointer getDrawNadaPS(); static ShaderPointer getDrawWhitePS(); + static ShaderPointer getDrawColorPS(); static ShaderPointer getDrawTexturePS(); static ShaderPointer getDrawTextureMirroredXPS(); static ShaderPointer getDrawTextureOpaquePS(); @@ -67,6 +68,7 @@ protected: static ShaderPointer _drawNadaPS; static ShaderPointer _drawWhitePS; + static ShaderPointer _drawColorPS; static ShaderPointer _drawTexturePS; static ShaderPointer _drawTextureMirroredXPS; static ShaderPointer _drawTextureOpaquePS; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 6a3b560167..75af8506a2 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -190,6 +190,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawLightBounds", lights); task.addJob("DrawZones", zones); + task.addJob("DrawFrustums"); } // Layered Overlays @@ -516,3 +517,88 @@ 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) { + 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); + } + + if (_updateFrustums) { + updateFrustum(args->getViewFrustum(), _viewFrustumMeshVertices); + + auto lightStage = renderContext->_scene->getStage(); + assert(lightStage); + + const auto globalShadow = lightStage->getCurrentKeyShadow(); + if (globalShadow) { + updateFrustum(*globalShadow->getFrustum(), _shadowFrustumMeshVertices); + } + } + + 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 452420589b..e8dd22359d 100644 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -170,6 +170,40 @@ 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) +public: + + DrawFrustumsConfig(bool enabled = false) : JobConfig(enabled) {} + + bool isFrozen{ false }; +signals: + void dirty(); + +}; + +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); +}; + class RenderDeferredTaskConfig : public render::Task::Config { Q_OBJECT Q_PROPERTY(float fadeScale MEMBER fadeScale NOTIFY dirty) diff --git a/scripts/developer/utilities/render/debugShadow.js b/scripts/developer/utilities/render/debugShadow.js new file mode 100644 index 0000000000..a0d2142258 --- /dev/null +++ b/scripts/developer/utilities/render/debugShadow.js @@ -0,0 +1,20 @@ +// +// debugShadow.js +// developer/utilities/render +// +// Olivier Prat, created on 10/25/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 +// + +// Set up the qml ui +var qml = Script.resolvePath('shadow.qml'); +var window = new OverlayWindow({ + title: 'Shadow Debug', + source: qml, + width: 200, + height: 90 +}); +window.closed.connect(function() { Script.stop(); }); \ No newline at end of file diff --git a/scripts/developer/utilities/render/shadow.qml b/scripts/developer/utilities/render/shadow.qml new file mode 100644 index 0000000000..1b4e647c77 --- /dev/null +++ b/scripts/developer/utilities/render/shadow.qml @@ -0,0 +1,46 @@ +// +// shadow.qml +// developer/utilities/render +// +// Olivier Prat, created on 10/25/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Column { + id: root + spacing: 8 + property var config: Render.getConfig("RenderMainView.DrawFrustums"); + + Component.onCompleted: { + config.enabled = true; + } + Component.onDestruction: { + config.enabled = false; + } + + CheckBox { + text: "Freeze Frustums" + checked: false + onCheckedChanged: { + config.isFrozen = checked; + } + } + Row { + spacing: 8 + Label { + text: "View" + color: "yellow" + font.italic: true + } + Label { + text: "Shadow" + color: "red" + font.italic: true + } + } +} From 6cf689a3853679c5661eb9e48f1a1b23948029cc Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 26 Oct 2017 12:42:36 +0200 Subject: [PATCH 15/55] First draft version of tighter shadow frustum --- libraries/render-utils/src/LightStage.cpp | 21 ++- libraries/render-utils/src/LightStage.h | 3 +- .../render-utils/src/RenderShadowTask.cpp | 129 +++++++++++++++-- libraries/render-utils/src/RenderShadowTask.h | 6 +- libraries/render/src/render/SortTask.cpp | 36 ++++- libraries/render/src/render/SortTask.h | 13 +- libraries/shared/src/AABox.h | 3 +- libraries/shared/src/GeometryUtil.cpp | 130 ++++++++++++++++++ libraries/shared/src/GeometryUtil.h | 4 + libraries/shared/src/Plane.h | 4 +- libraries/shared/src/Transform.h | 8 ++ 11 files changed, 335 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 079c63f367..945bb3b9e6 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -25,7 +25,10 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); } -void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth) { +void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, + float viewMinShadowDistance, float viewMaxShadowDistance, + float nearDepth, float farDepth) { + assert(viewMinShadowDistance < viewMaxShadowDistance); assert(nearDepth < farDepth); // Orient the keylight frustum @@ -48,8 +51,8 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, floa const Transform view{ _frustum->getView()}; const Transform viewInverse{ view.getInverseMatrix() }; - auto nearCorners = viewFrustum.getCorners(nearDepth); - auto farCorners = viewFrustum.getCorners(farDepth); + auto nearCorners = viewFrustum.getCorners(viewMinShadowDistance); + auto farCorners = viewFrustum.getCorners(viewMaxShadowDistance); vec3 min{ viewInverse.transform(nearCorners.bottomLeft) }; vec3 max{ min }; @@ -73,6 +76,8 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, floa fitFrustum(farCorners.topLeft); fitFrustum(farCorners.topRight); + // Re-adjust near shadow distance to + max.z = glm::max(max.z, -nearDepth); glm::mat4 ortho = glm::ortho(min.x, max.x, min.y, max.y, -max.z, -min.z); _frustum->setProjection(ortho); @@ -84,6 +89,16 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, floa _schemaBuffer.edit().viewInverse = viewInverse.getMatrix(); } +void LightStage::Shadow::setFrustum(const ViewFrustum& shadowFrustum) { + const Transform view{ shadowFrustum.getView() }; + const Transform viewInverse{ view.getInverseMatrix() }; + + *_frustum = shadowFrustum; + // Update the buffer + _schemaBuffer.edit().projection = shadowFrustum.getProjection(); + _schemaBuffer.edit().viewInverse = viewInverse.getMatrix(); +} + const glm::mat4& LightStage::Shadow::getView() const { return _frustum->getView(); } diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 66d73c9a6e..a6e369c2f4 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -48,8 +48,9 @@ public: Shadow(model::LightPointer light); - void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth); + void setKeylightFrustum(const ViewFrustum& viewFrustum, float viewMinShadowDistance, float viewMaxShadowDistance, float nearDepth = 1.0f, float farDepth = 1000.0f); + void setFrustum(const ViewFrustum& shadowFrustum); const std::shared_ptr getFrustum() const { return _frustum; } const glm::mat4& getView() const; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 7171543abc..80b988d055 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -22,25 +22,131 @@ #include "DeferredLightingEffect.h" #include "FramebufferCache.h" +#define SHADOW_FRUSTUM_NEAR 1.0f +#define SHADOW_FRUSTUM_FAR 100.0f + using namespace render; extern void initZPassPipelines(ShapePlumber& plumber, gpu::StatePointer state); -void RenderShadowMap::run(const render::RenderContextPointer& renderContext, - const render::ShapeBounds& inShapes) { +static void computeNearFar(const Triangle& triangle, const Plane shadowClipPlanes[4], float& near, float& far) { + static const int MAX_TRIANGLE_COUNT = 16; + Triangle clippedTriangles[MAX_TRIANGLE_COUNT]; + auto clippedTriangleCount = clipTriangleWithPlanes(triangle, shadowClipPlanes, 4, clippedTriangles, MAX_TRIANGLE_COUNT); + + for (auto i = 0; i < clippedTriangleCount; i++) { + const auto& clippedTriangle = clippedTriangles[i]; + + near = glm::min(near, -clippedTriangle.v0.z); + near = glm::min(near, -clippedTriangle.v1.z); + near = glm::min(near, -clippedTriangle.v2.z); + + far = glm::max(far, -clippedTriangle.v0.z); + far = glm::max(far, -clippedTriangle.v1.z); + far = glm::max(far, -clippedTriangle.v2.z); + } +} + +static void computeNearFar(const glm::vec3 sceneBoundVertices[8], const Plane shadowClipPlanes[4], float& near, float& far) { + // This code is inspired from Microsoft's CascadedShadowMaps11 sample which is under MIT licence. + // See https://code.msdn.microsoft.com/windowsdesktop/Direct3D-Shadow-Win32-2d72a4f2/sourcecode?fileId=121915&pathId=1645833187 + // Basically it decomposes the object bounding box in triangles and clips each triangle with the shadow + // frustum planes. Finally it computes the minimum and maximum depth of the clipped triangle vertices + // in shadow space to extract the near and far distances of the shadow frustum. + static const std::array boxQuadVertexIndices = { { + { TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, TOP_RIGHT_FAR }, + { TOP_LEFT_NEAR, BOTTOM_LEFT_NEAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR }, + { TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, TOP_RIGHT_NEAR }, + { TOP_LEFT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR }, + { BOTTOM_LEFT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_RIGHT_NEAR, BOTTOM_LEFT_NEAR }, + { TOP_LEFT_FAR, TOP_RIGHT_FAR, TOP_RIGHT_NEAR, TOP_LEFT_NEAR } + } }; + Triangle triangle; + + for (auto quadVertexIndices : boxQuadVertexIndices) { + triangle.v0 = sceneBoundVertices[quadVertexIndices[0]]; + triangle.v1 = sceneBoundVertices[quadVertexIndices[1]]; + triangle.v2 = sceneBoundVertices[quadVertexIndices[2]]; + computeNearFar(triangle, shadowClipPlanes, near, far); + triangle.v1 = sceneBoundVertices[quadVertexIndices[3]]; + computeNearFar(triangle, shadowClipPlanes, near, far); + } +} + +static void adjustNearFar(const AABox& inShapeBounds, ViewFrustum& shadowFrustum) { + const Transform shadowView{ shadowFrustum.getView() }; + const Transform shadowViewInverse{ shadowView.getInverseMatrix() }; + + glm::vec3 sceneBoundVertices[8]; + // Keep only the left, right, top and bottom shadow frustum planes as we wish to determine + // the near and far + Plane shadowClipPlanes[4]; + int i; + + // The vertices of the scene bounding box are expressed in the shadow frustum's local space + for (i = 0; i < 8; i++) { + sceneBoundVertices[i] = shadowViewInverse.transform(inShapeBounds.getVertex(static_cast(i))); + } + // This indirection array is just a protection in case the ViewFrustum::PlaneIndex enum + // changes order especially as we don't need to test the NEAR and FAR planes. + static const ViewFrustum::PlaneIndex planeIndices[4] = { + ViewFrustum::TOP_PLANE, + ViewFrustum::BOTTOM_PLANE, + ViewFrustum::LEFT_PLANE, + ViewFrustum::RIGHT_PLANE + }; + // Same goes for the shadow frustum planes. + for (i = 0; i < 4; i++) { + const auto& worldPlane = shadowFrustum.getPlanes()[planeIndices[i]]; + // We assume the transform doesn't have a non uniform scale component to apply the + // transform to the normal without using the correct transpose of inverse, which should be the + // case for a view matrix. + auto planeNormal = shadowViewInverse.transformDirection(worldPlane.getNormal()); + auto planePoint = shadowViewInverse.transform(worldPlane.getPoint()); + shadowClipPlanes[i].setNormalAndPoint(planeNormal, planePoint); + } + + float near = std::numeric_limits::max(); + float far = 0.0f; + + computeNearFar(sceneBoundVertices, shadowClipPlanes, near, far); + + const auto depthEpsilon = 0.25f; + auto projMatrix = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, near - depthEpsilon, far + depthEpsilon); + auto shadowProjection = shadowFrustum.getProjection(); + + shadowProjection[2][2] = projMatrix[2][2]; + shadowProjection[3][2] = projMatrix[3][2]; + shadowFrustum.setProjection(shadowProjection); + shadowFrustum.calculate(); +} + +void RenderShadowMap::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); + const auto& inShapes = inputs.get0(); + const auto& inShapeBounds = inputs.get1(); + auto lightStage = renderContext->_scene->getStage(); assert(lightStage); - const auto shadow = lightStage->getCurrentKeyShadow(); + auto shadow = lightStage->getCurrentKeyShadow(); if (!shadow) return; const auto& fbo = shadow->framebuffer; RenderArgs* args = renderContext->args; ShapeKey::Builder defaultKeyBuilder; + auto adjustedShadowFrustum = args->getViewFrustum(); + + // Adjust the frustum near and far depths based on the rendered items bounding box to have + // the minimal Z range. + adjustNearFar(inShapeBounds, adjustedShadowFrustum); + // Reapply the frustum as it has been adjusted + shadow->setFrustum(adjustedShadowFrustum); + args->popViewFrustum(); + args->pushViewFrustum(adjustedShadowFrustum); gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; @@ -55,8 +161,13 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, gpu::Framebuffer::BUFFER_COLOR0 | gpu::Framebuffer::BUFFER_DEPTH, vec4(vec3(1.0, 1.0, 1.0), 0.0), 1.0, 0, true); - batch.setProjectionTransform(shadow->getProjection()); - batch.setViewTransform(shadow->getView(), false); + glm::mat4 projMat; + Transform viewMat; + args->getViewFrustum().evalProjectionMatrix(projMat); + args->getViewFrustum().evalViewTransform(viewMat); + + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat, false); auto shadowPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder); auto shadowSkinnedPipeline = _shapePlumber->pickPipeline(args, defaultKeyBuilder.withSkinned()); @@ -109,10 +220,10 @@ void RenderShadowTask::build(JobModel& task, const render::Varying& input, rende // Sort const auto sortedPipelines = task.addJob("PipelineSortShadowSort", culledShadowSelection); - const auto sortedShapes = task.addJob("DepthSortShadowMap", sortedPipelines); + const auto sortedShapesAndBounds = task.addJob("DepthSortShadowMap", sortedPipelines, true); // GPU jobs: Render to shadow map - task.addJob("RenderShadowMap", sortedShapes, shapePlumber); + task.addJob("RenderShadowMap", sortedShapesAndBounds, shapePlumber); task.addJob("ShadowTeardown", cachedMode); } @@ -135,8 +246,8 @@ void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, O auto nearClip = args->getViewFrustum().getNearClip(); float nearDepth = -args->_boomOffset.z; - const int SHADOW_FAR_DEPTH = 20; - globalShadow->setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH); + const float SHADOW_MAX_DISTANCE = 20.0f; + globalShadow->setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_MAX_DISTANCE, SHADOW_FRUSTUM_NEAR, SHADOW_FRUSTUM_FAR); // Set the keylight render args args->pushViewFrustum(*(globalShadow->getFrustum())); diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 031f44a42d..7b2bbeb306 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -21,11 +21,11 @@ class ViewFrustum; class RenderShadowMap { public: - using JobModel = render::Job::ModelI; + using Inputs = render::VaryingSet2; + using JobModel = render::Job::ModelI; RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} - void run(const render::RenderContextPointer& renderContext, - const render::ShapeBounds& inShapes); + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); protected: render::ShapePlumberPointer _shapePlumber; diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index 5b7ead4b6a..f789f8c5c6 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -40,7 +40,8 @@ struct BackToFrontSort { } }; -void render::depthSortItems(const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) { +void render::depthSortItems(const RenderContextPointer& renderContext, bool frontToBack, + const ItemBounds& inItems, ItemBounds& outItems, AABox* bounds) { assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); @@ -75,8 +76,18 @@ void render::depthSortItems(const RenderContextPointer& renderContext, bool fron } // Finally once sorted result to a list of itemID - for (auto& item : itemBoundSorts) { - outItems.emplace_back(ItemBound(item._id, item._bounds)); + if (!bounds) { + for (auto& item : itemBoundSorts) { + outItems.emplace_back(ItemBound(item._id, item._bounds)); + } + } else if (!itemBoundSorts.empty()) { + if (bounds->isNull()) { + *bounds = itemBoundSorts.front()._bounds; + } + for (auto& item : itemBoundSorts) { + *bounds += item._bounds; + outItems.emplace_back(ItemBound(item._id, item._bounds)); + } } } @@ -115,6 +126,25 @@ void DepthSortShapes::run(const RenderContextPointer& renderContext, const Shape } } +void DepthSortShapesAndComputeBounds::run(const RenderContextPointer& renderContext, const ShapeBounds& inShapes, Outputs& outputs) { + auto& outShapes = outputs.edit0(); + auto& outBounds = outputs.edit1(); + + outShapes.clear(); + outShapes.reserve(inShapes.size()); + outBounds = AABox(); + + 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, ItemBounds{})).first; + } + + depthSortItems(renderContext, _frontToBack, inItems, outItems->second, &outBounds); + } +} + void DepthSortItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { depthSortItems(renderContext, _frontToBack, inItems, outItems); } diff --git a/libraries/render/src/render/SortTask.h b/libraries/render/src/render/SortTask.h index dfeb22d540..de670b1676 100644 --- a/libraries/render/src/render/SortTask.h +++ b/libraries/render/src/render/SortTask.h @@ -15,7 +15,7 @@ #include "Engine.h" namespace render { - void depthSortItems(const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems); + void depthSortItems(const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems, AABox* bounds = nullptr); class PipelineSortShapes { public: @@ -33,6 +33,17 @@ namespace render { void run(const RenderContextPointer& renderContext, const ShapeBounds& inShapes, ShapeBounds& outShapes); }; + class DepthSortShapesAndComputeBounds { + public: + using Outputs = VaryingSet2; + using JobModel = Job::ModelIO; + + bool _frontToBack; + DepthSortShapesAndComputeBounds(bool frontToBack = true) : _frontToBack(frontToBack) {} + + void run(const RenderContextPointer& renderContext, const ShapeBounds& inShapes, Outputs& outputs); + }; + class DepthSortItems { public: using JobModel = Job::ModelIO; diff --git a/libraries/shared/src/AABox.h b/libraries/shared/src/AABox.h index eef83974ea..24485eaad6 100644 --- a/libraries/shared/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -127,10 +127,11 @@ public: AABox getOctreeChild(OctreeChild child) const; // returns the AABox of the would be octree child of this AABox + glm::vec4 getPlane(BoxFace face) const; + private: glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const; glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const; - glm::vec4 getPlane(BoxFace face) const; static BoxFace getOppositeFace(BoxFace face); diff --git a/libraries/shared/src/GeometryUtil.cpp b/libraries/shared/src/GeometryUtil.cpp index 6b9718fbb8..e502d44a08 100644 --- a/libraries/shared/src/GeometryUtil.cpp +++ b/libraries/shared/src/GeometryUtil.cpp @@ -14,10 +14,12 @@ #include #include #include +#include #include #include "NumericalConstants.h" #include "GLMHelpers.h" +#include "Plane.h" glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end) { // compute the projection of the point vector onto the segment vector @@ -314,6 +316,134 @@ bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3& direc return false; } +static void getTrianglePlaneIntersectionPoints(const glm::vec3 trianglePoints[3], const float pointPlaneDistances[3], + const int clippedPointIndex, const int keptPointIndices[2], + glm::vec3 points[2]) { + assert(clippedPointIndex >= 0 && clippedPointIndex < 3); + const auto& clippedPoint = trianglePoints[clippedPointIndex]; + const float clippedPointPlaneDistance = pointPlaneDistances[clippedPointIndex]; + for (auto i = 0; i < 2; i++) { + assert(keptPointIndices[i] >= 0 && keptPointIndices[i] < 3); + const auto& keptPoint = trianglePoints[keptPointIndices[i]]; + const float keptPointPlaneDistance = pointPlaneDistances[keptPointIndices[i]]; + auto intersectionEdgeRatio = clippedPointPlaneDistance / (clippedPointPlaneDistance - keptPointPlaneDistance); + points[i] = clippedPoint + (keptPoint - clippedPoint) * intersectionEdgeRatio; + } +} + +int clipTriangleWithPlane(const Triangle& triangle, const Plane& plane, Triangle* clippedTriangles, int maxClippedTriangleCount) { + float pointDistanceToPlane[3]; + std::bitset<3> arePointsClipped; + glm::vec3 triangleVertices[3] = { triangle.v0, triangle.v1, triangle.v2 }; + int clippedTriangleCount = 0; + int i; + + assert(clippedTriangleCount > 0); + + for (i = 0; i < 3; i++) { + pointDistanceToPlane[i] = plane.distance(triangleVertices[i]); + arePointsClipped.set(i, pointDistanceToPlane[i] < 0.0f); + } + + switch (arePointsClipped.count()) { + case 0: + // Easy, the entire triangle is kept as is. + *clippedTriangles = triangle; + clippedTriangleCount = 1; + break; + + case 1: + { + int clippedPointIndex = 2; + int keptPointIndices[2] = { 0, 1 }; + glm::vec3 newVertices[2]; + + // Determine which point was clipped. + if (arePointsClipped.test(0)) { + clippedPointIndex = 0; + keptPointIndices[0] = 2; + } else if (arePointsClipped.test(1)) { + clippedPointIndex = 1; + keptPointIndices[1] = 2; + } + // We have a quad now, so we need to create two triangles. + getTrianglePlaneIntersectionPoints(triangleVertices, pointDistanceToPlane, clippedPointIndex, keptPointIndices, newVertices); + clippedTriangles->v0 = triangleVertices[keptPointIndices[0]]; + clippedTriangles->v1 = triangleVertices[keptPointIndices[1]]; + clippedTriangles->v2 = newVertices[1]; + clippedTriangles++; + clippedTriangleCount++; + + if (clippedTriangleCount < maxClippedTriangleCount) { + clippedTriangles->v0 = triangleVertices[keptPointIndices[0]]; + clippedTriangles->v1 = newVertices[0]; + clippedTriangles->v2 = newVertices[1]; + clippedTriangles++; + clippedTriangleCount++; + } + } + break; + + case 2: + { + int keptPointIndex = 2; + int clippedPointIndices[2] = { 0, 1 }; + glm::vec3 newVertices[2]; + + // Determine which point was NOT clipped. + if (!arePointsClipped.test(0)) { + keptPointIndex = 0; + clippedPointIndices[0] = 2; + } else if (!arePointsClipped.test(1)) { + keptPointIndex = 1; + clippedPointIndices[1] = 2; + } + // We have a single triangle + getTrianglePlaneIntersectionPoints(triangleVertices, pointDistanceToPlane, keptPointIndex, clippedPointIndices, newVertices); + clippedTriangles->v0 = triangleVertices[keptPointIndex]; + clippedTriangles->v1 = newVertices[0]; + clippedTriangles->v2 = newVertices[1]; + clippedTriangleCount = 1; + } + break; + + default: + // Entire triangle is clipped. + break; + } + + return clippedTriangleCount; +} + +int clipTriangleWithPlanes(const Triangle& triangle, const Plane* planes, int planeCount, Triangle* clippedTriangles, int maxClippedTriangleCount) { + auto planesEnd = planes + planeCount; + int triangleCount = 1; + std::vector trianglesToTest; + + assert(maxClippedTriangleCount > 0); + + *clippedTriangles = triangle; + + while (planes < planesEnd) { + int clippedSubTriangleCount; + + trianglesToTest.clear(); + trianglesToTest.insert(trianglesToTest.begin(), clippedTriangles, clippedTriangles + triangleCount); + triangleCount = 0; + + for (const auto& triangleToTest : trianglesToTest) { + clippedSubTriangleCount = clipTriangleWithPlane(triangleToTest, *planes, + clippedTriangles + triangleCount, maxClippedTriangleCount - triangleCount); + triangleCount += clippedSubTriangleCount; + if (triangleCount >= maxClippedTriangleCount) { + return triangleCount; + } + } + ++planes; + } + return triangleCount; +} + // Do line segments (r1p1.x, r1p1.y)--(r1p2.x, r1p2.y) and (r2p1.x, r2p1.y)--(r2p2.x, r2p2.y) intersect? // from: http://ptspts.blogspot.com/2010/06/how-to-determine-if-two-line-segments.html bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2) { diff --git a/libraries/shared/src/GeometryUtil.h b/libraries/shared/src/GeometryUtil.h index eb9424d938..dcb90643b6 100644 --- a/libraries/shared/src/GeometryUtil.h +++ b/libraries/shared/src/GeometryUtil.h @@ -15,6 +15,8 @@ #include #include +class Plane; + glm::vec3 computeVectorFromPointToSegment(const glm::vec3& point, const glm::vec3& start, const glm::vec3& end); /// Computes the penetration between a point and a sphere (centered at the origin) @@ -109,6 +111,8 @@ inline bool findRayTriangleIntersection(const glm::vec3& origin, const glm::vec3 return findRayTriangleIntersection(origin, direction, triangle.v0, triangle.v1, triangle.v2, distance, allowBackface); } +int clipTriangleWithPlane(const Triangle& triangle, const Plane& plane, Triangle* clippedTriangles, int maxClippedTriangleCount); +int clipTriangleWithPlanes(const Triangle& triangle, const Plane* planes, int planeCount, Triangle* clippedTriangles, int maxClippedTriangleCount); bool doLineSegmentsIntersect(glm::vec2 r1p1, glm::vec2 r1p2, glm::vec2 r2p1, glm::vec2 r2p2); bool isOnSegment(float xi, float yi, float xj, float yj, float xk, float yk); diff --git a/libraries/shared/src/Plane.h b/libraries/shared/src/Plane.h index c903ad9db7..cf17ca7201 100644 --- a/libraries/shared/src/Plane.h +++ b/libraries/shared/src/Plane.h @@ -19,7 +19,9 @@ class Plane { public: - Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); } + Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1, v2, v3); } + Plane(const glm::vec3 &normal, const glm::vec3 &point) { setNormalAndPoint(normal, point); } + Plane(float a, float b, float c, float d) { setCoefficients(a, b, c, d); } Plane() : _normal(0.0f), _point(0.0f), _dCoefficient(0.0f) {}; ~Plane() {} ; diff --git a/libraries/shared/src/Transform.h b/libraries/shared/src/Transform.h index 316fcb2f04..71d8b6c915 100644 --- a/libraries/shared/src/Transform.h +++ b/libraries/shared/src/Transform.h @@ -149,6 +149,7 @@ public: Vec4 transform(const Vec4& pos) const; Vec3 transform(const Vec3& pos) const; + Vec3 transformDirection(const Vec3& pos) const; bool containsNaN() const { return isNaN(_rotation) || isNaN(glm::dot(_scale, _translation)); } @@ -541,6 +542,13 @@ 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 { + Mat4 m; + getMatrix(m); + Vec4 result = m * Vec4(pos, 0.0f); + return Vec3(result.x, result.y, result.z); +} + inline Transform::Mat4& Transform::getCachedMatrix(Transform::Mat4& result) const { updateCache(); result = (*_matrix); From 9eed69d7ef39c0a8475dbbeae4037519993eed65 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 26 Oct 2017 15:11:42 +0200 Subject: [PATCH 16/55] Trying to pin point a zone bug --- .../src/RenderableZoneEntityItem.cpp | 6 +++- .../src/DeferredLightingEffect.cpp | 8 ++--- libraries/render-utils/src/DrawHaze.cpp | 6 ++-- libraries/render-utils/src/LightStage.cpp | 32 +++++++++++++++++++ libraries/render-utils/src/LightStage.h | 28 +++------------- .../render-utils/src/RenderShadowTask.cpp | 9 ++++-- 6 files changed, 56 insertions(+), 33 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 0235f1b7a3..7a30414360 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -40,22 +40,26 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity if (_stage) { if (!LightStage::isIndexInvalid(_sunIndex)) { _stage->removeLight(_sunIndex); + _sunIndex = INVALID_INDEX; + _shadowIndex = INVALID_INDEX; } if (!LightStage::isIndexInvalid(_ambientIndex)) { _stage->removeLight(_ambientIndex); - + _ambientIndex = INVALID_INDEX; } } if (_backgroundStage) { if (!BackgroundStage::isIndexInvalid(_backgroundIndex)) { _backgroundStage->removeBackground(_backgroundIndex); + _backgroundIndex = INVALID_INDEX; } } if (_hazeStage) { if (!HazeStage::isIndexInvalid(_hazeIndex)) { _hazeStage->removeHaze(_hazeIndex); + _hazeIndex = INVALID_INDEX; } } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index b6a91888a1..5068047d20 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -105,13 +105,13 @@ void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Bat PerformanceTimer perfTimer("DLE->setupBatch()"); model::LightPointer keySunLight; auto lightStage = args->_scene->getStage(); - if (lightStage && lightStage->_currentFrame._sunLights.size()) { - keySunLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); + if (lightStage) { + keySunLight = lightStage->getCurrentKeyLight(); } model::LightPointer keyAmbiLight; - if (lightStage && lightStage->_currentFrame._ambientLights.size()) { - keyAmbiLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front()); + if (lightStage) { + keyAmbiLight = lightStage->getCurrentAmbientLight(); } if (keySunLight) { diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index bf254ce80e..fc751e9dc1 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -191,9 +191,9 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu batch.setUniformBuffer(HazeEffect_TransformBufferSlot, transformBuffer->getFrameTransformBuffer()); auto lightStage = args->_scene->getStage(); - if (lightStage && lightStage->_currentFrame._sunLights.size() > 0) { - model::LightPointer keyLight; - keyLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); + if (lightStage) { + model::LightPointer keyLight; + keyLight = lightStage->getCurrentKeyLight(); if (keyLight != nullptr) { batch.setUniformBuffer(HazeEffect_LightingMapSlot, keyLight->getLightSchemaBuffer()); } diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 945bb3b9e6..0a18c19698 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -168,6 +168,38 @@ LightStage::LightPointer LightStage::removeLight(Index index) { return removed; } +LightStage::LightPointer LightStage::getCurrentKeyLight() const { + Index keyLightId{ 0 }; + if (!_currentFrame._sunLights.empty()) { + keyLightId = _currentFrame._sunLights.front(); + } + return _lights.get(keyLightId); +} + +LightStage::LightPointer LightStage::getCurrentAmbientLight() const { + Index keyLightId{ 0 }; + if (!_currentFrame._ambientLights.empty()) { + keyLightId = _currentFrame._ambientLights.front(); + } + return _lights.get(keyLightId); +} + +LightStage::ShadowPointer LightStage::getCurrentKeyShadow() const { + Index keyLightId{ 0 }; + if (!_currentFrame._sunLights.empty()) { + keyLightId = _currentFrame._sunLights.front(); + } + return getShadow(keyLightId); +} + +LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const { + Index keyLightId{ 0 }; + if (!_currentFrame._sunLights.empty()) { + keyLightId = _currentFrame._sunLights.front(); + } + return LightAndShadow(getLight(keyLightId), getShadow(keyLightId)); +} + void LightStage::updateLightArrayBuffer(Index lightId) { auto lightSize = sizeof(model::Light::LightSchema); if (!_lightArrayBuffer) { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index a6e369c2f4..cb310ce54d 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -117,31 +117,13 @@ public: return LightAndShadow(getLight(lightId), getShadow(lightId)); } - LightPointer getCurrentKeyLight() const { - Index keyLightId{ 0 }; - if (!_currentFrame._sunLights.empty()) { - keyLightId = _currentFrame._sunLights.front(); - } - return _lights.get(keyLightId); - } - - ShadowPointer getCurrentKeyShadow() const { - Index keyLightId{ 0 }; - if (!_currentFrame._sunLights.empty()) { - keyLightId = _currentFrame._sunLights.front(); - } - return getShadow(keyLightId); - } - - LightAndShadow getCurrentKeyLightAndShadow() const { - Index keyLightId{ 0 }; - if (!_currentFrame._sunLights.empty()) { - keyLightId = _currentFrame._sunLights.front(); - } - return LightAndShadow(getLight(keyLightId), getShadow(keyLightId)); - } + LightPointer getCurrentKeyLight() const; + LightPointer getCurrentAmbientLight() const; + ShadowPointer getCurrentKeyShadow() const; + LightAndShadow getCurrentKeyLightAndShadow() const; LightStage(); + Lights _lights; LightMap _lightMap; Descs _descs; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 80b988d055..9bf915b33e 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -22,8 +22,10 @@ #include "DeferredLightingEffect.h" #include "FramebufferCache.h" +// These values are used for culling the objects rendered in the shadow map +// but are readjusted afterwards #define SHADOW_FRUSTUM_NEAR 1.0f -#define SHADOW_FRUSTUM_FAR 100.0f +#define SHADOW_FRUSTUM_FAR 500.0f using namespace render; @@ -110,8 +112,11 @@ static void adjustNearFar(const AABox& inShapeBounds, ViewFrustum& shadowFrustum float far = 0.0f; computeNearFar(sceneBoundVertices, shadowClipPlanes, near, far); + // Limit the far range to the one used originally. There's no point in rendering objects + // that are not in the view frustum. + far = glm::min(far, shadowFrustum.getFarClip()); - const auto depthEpsilon = 0.25f; + const auto depthEpsilon = 0.1f; auto projMatrix = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, near - depthEpsilon, far + depthEpsilon); auto shadowProjection = shadowFrustum.getProjection(); From 5d83284ac59ae680408285ae05c0cc1f67999772 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 26 Oct 2017 16:47:20 +0200 Subject: [PATCH 17/55] Fixed small bug in shadow bounds computation --- libraries/render/src/render/SortTask.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp index f789f8c5c6..987b25358a 100644 --- a/libraries/render/src/render/SortTask.cpp +++ b/libraries/render/src/render/SortTask.cpp @@ -140,8 +140,14 @@ void DepthSortShapesAndComputeBounds::run(const RenderContextPointer& renderCont if (outItems == outShapes.end()) { outItems = outShapes.insert(std::make_pair(pipeline.first, ItemBounds{})).first; } + AABox bounds; - depthSortItems(renderContext, _frontToBack, inItems, outItems->second, &outBounds); + depthSortItems(renderContext, _frontToBack, inItems, outItems->second, &bounds); + if (!outBounds.isNull()) { + outBounds += bounds; + } else { + outBounds = bounds; + } } } From 44393f12d9409f9ed556ba934d4cf105ca6241cf Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 26 Oct 2017 17:41:54 +0200 Subject: [PATCH 18/55] Adjusted bias --- libraries/render-utils/src/LightStage.cpp | 7 ++++--- libraries/render-utils/src/LightStage.h | 2 +- libraries/render-utils/src/RenderShadowTask.cpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 0a18c19698..b13e46788d 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -76,9 +76,10 @@ void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, fitFrustum(farCorners.topLeft); fitFrustum(farCorners.topRight); - // Re-adjust near shadow distance to - max.z = glm::max(max.z, -nearDepth); - glm::mat4 ortho = glm::ortho(min.x, max.x, min.y, max.y, -max.z, -min.z); + // Re-adjust near shadow distance + auto near = glm::max(max.z, -nearDepth); + auto far = -min.z; + glm::mat4 ortho = glm::ortho(min.x, max.x, min.y, max.y, near, far); _frustum->setProjection(ortho); // Calculate the frustum's internal state diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index cb310ce54d..706caec9d6 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -69,7 +69,7 @@ public: glm::mat4 projection; glm::mat4 viewInverse; - glm::float32 bias = 0.005f; + glm::float32 bias = 0.003f; 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 9bf915b33e..7a6e3dc74f 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -203,7 +203,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con } void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, CullFunctor cullFunctor) { - cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; + cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&) { return true; }; // Prepare the ShapePipeline ShapePlumberPointer shapePlumber = std::make_shared(); From 0044759196656a08ffadfeae09ffe3b4e3a9e3d5 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 26 Oct 2017 18:29:29 +0200 Subject: [PATCH 19/55] Disabled broken PCF and reset back to previous bias --- libraries/render-utils/src/LightStage.cpp | 6 ++++++ libraries/render-utils/src/LightStage.h | 8 ++++++-- libraries/render-utils/src/Shadow.slh | 5 +++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index b13e46788d..411f179d49 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -18,6 +18,12 @@ std::string LightStage::_stageName { "LIGHT_STAGE"}; LightStage::LightStage() { } +LightStage::Shadow::Schema::Schema() : + bias{ 0.005f }, + scale{ 1.0f / MAP_SIZE } { + +} + LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } { framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); map = framebuffer->getDepthStencilBuffer(); diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 706caec9d6..3a2a77055f 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -60,17 +60,21 @@ public: gpu::FramebufferPointer framebuffer; gpu::TexturePointer map; + protected: model::LightPointer _light; std::shared_ptr _frustum; class Schema { public: + + Schema(); + glm::mat4 projection; glm::mat4 viewInverse; - glm::float32 bias = 0.003f; - glm::float32 scale = 1 / MAP_SIZE; + glm::float32 bias; + glm::float32 scale; }; UniformBufferView _schemaBuffer = nullptr; diff --git a/libraries/render-utils/src/Shadow.slh b/libraries/render-utils/src/Shadow.slh index 7b86b9b660..e844db43dd 100644 --- a/libraries/render-utils/src/Shadow.slh +++ b/libraries/render-utils/src/Shadow.slh @@ -68,6 +68,8 @@ vec2 PCFkernel[4] = vec2[4]( ); float evalShadowAttenuationPCF(vec4 position, vec4 shadowTexcoord) { + // PCF is buggy so disable it for the time being +#if 0 float pcfRadius = 3.0; float shadowScale = getShadowScale(); @@ -80,6 +82,9 @@ float evalShadowAttenuationPCF(vec4 position, vec4 shadowTexcoord) { fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[2], 0.0)) + fetchShadow(shadowTexcoord.xyz + shadowScale * vec3(offset + PCFkernel[3], 0.0)) )); +#else + float shadowAttenuation = fetchShadow(shadowTexcoord.xyz); +#endif return shadowAttenuation; } From 79c2da3dcb4841f4a5c17f4cfc82643a1e4e560e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Fri, 3 Nov 2017 16:52:29 +0100 Subject: [PATCH 20/55] Removed cull functor from shadow render task as it is inadapted for the shadow's orthographic projection --- libraries/render-utils/src/RenderViewTask.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index fceaf7b5b9..1085a1148c 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -19,7 +19,10 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred) { // auto items = input.get(); - task.addJob("RenderShadowTask", cullFunctor); + // Shadows use an orthographic projection because they are linked to sunlights + // but the cullFunctor passed is probably tailored for perspective projection and culls too much. + // TODO : create a special cull functor for this. + task.addJob("RenderShadowTask", nullptr); const auto items = task.addJob("FetchCullSort", cullFunctor); assert(items.canCast()); From 332cb48a41e0db4eaed996b0ab0a73162bc008ee Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 7 Nov 2017 16:57:55 -0700 Subject: [PATCH 21/55] Lasers and teleport scale with avatar --- interface/src/raypick/LaserPointer.cpp | 16 +++++++++++++--- interface/src/raypick/LaserPointer.h | 3 ++- interface/src/raypick/LaserPointerManager.cpp | 4 ++-- interface/src/raypick/LaserPointerManager.h | 2 +- .../raypick/LaserPointerScriptingInterface.cpp | 9 +++++++-- interface/src/ui/overlays/Line3DOverlay.cpp | 10 +++++++++- interface/src/ui/overlays/Line3DOverlay.h | 3 +++ libraries/render-utils/src/GeometryCache.cpp | 5 +++-- libraries/render-utils/src/GeometryCache.h | 6 +++--- libraries/render-utils/src/glowLine.slf | 5 +++-- libraries/render-utils/src/glowLine.slv | 3 +++ .../controllerModules/farActionGrabEntity.js | 1 + .../controllers/controllerModules/farTrigger.js | 1 + .../controllers/controllerModules/inEditMode.js | 1 + .../controllerModules/overlayLaserInput.js | 1 + .../controllers/controllerModules/teleport.js | 4 ++++ .../controllerModules/webEntityLaserInput.js | 2 +- .../marketplace/shapes/modules/laser.js | 1 + 18 files changed, 59 insertions(+), 18 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 75b43a251b..50479a77dd 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -7,7 +7,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// +//// #include "LaserPointer.h" #include "Application.h" @@ -15,7 +15,7 @@ #include "RayPickScriptingInterface.h" LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) : + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _defaultRenderStates(defaultRenderStates), @@ -23,6 +23,7 @@ LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& rende _centerEndY(centerEndY), _lockEnd(lockEnd), _distanceScaleEnd(distanceScaleEnd), + _scaleWithAvatar(scaleWithAvatar), _rayPickUID(DependencyManager::get()->createRayPick(rayProps)) { @@ -151,6 +152,9 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } } } + + float avatarScale = DependencyManager::get()->getMyAvatar()->getAvatarScale(); + QVariant end = vec3toVariant(endVec); if (!renderState.getPathID().isNull()) { QVariantMap pathProps; @@ -158,6 +162,11 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter pathProps.insert("end", end); pathProps.insert("visible", true); pathProps.insert("ignoreRayIntersection", renderState.doesPathIgnoreRays()); + if (_scaleWithAvatar) { + auto glowScaleProp = qApp->getOverlays().getProperty(renderState.getPathID(), "glowScale").value; + float glowScale = glowScaleProp.isValid() ? avatarScale * glowScaleProp.toFloat() : avatarScale; + pathProps.insert("glowScale", glowScale); + } qApp->getOverlays().editOverlay(renderState.getPathID(), pathProps); } if (!renderState.getEndID().isNull()) { @@ -165,7 +174,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter glm::quat faceAvatarRotation = DependencyManager::get()->getMyAvatar()->getOrientation() * glm::quat(glm::radians(glm::vec3(0.0f, 180.0f, 0.0f))); glm::vec3 dim = vec3FromVariant(qApp->getOverlays().getProperty(renderState.getEndID(), "dimensions").value); if (_distanceScaleEnd) { - dim = renderState.getEndDim() * glm::distance(pickRay.origin, endVec) * DependencyManager::get()->getMyAvatar()->getSensorToWorldScale(); + dim = renderState.getEndDim() * glm::distance(pickRay.origin, endVec); endProps.insert("dimensions", vec3toVariant(dim)); } if (_centerEndY) { @@ -211,6 +220,7 @@ void LaserPointer::update() { if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_objectLockEnd.first.isNull())) { float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; + qDebug() << &_currentRenderState; updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index f2350c7199..592ba978df 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -60,7 +60,7 @@ public: typedef std::unordered_map> DefaultRenderStateMap; LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled); + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled); ~LaserPointer(); QUuid getRayUID() { return _rayPickUID; } @@ -91,6 +91,7 @@ private: bool _centerEndY; bool _lockEnd; bool _distanceScaleEnd; + bool _scaleWithAvatar; std::pair _objectLockEnd { std::pair(QUuid(), false)}; const QUuid _rayPickUID; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 9d58cc2587..868491f166 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -11,9 +11,9 @@ #include "LaserPointerManager.h" QUuid LaserPointerManager::createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled) { + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) { QUuid result; - std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled); + std::shared_ptr laserPointer = std::make_shared(rayProps, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, scaleWithAvatar, enabled); if (!laserPointer->getRayUID().isNull()) { result = QUuid::createUuid(); withWriteLock([&] { _laserPointers[result] = laserPointer; }); diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index e302318483..9283b7ac89 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -25,7 +25,7 @@ class LaserPointerManager : protected ReadWriteLockable { public: QUuid createLaserPointer(const QVariant& rayProps, const LaserPointer::RenderStateMap& renderStates, const LaserPointer::DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool enabled); + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled); void removeLaserPointer(const QUuid& uid); void enableLaserPointer(const QUuid& uid) const; diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index e8d28bfab2..a47605fa1f 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -7,7 +7,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// +//// #include "LaserPointerScriptingInterface.h" @@ -51,6 +51,11 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert enabled = propertyMap["enabled"].toBool(); } + bool scaleWithAvatar = false; + if (propertyMap["scaleWithAvatar"].isValid()) { + scaleWithAvatar = propertyMap["scaleWithAvatar"].toBool(); + } + LaserPointer::RenderStateMap renderStates; if (propertyMap["renderStates"].isValid()) { QList renderStateVariants = propertyMap["renderStates"].toList(); @@ -80,7 +85,7 @@ QUuid LaserPointerScriptingInterface::createLaserPointer(const QVariant& propert } } - return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, enabled); + return qApp->getLaserPointerManager().createLaserPointer(properties, renderStates, defaultRenderStates, faceAvatar, centerEndY, lockEnd, distanceScaleEnd, scaleWithAvatar, enabled); } void LaserPointerScriptingInterface::editRenderState(const QUuid& uid, const QString& renderState, const QVariant& properties) const { diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index bdb35d4f49..7ac79f081a 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "AbstractViewStateInterface.h" @@ -35,6 +36,7 @@ Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) : _endParentJointIndex = line3DOverlay->getEndJointIndex(); _glow = line3DOverlay->getGlow(); _glowWidth = line3DOverlay->getGlowWidth(); + _glowScale = line3DOverlay->getGlowScale(); } Line3DOverlay::~Line3DOverlay() { @@ -145,7 +147,7 @@ void Line3DOverlay::render(RenderArgs* args) { geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID); } else { // renderGlowLine handles both glow = 0 and glow > 0 cases - geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _geometryCacheID); + geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _glowScale, _geometryCacheID); } } } @@ -244,6 +246,12 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { setGlowWidth(glowWidth.toFloat()); } + auto glowScale = properties["glowScale"]; + if (glowScale.isValid()) { + float gscale = glowScale.toFloat(); + setGlowScale(gscale); + } + } QVariant Line3DOverlay::getProperty(const QString& property) { diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index bcb65b1f1e..250d823598 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -33,6 +33,7 @@ public: glm::vec3 getEnd() const; const float& getGlow() const { return _glow; } const float& getGlowWidth() const { return _glowWidth; } + const float& getGlowScale() const { return _glowScale; } // setters void setStart(const glm::vec3& start); @@ -43,6 +44,7 @@ public: void setGlow(const float& glow) { _glow = glow; } void setGlowWidth(const float& glowWidth) { _glowWidth = glowWidth; } + void setGlowScale(const float& glowScale) { _glowScale = glowScale; } void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -72,6 +74,7 @@ private: float _glow { 0.0 }; float _glowWidth { 0.0 }; + float _glowScale{ 1.0 }; int _geometryCacheID; }; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index fa00737e3c..90b3ca402d 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1868,7 +1868,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, - const glm::vec4& color, float glowIntensity, float glowWidth, int id) { + const glm::vec4& color, float glowIntensity, float glowWidth, float glowScale, int id) { // Disable glow lines on OSX #ifndef Q_OS_WIN @@ -1931,9 +1931,10 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const vec4 p1; vec4 p2; vec4 color; + float scale; }; - LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color }; + LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color, glowScale }; details.uniformBuffer->resize(sizeof(LineData)); details.uniformBuffer->setSubData(0, lineData); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index cd8c43f1df..862331b743 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -248,7 +248,7 @@ public: renderWireCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - // Dynamic geometry + // //Dynamic geometry void renderShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape); size_t getShapeTriangleCount(Shape shape); @@ -314,10 +314,10 @@ public: const glm::vec4& color1, const glm::vec4& color2, int id); void renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, - const glm::vec4& color, float glowIntensity, float glowWidth, int id); + const glm::vec4& color, float glowIntensity, float glowWidth, float glowScale, int id); void renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec4& color, int id) - { renderGlowLine(batch, p1, p2, color, 1.0f, 0.05f, id); } + { renderGlowLine(batch, p1, p2, color, 1.0f, 0.05f, 1.0f, id); } void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) { renderDashedLine(batch, start, end, color, 0.05f, 0.025f, id); } diff --git a/libraries/render-utils/src/glowLine.slf b/libraries/render-utils/src/glowLine.slf index 73e14bd319..be1c6842e3 100644 --- a/libraries/render-utils/src/glowLine.slf +++ b/libraries/render-utils/src/glowLine.slf @@ -10,8 +10,9 @@ // in vec4 _color; -in float distanceFromCenter; +in float _scale; +in float distanceFromCenter; out vec4 _fragColor; void main(void) { @@ -21,7 +22,7 @@ void main(void) { float alpha = 1.0 - abs(distanceFromCenter); // Convert from a linear alpha curve to a sharp peaked one - alpha = _color.a * pow(alpha, 10.0); + alpha = _color.a * pow(alpha, 10.0/_scale); // Drop everything where the curve falls off to nearly nothing if (alpha <= 0.05) { diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv index fd3a85d254..7b69943b7a 100644 --- a/libraries/render-utils/src/glowLine.slv +++ b/libraries/render-utils/src/glowLine.slv @@ -16,14 +16,17 @@ layout(std140) uniform lineData { vec4 p1; vec4 p2; vec4 color; + float scale; }; out vec4 _color; +out float _scale; // the distance from the center in 'quad space' out float distanceFromCenter; void main(void) { _color = color; + _scale = scale; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index e34855d521..2ee308ddb4 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -584,6 +584,7 @@ Script.include("/~/system/libraries/controllers.js"); renderStates: renderStates, faceAvatar: true, distanceScaleEnd: true, + scaleWithAvatar: true, defaultRenderStates: defaultRenderStates }); } diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index de60e2e227..ab950cbbdf 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -190,6 +190,7 @@ Script.include("/~/system/libraries/controllers.js"); renderStates: renderStates, faceAvatar: true, distanceScaleEnd: true, + scaleWithAvatar: true, defaultRenderStates: defaultRenderStates }); diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index f9ec38d22a..4520a91d74 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -237,6 +237,7 @@ Script.include("/~/system/libraries/utils.js"); posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, + scaleWithAvatar: true, defaultRenderStates: defaultRenderStates }); diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 1c83f38d9b..e87e6e000a 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -371,6 +371,7 @@ Script.include("/~/system/libraries/controllers.js"); posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, + scaleWithAvatar: true, defaultRenderStates: defaultRenderStates }); diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 0364e4f9b4..c4fbe781b9 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -153,6 +153,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: (_this.hand === RIGHT_HAND) ? "RightHand" : "LeftHand", filter: RayPick.PICK_ENTITIES, faceAvatar: true, + scaleWithAvatar: true, centerEndY: false, renderStates: teleportRenderStates, defaultRenderStates: teleportDefaultRenderStates @@ -161,6 +162,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: (_this.hand === RIGHT_HAND) ? "RightHand" : "LeftHand", filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, faceAvatar: true, + scaleWithAvatar: true, centerEndY: false, renderStates: teleportRenderStates }); @@ -168,6 +170,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: "Avatar", filter: RayPick.PICK_ENTITIES, faceAvatar: true, + scaleWithAvatar: true, centerEndY: false, renderStates: teleportRenderStates, defaultRenderStates: teleportDefaultRenderStates @@ -176,6 +179,7 @@ Script.include("/~/system/libraries/controllers.js"); joint: "Avatar", filter: RayPick.PICK_ENTITIES | RayPick.PICK_INCLUDE_INVISIBLE, faceAvatar: true, + scaleWithAvatar: true, centerEndY: false, renderStates: teleportRenderStates }); diff --git a/scripts/system/controllers/controllerModules/webEntityLaserInput.js b/scripts/system/controllers/controllerModules/webEntityLaserInput.js index 39969df614..eafe7c3462 100644 --- a/scripts/system/controllers/controllerModules/webEntityLaserInput.js +++ b/scripts/system/controllers/controllerModules/webEntityLaserInput.js @@ -88,7 +88,6 @@ Script.include("/~/system/libraries/controllers.js"); {name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath} ]; - // triggered when stylus presses a web overlay/entity var HAPTIC_STYLUS_STRENGTH = 1.0; var HAPTIC_STYLUS_DURATION = 20.0; @@ -452,6 +451,7 @@ Script.include("/~/system/libraries/controllers.js"); posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, + scaleWithAvatar: true, defaultRenderStates: defaultRenderStates }); } diff --git a/unpublishedScripts/marketplace/shapes/modules/laser.js b/unpublishedScripts/marketplace/shapes/modules/laser.js index 1efc38b65a..beefa8a2f4 100644 --- a/unpublishedScripts/marketplace/shapes/modules/laser.js +++ b/unpublishedScripts/marketplace/shapes/modules/laser.js @@ -150,6 +150,7 @@ Laser = function (side) { } function update(hand) { + return; var handPosition, handOrientation, deltaOrigin, From ee3900be4f7104841244222be95af1f9a7f22b04 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 7 Nov 2017 18:26:41 -0700 Subject: [PATCH 22/55] Corrections --- interface/src/raypick/LaserPointer.cpp | 31 ++++++++++++------- interface/src/raypick/LaserPointer.h | 10 +++--- interface/src/raypick/LaserPointerManager.cpp | 4 +-- interface/src/raypick/LaserPointerManager.h | 2 +- .../LaserPointerScriptingInterface.cpp | 2 +- interface/src/ui/overlays/Line3DOverlay.h | 2 +- libraries/render-utils/src/GeometryCache.h | 2 +- .../marketplace/shapes/modules/laser.js | 1 - 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index af09e50cb6..ee0336438c 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -7,7 +7,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -//// +// #include "LaserPointer.h" #include "Application.h" @@ -15,7 +15,7 @@ #include "RayPickScriptingInterface.h" LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _defaultRenderStates(defaultRenderStates), @@ -121,7 +121,8 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter glm::vec3 endVec; if (((defaultState || !_lockEnd) && _lockEndObject.id.isNull()) || type == IntersectionType::HUD) { endVec = pickRay.origin + pickRay.direction * distance; - } else { + } + else { if (!_lockEndObject.id.isNull()) { glm::vec3 pos; glm::quat rot; @@ -132,7 +133,8 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter rot = quatFromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "rotation").value); dim = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "dimensions").value); registrationPoint = glm::vec3(0.5f); - } else { + } + else { EntityItemProperties props = DependencyManager::get()->getEntityProperties(_lockEndObject.id); glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); glm::mat4 finalPosAndRotMat = entityMat * _lockEndObject.offsetMat; @@ -143,17 +145,20 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f); endVec = pos + rot * (dim * (DEFAULT_REGISTRATION_POINT - registrationPoint)); - } else { + } + else { if (type == IntersectionType::ENTITY) { endVec = DependencyManager::get()->getEntityTransform(objectID)[3]; - } else if (type == IntersectionType::OVERLAY) { + } + else if (type == IntersectionType::OVERLAY) { endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value); - } else if (type == IntersectionType::AVATAR) { + } + else if (type == IntersectionType::AVATAR) { endVec = DependencyManager::get()->getAvatar(objectID)->getPosition(); } } } - + float avatarScale = DependencyManager::get()->getMyAvatar()->getAvatarScale(); QVariant end = vec3toVariant(endVec); @@ -180,7 +185,8 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } if (_centerEndY) { endProps.insert("position", end); - } else { + } + else { glm::vec3 currentUpVector = faceAvatarRotation * Vectors::UP; endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.5f * dim.y, currentUpVector.y * 0.5f * dim.y, currentUpVector.z * 0.5f * dim.y))); } @@ -221,13 +227,14 @@ void LaserPointer::update() { if (_renderingEnabled && !_currentRenderState.empty() && _renderStates.find(_currentRenderState) != _renderStates.end() && (prevRayPickResult.type != IntersectionType::NONE || _laserLength > 0.0f || !_lockEndObject.id.isNull())) { float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; - qDebug() << &_currentRenderState; updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); - } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { + } + else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true); - } else if (!_currentRenderState.empty()) { + } + else if (!_currentRenderState.empty()) { disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_defaultRenderStates[_currentRenderState].second); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index e0c6f631c0..7d44194be4 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -22,9 +22,9 @@ class RayPickResult; struct LockEndObject { - QUuid id { QUuid() }; - bool isOverlay { false }; - glm::mat4 offsetMat { glm::mat4() }; + QUuid id{ QUuid() }; + bool isOverlay{ false }; + glm::mat4 offsetMat{ glm::mat4() }; }; class RenderState { @@ -89,8 +89,8 @@ public: private: bool _renderingEnabled; - float _laserLength { 0.0f }; - std::string _currentRenderState { "" }; + float _laserLength{ 0.0f }; + std::string _currentRenderState{ "" }; RenderStateMap _renderStates; DefaultRenderStateMap _defaultRenderStates; bool _faceAvatar; diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 143451d0d3..868491f166 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -113,9 +113,9 @@ void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector } } -void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat) const { +void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const { auto laserPointer = find(uid); if (laserPointer) { - laserPointer->setLockEndUUID(objectID, isOverlay, offsetMat); + laserPointer->setLockEndUUID(objectID, isOverlay); } } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 3f8f962679..9283b7ac89 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -39,7 +39,7 @@ public: void setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const; void setIncludeItems(const QUuid& uid, const QVector& includeEntities) const; - void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const; + void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const; void update(); diff --git a/interface/src/raypick/LaserPointerScriptingInterface.cpp b/interface/src/raypick/LaserPointerScriptingInterface.cpp index a47605fa1f..eb69d610ad 100644 --- a/interface/src/raypick/LaserPointerScriptingInterface.cpp +++ b/interface/src/raypick/LaserPointerScriptingInterface.cpp @@ -7,7 +7,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -//// +// #include "LaserPointerScriptingInterface.h" diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index 250d823598..39e6436683 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -74,7 +74,7 @@ private: float _glow { 0.0 }; float _glowWidth { 0.0 }; - float _glowScale{ 1.0 }; + float _glowScale { 1.0 }; int _geometryCacheID; }; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 862331b743..a325026914 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -248,7 +248,7 @@ public: renderWireCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - // //Dynamic geometry + // Dynamic geometry void renderShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape); size_t getShapeTriangleCount(Shape shape); diff --git a/unpublishedScripts/marketplace/shapes/modules/laser.js b/unpublishedScripts/marketplace/shapes/modules/laser.js index beefa8a2f4..1efc38b65a 100644 --- a/unpublishedScripts/marketplace/shapes/modules/laser.js +++ b/unpublishedScripts/marketplace/shapes/modules/laser.js @@ -150,7 +150,6 @@ Laser = function (side) { } function update(hand) { - return; var handPosition, handOrientation, deltaOrigin, From 536bf6f81d5e763cd4bde37bf08ec4571a655fdb Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 7 Nov 2017 18:34:33 -0700 Subject: [PATCH 23/55] Corrections --- interface/src/raypick/LaserPointer.cpp | 26 +++++++++----------------- interface/src/raypick/LaserPointer.h | 10 +++++----- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index ee0336438c..5f2549deea 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -15,7 +15,7 @@ #include "RayPickScriptingInterface.h" LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, - const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : + const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : _renderingEnabled(enabled), _renderStates(renderStates), _defaultRenderStates(defaultRenderStates), @@ -121,8 +121,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter glm::vec3 endVec; if (((defaultState || !_lockEnd) && _lockEndObject.id.isNull()) || type == IntersectionType::HUD) { endVec = pickRay.origin + pickRay.direction * distance; - } - else { + } else { if (!_lockEndObject.id.isNull()) { glm::vec3 pos; glm::quat rot; @@ -133,8 +132,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter rot = quatFromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "rotation").value); dim = vec3FromVariant(qApp->getOverlays().getProperty(_lockEndObject.id, "dimensions").value); registrationPoint = glm::vec3(0.5f); - } - else { + } else { EntityItemProperties props = DependencyManager::get()->getEntityProperties(_lockEndObject.id); glm::mat4 entityMat = createMatFromQuatAndPos(props.getRotation(), props.getPosition()); glm::mat4 finalPosAndRotMat = entityMat * _lockEndObject.offsetMat; @@ -145,15 +143,12 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } const glm::vec3 DEFAULT_REGISTRATION_POINT = glm::vec3(0.5f); endVec = pos + rot * (dim * (DEFAULT_REGISTRATION_POINT - registrationPoint)); - } - else { + } else { if (type == IntersectionType::ENTITY) { endVec = DependencyManager::get()->getEntityTransform(objectID)[3]; - } - else if (type == IntersectionType::OVERLAY) { + } else if (type == IntersectionType::OVERLAY) { endVec = vec3FromVariant(qApp->getOverlays().getProperty(objectID, "position").value); - } - else if (type == IntersectionType::AVATAR) { + } else if (type == IntersectionType::AVATAR) { endVec = DependencyManager::get()->getAvatar(objectID)->getPosition(); } } @@ -185,8 +180,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } if (_centerEndY) { endProps.insert("position", end); - } - else { + } else { glm::vec3 currentUpVector = faceAvatarRotation * Vectors::UP; endProps.insert("position", vec3toVariant(endVec + glm::vec3(currentUpVector.x * 0.5f * dim.y, currentUpVector.y * 0.5f * dim.y, currentUpVector.z * 0.5f * dim.y))); } @@ -229,12 +223,10 @@ void LaserPointer::update() { float distance = _laserLength > 0.0f ? _laserLength : prevRayPickResult.distance; updateRenderState(_renderStates[_currentRenderState], prevRayPickResult.type, distance, prevRayPickResult.objectID, prevRayPickResult.searchRay, false); disableRenderState(_defaultRenderStates[_currentRenderState].second); - } - else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { + } else if (_renderingEnabled && !_currentRenderState.empty() && _defaultRenderStates.find(_currentRenderState) != _defaultRenderStates.end()) { disableRenderState(_renderStates[_currentRenderState]); updateRenderState(_defaultRenderStates[_currentRenderState].second, IntersectionType::NONE, _defaultRenderStates[_currentRenderState].first, QUuid(), prevRayPickResult.searchRay, true); - } - else if (!_currentRenderState.empty()) { + } else if (!_currentRenderState.empty()) { disableRenderState(_renderStates[_currentRenderState]); disableRenderState(_defaultRenderStates[_currentRenderState].second); } diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index 7d44194be4..e0c6f631c0 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -22,9 +22,9 @@ class RayPickResult; struct LockEndObject { - QUuid id{ QUuid() }; - bool isOverlay{ false }; - glm::mat4 offsetMat{ glm::mat4() }; + QUuid id { QUuid() }; + bool isOverlay { false }; + glm::mat4 offsetMat { glm::mat4() }; }; class RenderState { @@ -89,8 +89,8 @@ public: private: bool _renderingEnabled; - float _laserLength{ 0.0f }; - std::string _currentRenderState{ "" }; + float _laserLength { 0.0f }; + std::string _currentRenderState { "" }; RenderStateMap _renderStates; DefaultRenderStateMap _defaultRenderStates; bool _faceAvatar; From 8c5f97f3d10d4af6d86fb1d9c550c797eb2e03ea Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 7 Nov 2017 20:25:24 -0700 Subject: [PATCH 24/55] More corrections --- interface/src/raypick/LaserPointerManager.cpp | 4 ++-- interface/src/raypick/LaserPointerManager.h | 2 +- interface/src/ui/overlays/Line3DOverlay.cpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/raypick/LaserPointerManager.cpp b/interface/src/raypick/LaserPointerManager.cpp index 868491f166..143451d0d3 100644 --- a/interface/src/raypick/LaserPointerManager.cpp +++ b/interface/src/raypick/LaserPointerManager.cpp @@ -113,9 +113,9 @@ void LaserPointerManager::setIncludeItems(const QUuid& uid, const QVector } } -void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const { +void LaserPointerManager::setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat) const { auto laserPointer = find(uid); if (laserPointer) { - laserPointer->setLockEndUUID(objectID, isOverlay); + laserPointer->setLockEndUUID(objectID, isOverlay, offsetMat); } } diff --git a/interface/src/raypick/LaserPointerManager.h b/interface/src/raypick/LaserPointerManager.h index 9283b7ac89..3f8f962679 100644 --- a/interface/src/raypick/LaserPointerManager.h +++ b/interface/src/raypick/LaserPointerManager.h @@ -39,7 +39,7 @@ public: void setIgnoreItems(const QUuid& uid, const QVector& ignoreEntities) const; void setIncludeItems(const QUuid& uid, const QVector& includeEntities) const; - void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay) const; + void setLockEndUUID(const QUuid& uid, const QUuid& objectID, const bool isOverlay, const glm::mat4& offsetMat = glm::mat4()) const; void update(); diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 7ac79f081a..0dc8fddd04 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -12,7 +12,6 @@ #include #include -#include #include "AbstractViewStateInterface.h" From 39604363eaeefb11ceae5c3870b117c0a21bcc5b Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 8 Nov 2017 11:38:20 +0100 Subject: [PATCH 25/55] Optimized performance of bloom by reducing blur resolution and merging some downsampling passes with blur passes --- libraries/render-utils/src/BloomApply.slf | 2 +- libraries/render-utils/src/BloomEffect.cpp | 116 +++++++++++++----- libraries/render-utils/src/BloomEffect.h | 19 ++- libraries/render-utils/src/BloomThreshold.slf | 28 ++++- libraries/render/src/render/BlurTask.cpp | 32 +++-- libraries/render/src/render/BlurTask.h | 7 +- libraries/render/src/render/ResampleTask.cpp | 4 +- libraries/render/src/render/ResampleTask.h | 3 +- 8 files changed, 151 insertions(+), 60 deletions(-) diff --git a/libraries/render-utils/src/BloomApply.slf b/libraries/render-utils/src/BloomApply.slf index 17f13b1187..953258e8ab 100644 --- a/libraries/render-utils/src/BloomApply.slf +++ b/libraries/render-utils/src/BloomApply.slf @@ -23,5 +23,5 @@ void main(void) { vec4 blur1 = texture(blurMap1, varTexCoord0); vec4 blur2 = texture(blurMap2, varTexCoord0); - outFragColor = vec4((blur0.rgb+blur1.rgb+blur2.rgb)/3.0, intensity); + outFragColor = vec4((blur0.rgb+blur1.rgb+blur2.rgb)*intensity, 1.0f); } diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 69bc790c59..9d9367a6d5 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -21,8 +21,9 @@ #define BLOOM_BLUR_LEVEL_COUNT 3 -BloomThreshold::BloomThreshold() { - +BloomThreshold::BloomThreshold(unsigned int downsamplingFactor) : + _downsamplingFactor(downsamplingFactor) { + assert(downsamplingFactor > 0); } void BloomThreshold::configure(const Config& config) { @@ -41,9 +42,13 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons assert(inputFrameBuffer->hasColor()); auto inputBuffer = inputFrameBuffer->getRenderBuffer(0); - auto bufferSize = glm::ivec2(inputBuffer->getDimensions()); + auto bufferSize = gpu::Vec2u(inputBuffer->getDimensions()); - if (!_outputBuffer || _outputBuffer->getSize() != inputFrameBuffer->getSize()) { + // Downsample resolution + bufferSize.x /= _downsamplingFactor; + bufferSize.y /= _downsamplingFactor; + + if (!_outputBuffer || _outputBuffer->getSize() != bufferSize) { auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputBuffer->getTexelFormat(), bufferSize.x, bufferSize.y, gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT))); @@ -68,13 +73,15 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons _pipeline = gpu::Pipeline::create(program, state); } + glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y }; + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); - batch.setViewportTransform(args->_viewport); + batch.setViewportTransform(viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, args->_viewport)); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport)); batch.setPipeline(_pipeline); batch.setFramebuffer(_outputBuffer); @@ -117,8 +124,7 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + state->setDepthTest(gpu::State::DepthTest(false, false)); _pipeline = gpu::Pipeline::create(program, state); } @@ -127,26 +133,70 @@ void BloomApply::run(const render::RenderContextPointer& renderContext, const In const auto blur0FB = inputs.get1(); const auto blur1FB = inputs.get2(); const auto blur2FB = inputs.get3(); + const glm::ivec4 viewport{ 0, 0, framebufferSize.x, framebufferSize.y }; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { batch.enableStereo(false); batch.setFramebuffer(frameBuffer); - batch.setViewportTransform(args->_viewport); + batch.setViewportTransform(viewport); batch.setProjectionTransform(glm::mat4()); batch.resetViewTransform(); batch.setPipeline(_pipeline); - batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, viewport)); batch.setResourceTexture(BLUR0_SLOT, blur0FB->getRenderBuffer(0)); batch.setResourceTexture(BLUR1_SLOT, blur1FB->getRenderBuffer(0)); batch.setResourceTexture(BLUR2_SLOT, blur2FB->getRenderBuffer(0)); - batch._glUniform1f(INTENSITY_SLOT, _intensity); + batch._glUniform1f(INTENSITY_SLOT, _intensity / 3.0f); batch.draw(gpu::TRIANGLE_STRIP, 4); }); } +void BloomDraw::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { + assert(renderContext->args); + assert(renderContext->args->hasViewFrustum()); + RenderArgs* args = renderContext->args; + + const auto frameBuffer = inputs.get0(); + const auto bloomFrameBuffer = inputs.get1(); + + if (frameBuffer && bloomFrameBuffer) { + const auto framebufferSize = frameBuffer->getSize(); + + if (!_pipeline) { + auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS(); + auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS(); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + + gpu::Shader::BindingSet slotBindings; + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(false, false)); + state->setBlendFunction(true, gpu::State::ONE, gpu::State::BLEND_OP_ADD, gpu::State::ONE, + gpu::State::ZERO, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _pipeline = gpu::Pipeline::create(program, state); + } + + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.enableStereo(false); + + batch.setFramebuffer(frameBuffer); + + batch.setViewportTransform(args->_viewport); + batch.setProjectionTransform(glm::mat4()); + batch.resetViewTransform(); + batch.setPipeline(_pipeline); + + batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(framebufferSize, args->_viewport)); + batch.setResourceTexture(0, bloomFrameBuffer->getRenderBuffer(0)); + batch.draw(gpu::TRIANGLE_STRIP, 4); + }); + } +} + DebugBloom::DebugBloom() { } @@ -161,6 +211,7 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In RenderArgs* args = renderContext->args; const auto frameBuffer = inputs.get0(); + const auto combinedBlurBuffer = inputs.get4(); const auto framebufferSize = frameBuffer->getSize(); const auto level0FB = inputs.get1(); const auto level1FB = inputs.get2(); @@ -216,6 +267,11 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In batch.setModelTransform(modelTransform); batch.setResourceTexture(0, levelTextures[2]); batch.draw(gpu::TRIANGLE_STRIP, 4); + + modelTransform.postTranslate(glm::vec3(2.0f, 0.0f, 0.0f)); + batch.setModelTransform(modelTransform); + batch.setResourceTexture(0, combinedBlurBuffer->getRenderBuffer(0)); + batch.draw(gpu::TRIANGLE_STRIP, 4); } else { auto viewport = args->_viewport; auto blurLevel = _mode - DebugBloomConfig::MODE_LEVEL0; @@ -258,7 +314,7 @@ void BloomConfig::setSize(float value) { assert(blurJobIt != task->_jobs.end()); auto& gaussianBlur = blurJobIt->edit(); auto gaussianBlurParams = gaussianBlur.getParameters(); - gaussianBlurParams->setFilterGaussianTaps((BLUR_MAX_NUM_TAPS - 1) / 2, sigma); + gaussianBlurParams->setFilterGaussianTaps(5, sigma); // Gaussian blur increases at each level to have a slower rolloff on the edge // of the response sigma *= 1.5f; @@ -280,32 +336,24 @@ void Bloom::configure(const Config& config) { } void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs); - const auto bloomHalfInputBuffer = task.addJob("BloomHalf", bloomInputBuffer); - const auto bloomQuarterInputBuffer = task.addJob("BloomQuarter", bloomHalfInputBuffer); + // Start by computing threshold of color buffer input at quarter resolution + const auto bloomInputBuffer = task.addJob("BloomThreshold", inputs, 4U); -#if 1 - // Multi-scale blur - const auto blurFB0 = task.addJob("BloomBlur0", bloomQuarterInputBuffer); - const auto halfBlurFB0 = task.addJob("BloomHalfBlur0", blurFB0); - const auto blurFB1 = task.addJob("BloomBlur1", halfBlurFB0, true); - const auto halfBlurFB1 = task.addJob("BloomHalfBlur1", blurFB1); - const auto blurFB2 = task.addJob("BloomBlur2", halfBlurFB1, true); -#else - // Multi-scale downsampling debug - const auto blurFB0 = bloomQuarterInputBuffer; - const auto blurFB1 = task.addJob("BloomHalfBlur1", blurFB0); - const auto blurFB2 = task.addJob("BloomHalfBlur2", blurFB1); - // This is only needed so as not to crash as we expect to have the three blur jobs - task.addJob("BloomBlur0", bloomHalfInputBuffer, true); - task.addJob("BloomBlur1", blurFB1, true); - task.addJob("BloomBlur2", blurFB2, true); -#endif + // Multi-scale blur, each new blur is half resolution of the previous pass + const auto blurFB0 = task.addJob("BloomBlur0", bloomInputBuffer, true); + const auto blurFB1 = task.addJob("BloomBlur1", blurFB0, true, 2U); + const auto blurFB2 = task.addJob("BloomBlur2", blurFB1, true, 2U); const auto& input = inputs.get(); const auto& frameBuffer = input[1]; - const auto applyInput = DebugBloom::Inputs(frameBuffer, blurFB0, blurFB1, blurFB2).asVarying(); + // Mix all blur levels at quarter resolution + const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2).asVarying(); task.addJob("BloomApply", applyInput); - task.addJob("DebugBloom", applyInput); + // And them blend result in additive manner on top of final color buffer + const auto drawInput = BloomDraw::Inputs(frameBuffer, bloomInputBuffer).asVarying(); + task.addJob("BloomDraw", drawInput); + + const auto debugInput = DebugBloom::Inputs(frameBuffer, blurFB0, blurFB1, blurFB2, bloomInputBuffer).asVarying(); + task.addJob("DebugBloom", debugInput); } diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index fdc2d1a0ba..76ce1b8f52 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -54,7 +54,7 @@ public: using Config = BloomThresholdConfig; using JobModel = render::Job::ModelIO; - BloomThreshold(); + BloomThreshold(unsigned int downsamplingFactor); void configure(const Config& config); void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs); @@ -64,6 +64,7 @@ private: gpu::FramebufferPointer _outputBuffer; gpu::PipelinePointer _pipeline; float _threshold; + unsigned int _downsamplingFactor; }; @@ -96,6 +97,20 @@ private: float _intensity{ 1.0f }; }; +class BloomDraw { +public: + using Inputs = render::VaryingSet2; + using JobModel = render::Job::ModelI; + + BloomDraw() {} + + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); + +private: + + gpu::PipelinePointer _pipeline; +}; + class DebugBloomConfig : public render::Job::Config { Q_OBJECT Q_PROPERTY(int mode MEMBER mode NOTIFY dirty) @@ -121,7 +136,7 @@ signals: class DebugBloom { public: - using Inputs = render::VaryingSet4; + using Inputs = render::VaryingSet5; using Config = DebugBloomConfig; using JobModel = render::Job::ModelI; diff --git a/libraries/render-utils/src/BloomThreshold.slf b/libraries/render-utils/src/BloomThreshold.slf index 14d20dd684..e4b96618df 100644 --- a/libraries/render-utils/src/BloomThreshold.slf +++ b/libraries/render-utils/src/BloomThreshold.slf @@ -16,12 +16,30 @@ uniform float threshold; in vec2 varTexCoord0; out vec4 outFragColor; +#define DOWNSAMPLING_FACTOR 4 +#define SAMPLE_COUNT (DOWNSAMPLING_FACTOR/2) + void main(void) { - vec4 color = texture(colorMap, varTexCoord0); - float luminance = (color.r+color.g+color.b) / 3.0; - float mask = clamp((luminance-threshold)*0.25, 0, 1); + vec2 deltaX = dFdx(varTexCoord0) / SAMPLE_COUNT; + vec2 deltaY = dFdy(varTexCoord0) / SAMPLE_COUNT; + vec2 startUv = varTexCoord0; + vec4 maskedColor = vec4(0,0,0,0); - color *= mask; + for (int y=0 ; y 0); } bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFramebuffer, Resources& blurringResources) { if (!sourceFramebuffer) { return false; } - if (_blurredFramebuffer && _blurredFramebuffer->getSize() != sourceFramebuffer->getSize()) { + + auto blurBufferSize = sourceFramebuffer->getSize(); + + blurBufferSize.x /= _downsampleFactor; + blurBufferSize.y /= _downsampleFactor; + + if (_blurredFramebuffer && _blurredFramebuffer->getSize() != blurBufferSize) { _blurredFramebuffer.reset(); } @@ -158,7 +164,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra // _blurredFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat()); //} auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); + auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), blurBufferSize.x, blurBufferSize.y, gpu::Texture::SINGLE_MIP, blurringSampler); _blurredFramebuffer->setRenderBuffer(0, blurringTarget); } @@ -167,7 +173,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra blurringResources.blurringTexture = _blurredFramebuffer->getRenderBuffer(0); if (_generateOutputFramebuffer) { - if (_outputFramebuffer && _outputFramebuffer->getSize() != sourceFramebuffer->getSize()) { + if (_outputFramebuffer && _outputFramebuffer->getSize() != blurBufferSize) { _outputFramebuffer.reset(); } @@ -181,7 +187,7 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra _outputFramebuffer->setDepthStencilBuffer(sourceFramebuffer->getDepthStencilBuffer(), sourceFramebuffer->getDepthStencilBufferFormat()); }*/ auto blurringSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT); - auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), sourceFramebuffer->getWidth(), sourceFramebuffer->getHeight(), gpu::Texture::SINGLE_MIP, blurringSampler); + auto blurringTarget = gpu::Texture::createRenderBuffer(sourceFramebuffer->getRenderBuffer(0)->getTexelFormat(), blurBufferSize.x, blurBufferSize.y, gpu::Texture::SINGLE_MIP, blurringSampler); _outputFramebuffer->setRenderBuffer(0, blurringTarget); } @@ -195,8 +201,8 @@ bool BlurInOutResource::updateResources(const gpu::FramebufferPointer& sourceFra return true; } -BlurGaussian::BlurGaussian(bool generateOutputFramebuffer) : - _inOutResources(generateOutputFramebuffer) +BlurGaussian::BlurGaussian(bool generateOutputFramebuffer, unsigned int downsampleFactor) : + _inOutResources(generateOutputFramebuffer, downsampleFactor) { _parameters = std::make_shared(); } @@ -276,8 +282,8 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra auto blurHPipeline = getBlurHPipeline(); glm::ivec4 viewport { 0, 0, blurredFramebuffer->getWidth(), blurredFramebuffer->getHeight() }; - _parameters->setWidthHeight(viewport.z, viewport.w, args->isStereo()); - glm::ivec2 textureSize(blurringResources.sourceTexture->getDimensions()); + glm::ivec2 textureSize = blurredFramebuffer->getSize(); + _parameters->setWidthHeight(blurredFramebuffer->getWidth(), blurredFramebuffer->getHeight(), args->isStereo()); _parameters->setTexcoordTransform(gpu::Framebuffer::evalSubregionTexcoordTransformCoefficients(textureSize, viewport)); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { @@ -310,7 +316,7 @@ void BlurGaussian::run(const RenderContextPointer& renderContext, const gpu::Fra BlurGaussianDepthAware::BlurGaussianDepthAware(bool generateOutputFramebuffer, const BlurParamsPointer& params) : - _inOutResources(generateOutputFramebuffer), + _inOutResources(generateOutputFramebuffer, 1U), _parameters((params ? params : std::make_shared())) { } diff --git a/libraries/render/src/render/BlurTask.h b/libraries/render/src/render/BlurTask.h index cbee3e35f1..e8d268dc63 100644 --- a/libraries/render/src/render/BlurTask.h +++ b/libraries/render/src/render/BlurTask.h @@ -72,7 +72,7 @@ using BlurParamsPointer = std::shared_ptr; class BlurInOutResource { public: - BlurInOutResource(bool generateOutputFramebuffer = false); + BlurInOutResource(bool generateOutputFramebuffer, unsigned int downsampleFactor); struct Resources { gpu::TexturePointer sourceTexture; @@ -85,8 +85,9 @@ public: gpu::FramebufferPointer _blurredFramebuffer; - // the output framebuffer defined if the job needs to output the result in a new framebuffer and not in place in th einput buffer + // the output framebuffer defined if the job needs to output the result in a new framebuffer and not in place in the input buffer gpu::FramebufferPointer _outputFramebuffer; + unsigned int _downsampleFactor{ 1U }; bool _generateOutputFramebuffer{ false }; }; @@ -115,7 +116,7 @@ public: using Config = BlurGaussianConfig; using JobModel = Job::ModelIO; - BlurGaussian(bool generateOutputFramebuffer = false); + BlurGaussian(bool generateOutputFramebuffer = false, unsigned int downsampleFactor = 1U); void configure(const Config& config); void run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& sourceFramebuffer, gpu::FramebufferPointer& blurredFramebuffer); diff --git a/libraries/render/src/render/ResampleTask.cpp b/libraries/render/src/render/ResampleTask.cpp index 929db50c31..65c0ff45b9 100644 --- a/libraries/render/src/render/ResampleTask.cpp +++ b/libraries/render/src/render/ResampleTask.cpp @@ -17,6 +17,8 @@ using namespace render; +gpu::PipelinePointer HalfDownsample::_pipeline; + HalfDownsample::HalfDownsample() { } @@ -57,7 +59,7 @@ void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::F gpu::Shader::makeProgram(*program, slotBindings); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(false)); + state->setDepthTest(gpu::State::DepthTest(false, false)); _pipeline = gpu::Pipeline::create(program, state); } diff --git a/libraries/render/src/render/ResampleTask.h b/libraries/render/src/render/ResampleTask.h index 70cb9a54bb..da2b7b3537 100644 --- a/libraries/render/src/render/ResampleTask.h +++ b/libraries/render/src/render/ResampleTask.h @@ -30,7 +30,8 @@ namespace render { protected: - gpu::PipelinePointer _pipeline; + static gpu::PipelinePointer _pipeline; + gpu::FramebufferPointer _destinationFrameBuffer; gpu::FramebufferPointer getResampledFrameBuffer(const gpu::FramebufferPointer& sourceFramebuffer); From 1791ed01ca050d9c9ff505610a12c7b8871c9d07 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 8 Nov 2017 18:35:26 -0700 Subject: [PATCH 26/55] add width param to vertex shader --- interface/src/raypick/LaserPointer.cpp | 11 ++++++----- interface/src/ui/overlays/Line3DOverlay.cpp | 10 +--------- interface/src/ui/overlays/Line3DOverlay.h | 3 --- libraries/render-utils/src/GeometryCache.cpp | 6 +++--- libraries/render-utils/src/GeometryCache.h | 4 ++-- libraries/render-utils/src/glowLine.slf | 3 +-- libraries/render-utils/src/glowLine.slv | 6 ++---- 7 files changed, 15 insertions(+), 28 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 5f2549deea..14af9b336f 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -14,6 +14,8 @@ #include "avatar/AvatarManager.h" #include "RayPickScriptingInterface.h" +static const float DEFAULT_LASER_POINTER_SIZE = 0.02f; + LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : _renderingEnabled(enabled), @@ -163,11 +165,10 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter pathProps.insert("end", end); pathProps.insert("visible", true); pathProps.insert("ignoreRayIntersection", renderState.doesPathIgnoreRays()); - if (_scaleWithAvatar) { - auto glowScaleProp = qApp->getOverlays().getProperty(renderState.getPathID(), "glowScale").value; - float glowScale = glowScaleProp.isValid() ? avatarScale * glowScaleProp.toFloat() : avatarScale; - pathProps.insert("glowScale", glowScale); - } + + float glowWidth = _scaleWithAvatar ? DEFAULT_LASER_POINTER_SIZE * avatarScale : DEFAULT_LASER_POINTER_SIZE; + pathProps.insert("glowWidth", glowWidth); + qApp->getOverlays().editOverlay(renderState.getPathID(), pathProps); } if (!renderState.getEndID().isNull()) { diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 0dc8fddd04..82a3c46727 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -35,7 +35,6 @@ Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) : _endParentJointIndex = line3DOverlay->getEndJointIndex(); _glow = line3DOverlay->getGlow(); _glowWidth = line3DOverlay->getGlowWidth(); - _glowScale = line3DOverlay->getGlowScale(); } Line3DOverlay::~Line3DOverlay() { @@ -146,7 +145,7 @@ void Line3DOverlay::render(RenderArgs* args) { geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID); } else { // renderGlowLine handles both glow = 0 and glow > 0 cases - geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _glowScale, _geometryCacheID); + geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _geometryCacheID); } } } @@ -244,13 +243,6 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { if (glowWidth.isValid()) { setGlowWidth(glowWidth.toFloat()); } - - auto glowScale = properties["glowScale"]; - if (glowScale.isValid()) { - float gscale = glowScale.toFloat(); - setGlowScale(gscale); - } - } QVariant Line3DOverlay::getProperty(const QString& property) { diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index 39e6436683..bcb65b1f1e 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -33,7 +33,6 @@ public: glm::vec3 getEnd() const; const float& getGlow() const { return _glow; } const float& getGlowWidth() const { return _glowWidth; } - const float& getGlowScale() const { return _glowScale; } // setters void setStart(const glm::vec3& start); @@ -44,7 +43,6 @@ public: void setGlow(const float& glow) { _glow = glow; } void setGlowWidth(const float& glowWidth) { _glowWidth = glowWidth; } - void setGlowScale(const float& glowScale) { _glowScale = glowScale; } void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -74,7 +72,6 @@ private: float _glow { 0.0 }; float _glowWidth { 0.0 }; - float _glowScale { 1.0 }; int _geometryCacheID; }; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 90b3ca402d..ebf0f13d97 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1868,7 +1868,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, - const glm::vec4& color, float glowIntensity, float glowWidth, float glowScale, int id) { + const glm::vec4& color, float glowIntensity, float glowWidth, int id) { // Disable glow lines on OSX #ifndef Q_OS_WIN @@ -1931,10 +1931,10 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const vec4 p1; vec4 p2; vec4 color; - float scale; + float width; }; - LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color, glowScale }; + LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color, glowWidth }; details.uniformBuffer->resize(sizeof(LineData)); details.uniformBuffer->setSubData(0, lineData); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index a325026914..cd8c43f1df 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -314,10 +314,10 @@ public: const glm::vec4& color1, const glm::vec4& color2, int id); void renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, - const glm::vec4& color, float glowIntensity, float glowWidth, float glowScale, int id); + const glm::vec4& color, float glowIntensity, float glowWidth, int id); void renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec4& color, int id) - { renderGlowLine(batch, p1, p2, color, 1.0f, 0.05f, 1.0f, id); } + { renderGlowLine(batch, p1, p2, color, 1.0f, 0.05f, id); } void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) { renderDashedLine(batch, start, end, color, 0.05f, 0.025f, id); } diff --git a/libraries/render-utils/src/glowLine.slf b/libraries/render-utils/src/glowLine.slf index be1c6842e3..6a7a6157a4 100644 --- a/libraries/render-utils/src/glowLine.slf +++ b/libraries/render-utils/src/glowLine.slf @@ -10,7 +10,6 @@ // in vec4 _color; -in float _scale; in float distanceFromCenter; out vec4 _fragColor; @@ -22,7 +21,7 @@ void main(void) { float alpha = 1.0 - abs(distanceFromCenter); // Convert from a linear alpha curve to a sharp peaked one - alpha = _color.a * pow(alpha, 10.0/_scale); + alpha = _color.a * pow(alpha, 10.0); // Drop everything where the curve falls off to nearly nothing if (alpha <= 0.05) { diff --git a/libraries/render-utils/src/glowLine.slv b/libraries/render-utils/src/glowLine.slv index 7b69943b7a..4532ed7b9f 100644 --- a/libraries/render-utils/src/glowLine.slv +++ b/libraries/render-utils/src/glowLine.slv @@ -16,17 +16,15 @@ layout(std140) uniform lineData { vec4 p1; vec4 p2; vec4 color; - float scale; + float width; }; out vec4 _color; -out float _scale; // the distance from the center in 'quad space' out float distanceFromCenter; void main(void) { _color = color; - _scale = scale; TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -42,7 +40,7 @@ void main(void) { // Find the vector from the eye to one of the points vec3 v2 = normalize(p1eye.xyz); // The orthogonal vector is the cross product of these two - vec3 orthogonal = cross(v1, v2) * 0.02; + vec3 orthogonal = cross(v1, v2) * width; // Deteremine which end to emit based on the vertex id (even / odd) vec4 eye = (0 == gl_VertexID % 2) ? p1eye : p2eye; From bccd6df57c14c6586218597db4fcc9bc61a4676f Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Thu, 9 Nov 2017 11:19:28 +0100 Subject: [PATCH 27/55] Fixed warning on Mac and Ubuntu --- libraries/render/src/render/BlurTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render/src/render/BlurTask.cpp b/libraries/render/src/render/BlurTask.cpp index 54ec531c8b..2be6f8fad2 100644 --- a/libraries/render/src/render/BlurTask.cpp +++ b/libraries/render/src/render/BlurTask.cpp @@ -137,8 +137,8 @@ void BlurParams::setLinearDepthPosFar(float farPosDepth) { BlurInOutResource::BlurInOutResource(bool generateOutputFramebuffer, unsigned int downsampleFactor) : -_generateOutputFramebuffer(generateOutputFramebuffer), -_downsampleFactor(downsampleFactor) { + _downsampleFactor(downsampleFactor), + _generateOutputFramebuffer(generateOutputFramebuffer) { assert(downsampleFactor > 0); } From 7dfdc8da59fc80f006dd0dfba683259d2a0c03fd Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 9 Nov 2017 17:50:38 -0700 Subject: [PATCH 28/55] Redesign and clean of unused lineWidths --- interface/src/raypick/LaserPointer.cpp | 12 ++++++++---- interface/src/raypick/LaserPointer.h | 4 ++++ interface/src/ui/overlays/Base3DOverlay.cpp | 12 ------------ interface/src/ui/overlays/Base3DOverlay.h | 3 --- interface/src/ui/overlays/Line3DOverlay.cpp | 15 +++++++++------ interface/src/ui/overlays/Line3DOverlay.h | 8 +++++--- .../tests/performance/rayPickPerformance.js | 1 - scripts/system/chat.js | 3 +-- .../controllerModules/farActionGrabEntity.js | 3 --- .../controllerModules/farTrigger.js | 3 --- .../controllerModules/hudOverlayPointer.js | 3 --- .../controllerModules/inEditMode.js | 3 --- .../controllerModules/overlayLaserInput.js | 3 --- .../controllerModules/webEntityLaserInput.js | 3 --- .../system/libraries/entitySelectionTool.js | 19 ++----------------- scripts/system/pal.js | 1 - scripts/tutorials/entity_scripts/pistol.js | 3 +-- .../DomainContent/Toybox/bow/bow.js | 2 -- .../DomainContent/Toybox/bow/createBow.js | 1 - .../DomainContent/Toybox/hiddenEntityReset.js | 1 - .../DomainContent/Toybox/masterReset.js | 1 - .../DomainContent/Toybox/pistol/pistol.js | 3 +-- unpublishedScripts/marketplace/bow/bow.js | 2 -- .../marketplace/laser/laserPointerApp.js | 1 - .../marketplace/shapes/modules/laser.js | 1 - .../marketplace/shortbow/bow/bow.js | 2 -- 26 files changed, 31 insertions(+), 82 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 14af9b336f..4ef5613b79 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -97,6 +97,10 @@ void LaserPointer::editRenderState(const std::string& state, const QVariant& sta if (endDim.isValid()) { _renderStates[state].setEndDim(vec3FromVariant(endDim)); } + QVariant lineWidth = pathProps.toMap()["lineWidth"]; + if (lineWidth.isValid()) { + _renderStates[state].setLineWidth(lineWidth.toFloat()); + } }); } @@ -165,10 +169,9 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter pathProps.insert("end", end); pathProps.insert("visible", true); pathProps.insert("ignoreRayIntersection", renderState.doesPathIgnoreRays()); - - float glowWidth = _scaleWithAvatar ? DEFAULT_LASER_POINTER_SIZE * avatarScale : DEFAULT_LASER_POINTER_SIZE; - pathProps.insert("glowWidth", glowWidth); - + if (_scaleWithAvatar) { + pathProps.insert("lineWidth", renderState.getLineWidth() * avatarScale); + } qApp->getOverlays().editOverlay(renderState.getPathID(), pathProps); } if (!renderState.getEndID().isNull()) { @@ -268,6 +271,7 @@ RenderState::RenderState(const OverlayID& startID, const OverlayID& pathID, cons } if (!_pathID.isNull()) { _pathIgnoreRays = qApp->getOverlays().getProperty(_pathID, "ignoreRayIntersection").value.toBool(); + _lineWidth = qApp->getOverlays().getProperty(_pathID, "lineWidth").value.toFloat(); } if (!_endID.isNull()) { _endDim = vec3FromVariant(qApp->getOverlays().getProperty(_endID, "dimensions").value); diff --git a/interface/src/raypick/LaserPointer.h b/interface/src/raypick/LaserPointer.h index e0c6f631c0..d38070c05c 100644 --- a/interface/src/raypick/LaserPointer.h +++ b/interface/src/raypick/LaserPointer.h @@ -43,6 +43,9 @@ public: void setEndDim(const glm::vec3& endDim) { _endDim = endDim; } const glm::vec3& getEndDim() const { return _endDim; } + void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; } + const float& getLineWidth() const { return _lineWidth; } + void deleteOverlays(); private: @@ -54,6 +57,7 @@ private: bool _endIgnoreRays; glm::vec3 _endDim; + float _lineWidth; }; diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 42425932df..a2f400900e 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -16,13 +16,11 @@ #include "Application.h" -const float DEFAULT_LINE_WIDTH = 1.0f; const bool DEFAULT_IS_SOLID = false; const bool DEFAULT_IS_DASHED_LINE = false; Base3DOverlay::Base3DOverlay() : SpatiallyNestable(NestableType::Overlay, QUuid::createUuid()), - _lineWidth(DEFAULT_LINE_WIDTH), _isSolid(DEFAULT_IS_SOLID), _isDashedLine(DEFAULT_IS_DASHED_LINE), _ignoreRayIntersection(false), @@ -34,7 +32,6 @@ Base3DOverlay::Base3DOverlay() : Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : Overlay(base3DOverlay), SpatiallyNestable(NestableType::Overlay, QUuid::createUuid()), - _lineWidth(base3DOverlay->_lineWidth), _isSolid(base3DOverlay->_isSolid), _isDashedLine(base3DOverlay->_isDashedLine), _ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection), @@ -153,12 +150,6 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { setLocalOrientation(quatFromVariant(properties["orientation"])); needRenderItemUpdate = true; } - - if (properties["lineWidth"].isValid()) { - setLineWidth(properties["lineWidth"].toFloat()); - needRenderItemUpdate = true; - } - if (properties["isSolid"].isValid()) { setIsSolid(properties["isSolid"].toBool()); } @@ -225,9 +216,6 @@ QVariant Base3DOverlay::getProperty(const QString& property) { if (property == "localRotation" || property == "localOrientation") { return quatToVariant(getLocalOrientation()); } - if (property == "lineWidth") { - return _lineWidth; - } if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filed") { return _isSolid; } diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 436cfbf97b..0c73214259 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -35,7 +35,6 @@ public: // TODO: consider implementing registration points in this class glm::vec3 getCenter() const { return getPosition(); } - float getLineWidth() const { return _lineWidth; } bool getIsSolid() const { return _isSolid; } bool getIsDashedLine() const { return _isDashedLine; } bool getIsSolidLine() const { return !_isDashedLine; } @@ -44,7 +43,6 @@ public: bool getDrawHUDLayer() const { return _drawHUDLayer; } bool getIsGrabbable() const { return _isGrabbable; } - void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } void setIsSolid(bool isSolid) { _isSolid = isSolid; } void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } @@ -80,7 +78,6 @@ protected: virtual void setRenderTransform(const Transform& transform); const Transform& getRenderTransform() const { return _renderTransform; } - float _lineWidth; bool _isSolid; bool _isDashedLine; bool _ignoreRayIntersection; diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 82a3c46727..c3d9de859c 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -6,7 +6,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// +//// #include "Line3DOverlay.h" @@ -33,8 +33,8 @@ Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) : _length = line3DOverlay->getLength(); _endParentID = line3DOverlay->getEndParentID(); _endParentJointIndex = line3DOverlay->getEndJointIndex(); + _lineWidth = line3DOverlay->getLineWidth(); _glow = line3DOverlay->getGlow(); - _glowWidth = line3DOverlay->getGlowWidth(); } Line3DOverlay::~Line3DOverlay() { @@ -145,7 +145,7 @@ void Line3DOverlay::render(RenderArgs* args) { geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID); } else { // renderGlowLine handles both glow = 0 and glow > 0 cases - geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _glowWidth, _geometryCacheID); + geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _lineWidth, _geometryCacheID); } } } @@ -239,9 +239,9 @@ void Line3DOverlay::setProperties(const QVariantMap& originalProperties) { } } - auto glowWidth = properties["glowWidth"]; - if (glowWidth.isValid()) { - setGlowWidth(glowWidth.toFloat()); + auto lineWidth = properties["lineWidth"]; + if (lineWidth.isValid()) { + setLineWidth(lineWidth.toFloat()); } } @@ -261,6 +261,9 @@ QVariant Line3DOverlay::getProperty(const QString& property) { if (property == "length") { return QVariant(getLength()); } + if (property == "lineWidth") { + return _lineWidth; + } return Base3DOverlay::getProperty(property); } diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index bcb65b1f1e..2a3c7caa99 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -13,6 +13,8 @@ #include "Base3DOverlay.h" +static const float DEFAULT_LINE_WIDTH = 0.02f; + class Line3DOverlay : public Base3DOverlay { Q_OBJECT using Parent = Base3DOverlay; @@ -31,8 +33,8 @@ public: // getters glm::vec3 getStart() const; glm::vec3 getEnd() const; + const float& getLineWidth() const { return _lineWidth; } const float& getGlow() const { return _glow; } - const float& getGlowWidth() const { return _glowWidth; } // setters void setStart(const glm::vec3& start); @@ -41,8 +43,8 @@ public: void setLocalStart(const glm::vec3& localStart) { setLocalPosition(localStart); } void setLocalEnd(const glm::vec3& localEnd); + void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; } void setGlow(const float& glow) { _glow = glow; } - void setGlowWidth(const float& glowWidth) { _glowWidth = glowWidth; } void setProperties(const QVariantMap& properties) override; QVariant getProperty(const QString& property) override; @@ -70,8 +72,8 @@ private: glm::vec3 _direction; // in parent frame float _length { 1.0 }; // in parent frame + float _lineWidth { DEFAULT_LINE_WIDTH }; float _glow { 0.0 }; - float _glowWidth { 0.0 }; int _geometryCacheID; }; diff --git a/scripts/developer/tests/performance/rayPickPerformance.js b/scripts/developer/tests/performance/rayPickPerformance.js index b4faf4c1be..92d12c0e71 100644 --- a/scripts/developer/tests/performance/rayPickPerformance.js +++ b/scripts/developer/tests/performance/rayPickPerformance.js @@ -96,7 +96,6 @@ function rayCastTest() { color: color, alpha: 1, visible: visible, - lineWidth: 2, start: origin, end: Vec3.sum(origin,Vec3.multiply(5,direction)) }); diff --git a/scripts/system/chat.js b/scripts/system/chat.js index fa997e20cc..0cb414e23c 100644 --- a/scripts/system/chat.js +++ b/scripts/system/chat.js @@ -284,8 +284,7 @@ endParentJointIndex: yourJointIndex, end: yourJointPosition, color: identifyAvatarLineColor, - alpha: 1, - lineWidth: 1 + alpha: 1 }; avatarIdentifiers[yourAvatarID] = identifierParams; diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 0b00cfa303..8139302dfe 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -33,7 +33,6 @@ Script.include("/~/system/libraries/Xform.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -55,7 +54,6 @@ Script.include("/~/system/libraries/Xform.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -77,7 +75,6 @@ Script.include("/~/system/libraries/Xform.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID diff --git a/scripts/system/controllers/controllerModules/farTrigger.js b/scripts/system/controllers/controllerModules/farTrigger.js index ab950cbbdf..9c72c3df4d 100644 --- a/scripts/system/controllers/controllerModules/farTrigger.js +++ b/scripts/system/controllers/controllerModules/farTrigger.js @@ -25,7 +25,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -47,7 +46,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -69,7 +67,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js index 23802893a8..acddcaf246 100644 --- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -31,7 +31,6 @@ alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawHUDLayer: true, parentID: MyAvatar.SELF_ID @@ -53,7 +52,6 @@ alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawHUDLayer: true, parentID: MyAvatar.SELF_ID @@ -75,7 +73,6 @@ alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawHUDLayer: true, parentID: MyAvatar.SELF_ID diff --git a/scripts/system/controllers/controllerModules/inEditMode.js b/scripts/system/controllers/controllerModules/inEditMode.js index 4520a91d74..94233376c7 100644 --- a/scripts/system/controllers/controllerModules/inEditMode.js +++ b/scripts/system/controllers/controllerModules/inEditMode.js @@ -27,7 +27,6 @@ Script.include("/~/system/libraries/utils.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -49,7 +48,6 @@ Script.include("/~/system/libraries/utils.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -71,7 +69,6 @@ Script.include("/~/system/libraries/utils.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index e87e6e000a..2d27f160c1 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -26,7 +26,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -48,7 +47,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -70,7 +68,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID diff --git a/scripts/system/controllers/controllerModules/webEntityLaserInput.js b/scripts/system/controllers/controllerModules/webEntityLaserInput.js index eafe7c3462..36a36d38f3 100644 --- a/scripts/system/controllers/controllerModules/webEntityLaserInput.js +++ b/scripts/system/controllers/controllerModules/webEntityLaserInput.js @@ -26,7 +26,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -48,7 +47,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID @@ -70,7 +68,6 @@ Script.include("/~/system/libraries/controllers.js"); alpha: 1, solid: true, glow: 1.0, - lineWidth: 5, ignoreRayIntersection: true, // always ignore this drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 3a422bcb8a..d947a1d397 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -339,7 +339,6 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - lineWidth: grabberLineWidth, drawInFront: true, borderSize: 1.4 }; @@ -352,7 +351,6 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - lineWidth: grabberLineWidth, drawInFront: true, borderSize: 1.4 }; @@ -365,7 +363,6 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - lineWidth: grabberLineWidth, drawInFront: true, borderSize: 1.4 }; @@ -378,14 +375,12 @@ SelectionDisplay = (function() { solid: grabberSolid, visible: false, dashed: false, - lineWidth: grabberLineWidth, drawInFront: true, borderSize: 1.4 }; var spotLightLineProperties = { - color: lightOverlayColor, - lineWidth: 1.5 + color: lightOverlayColor }; var highlightBox = Overlays.addOverlay("cube", { @@ -400,7 +395,6 @@ SelectionDisplay = (function() { solid: false, visible: false, dashed: true, - lineWidth: 2.0, ignoreRayIntersection: true, // this never ray intersects drawInFront: true }); @@ -416,8 +410,7 @@ SelectionDisplay = (function() { alpha: 1, solid: false, visible: false, - dashed: false, - lineWidth: 1.0 + dashed: false }); var selectionBoxes = []; @@ -466,7 +459,6 @@ SelectionDisplay = (function() { // var normalLine = Overlays.addOverlay("line3d", { // visible: true, - // lineWidth: 2.0, // start: { x: 0, y: 0, z: 0 }, // end: { x: 0, y: 0, z: 0 }, // color: { red: 255, green: 255, blue: 0 }, @@ -656,7 +648,6 @@ SelectionDisplay = (function() { var xRailOverlay = Overlays.addOverlay("line3d", { visible: false, - lineWidth: 1.0, start: Vec3.ZERO, end: Vec3.ZERO, color: { @@ -668,7 +659,6 @@ SelectionDisplay = (function() { }); var yRailOverlay = Overlays.addOverlay("line3d", { visible: false, - lineWidth: 1.0, start: Vec3.ZERO, end: Vec3.ZERO, color: { @@ -680,7 +670,6 @@ SelectionDisplay = (function() { }); var zRailOverlay = Overlays.addOverlay("line3d", { visible: false, - lineWidth: 1.0, start: Vec3.ZERO, end: Vec3.ZERO, color: { @@ -693,7 +682,6 @@ SelectionDisplay = (function() { var rotateZeroOverlay = Overlays.addOverlay("line3d", { visible: false, - lineWidth: 2.0, start: Vec3.ZERO, end: Vec3.ZERO, color: { @@ -706,7 +694,6 @@ SelectionDisplay = (function() { var rotateCurrentOverlay = Overlays.addOverlay("line3d", { visible: false, - lineWidth: 2.0, start: Vec3.ZERO, end: Vec3.ZERO, color: { @@ -1788,7 +1775,6 @@ SelectionDisplay = (function() { y: distance, z: 1 }, - lineWidth: 1.5, rotation: rotation, visible: true }); @@ -1994,7 +1980,6 @@ SelectionDisplay = (function() { solid: false, visible: false, dashed: false, - lineWidth: 1.0, ignoreRayIntersection: true })); } diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 44ff7c2acd..b5551cf596 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -189,7 +189,6 @@ function HighlightedEntity(id, entityProperties) { green: 0x91, blue: 0x29 }, - lineWidth: 1.0, ignoreRayIntersection: true, drawInFront: false // Arguable. For now, let's not distract with mysterious wires around the scene. }); diff --git a/scripts/tutorials/entity_scripts/pistol.js b/scripts/tutorials/entity_scripts/pistol.js index 1a570cc80f..62517f486d 100644 --- a/scripts/tutorials/entity_scripts/pistol.js +++ b/scripts/tutorials/entity_scripts/pistol.js @@ -350,8 +350,7 @@ end: ZERO_VECTOR, color: { red: 255, green: 0, blue: 0}, alpha: 1, - visible: true, - lineWidth: 2 + visible: true }); }, }; diff --git a/unpublishedScripts/DomainContent/Toybox/bow/bow.js b/unpublishedScripts/DomainContent/Toybox/bow/bow.js index 0c16bcbc7b..47335bcb6d 100644 --- a/unpublishedScripts/DomainContent/Toybox/bow/bow.js +++ b/unpublishedScripts/DomainContent/Toybox/bow/bow.js @@ -329,7 +329,6 @@ y: 0, z: 0 }, lineVectors[0]], - lineWidth: 5, color: this.stringData.currentColor }); @@ -339,7 +338,6 @@ y: 0, z: 0 }, lineVectors[1]], - lineWidth: 5, color: this.stringData.currentColor }); diff --git a/unpublishedScripts/DomainContent/Toybox/bow/createBow.js b/unpublishedScripts/DomainContent/Toybox/bow/createBow.js index f1ed9eb263..5a4275d96a 100644 --- a/unpublishedScripts/DomainContent/Toybox/bow/createBow.js +++ b/unpublishedScripts/DomainContent/Toybox/bow/createBow.js @@ -125,7 +125,6 @@ function createPreNotchString() { y: 0, z: 0 }, downOffset)], - lineWidth: 5, color: { red: 255, green: 255, diff --git a/unpublishedScripts/DomainContent/Toybox/hiddenEntityReset.js b/unpublishedScripts/DomainContent/Toybox/hiddenEntityReset.js index e2deec75ed..fe514f6dfc 100644 --- a/unpublishedScripts/DomainContent/Toybox/hiddenEntityReset.js +++ b/unpublishedScripts/DomainContent/Toybox/hiddenEntityReset.js @@ -450,7 +450,6 @@ y: 0, z: 0 }, downOffset)], - lineWidth: 5, color: { red: 255, green: 255, diff --git a/unpublishedScripts/DomainContent/Toybox/masterReset.js b/unpublishedScripts/DomainContent/Toybox/masterReset.js index 4ad9cce401..b621544621 100644 --- a/unpublishedScripts/DomainContent/Toybox/masterReset.js +++ b/unpublishedScripts/DomainContent/Toybox/masterReset.js @@ -427,7 +427,6 @@ MasterReset = function() { y: 0, z: 0 }, downOffset)], - lineWidth: 5, color: { red: 255, green: 255, diff --git a/unpublishedScripts/DomainContent/Toybox/pistol/pistol.js b/unpublishedScripts/DomainContent/Toybox/pistol/pistol.js index 5f57c6fc17..b408e4f464 100644 --- a/unpublishedScripts/DomainContent/Toybox/pistol/pistol.js +++ b/unpublishedScripts/DomainContent/Toybox/pistol/pistol.js @@ -346,8 +346,7 @@ end: { x: 0, y: 0, z: 0 }, color: COLORS.RED, alpha: 1, - visible: true, - lineWidth: 2 + visible: true }); }, }; diff --git a/unpublishedScripts/marketplace/bow/bow.js b/unpublishedScripts/marketplace/bow/bow.js index 818960e335..883eff113c 100644 --- a/unpublishedScripts/marketplace/bow/bow.js +++ b/unpublishedScripts/marketplace/bow/bow.js @@ -266,7 +266,6 @@ dimensions: { "x": 5, "y": 5, "z": 5 }, ignoreForCollisions: 1, linePoints: [ { "x": 0, "y": 0, "z": 0 }, { "x": 0, "y": -1.2, "z": 0 } ], - lineWidth: 5, name: STRING_NAME, parentID: this.entityID, localPosition: { "x": 0, "y": 0.6, "z": 0.1 }, @@ -287,7 +286,6 @@ resetStringToIdlePosition: function() { Entities.editEntity(this.stringID, { linePoints: [ { "x": 0, "y": 0, "z": 0 }, { "x": 0, "y": -1.2, "z": 0 } ], - lineWidth: 5, localPosition: { "x": 0, "y": 0.6, "z": 0.1 }, localRotation: { "w": 1, "x": 0, "y": 0, "z": 0 }, }); diff --git a/unpublishedScripts/marketplace/laser/laserPointerApp.js b/unpublishedScripts/marketplace/laser/laserPointerApp.js index 515a2c3a76..aa049ea470 100644 --- a/unpublishedScripts/marketplace/laser/laserPointerApp.js +++ b/unpublishedScripts/marketplace/laser/laserPointerApp.js @@ -99,7 +99,6 @@ lifetime: 360, type: 'Line', glow: 1.0, - lineWidth: 5, alpha: 0.5, ignoreRayIntersection: true, drawInFront: true, diff --git a/unpublishedScripts/marketplace/shapes/modules/laser.js b/unpublishedScripts/marketplace/shapes/modules/laser.js index 1efc38b65a..d5feda0e1f 100644 --- a/unpublishedScripts/marketplace/shapes/modules/laser.js +++ b/unpublishedScripts/marketplace/shapes/modules/laser.js @@ -72,7 +72,6 @@ Laser = function (side) { } laserLine = Overlays.addOverlay("line3d", { - lineWidth: 5, alpha: 1.0, glow: 1.0, ignoreRayIntersection: true, diff --git a/unpublishedScripts/marketplace/shortbow/bow/bow.js b/unpublishedScripts/marketplace/shortbow/bow/bow.js index a8e76f76fd..5134fb6fd8 100644 --- a/unpublishedScripts/marketplace/shortbow/bow/bow.js +++ b/unpublishedScripts/marketplace/shortbow/bow/bow.js @@ -408,7 +408,6 @@ function getControllerLocation(controllerHand) { dimensions: { "x": 5, "y": 5, "z": 5 }, ignoreForCollisions: 1, linePoints: [ { "x": 0, "y": 0, "z": 0 }, { "x": 0, "y": -1.2, "z": 0 } ], - lineWidth: 5, color: { red: 153, green: 102, blue: 51 }, name: STRING_NAME, parentID: this.entityID, @@ -430,7 +429,6 @@ function getControllerLocation(controllerHand) { resetStringToIdlePosition: function() { Entities.editEntity(this.stringID, { linePoints: [ { "x": 0, "y": 0, "z": 0 }, { "x": 0, "y": -1.2, "z": 0 } ], - lineWidth: 5, localPosition: { "x": 0, "y": 0.6, "z": 0.1 }, localRotation: { "w": 1, "x": 0, "y": 0, "z": 0 }, }); From 255a40ce3139868333d4b30a8c882e3f563f4b82 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 9 Nov 2017 18:38:04 -0700 Subject: [PATCH 29/55] Corrections --- interface/src/raypick/LaserPointer.cpp | 2 -- interface/src/ui/overlays/Line3DOverlay.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 4ef5613b79..6d29154be0 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -14,8 +14,6 @@ #include "avatar/AvatarManager.h" #include "RayPickScriptingInterface.h" -static const float DEFAULT_LASER_POINTER_SIZE = 0.02f; - LaserPointer::LaserPointer(const QVariant& rayProps, const RenderStateMap& renderStates, const DefaultRenderStateMap& defaultRenderStates, const bool faceAvatar, const bool centerEndY, const bool lockEnd, const bool distanceScaleEnd, const bool scaleWithAvatar, const bool enabled) : _renderingEnabled(enabled), diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index c3d9de859c..a6b7242df2 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -6,7 +6,7 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -//// +// #include "Line3DOverlay.h" From bf576e63fe49b91e0056c5ea97a2dffe4172bd91 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 10 Nov 2017 11:54:53 -0700 Subject: [PATCH 30/55] move constant to class definition --- interface/src/ui/overlays/Line3DOverlay.cpp | 4 +++- interface/src/ui/overlays/Line3DOverlay.h | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index a6b7242df2..eb19617bfc 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -16,9 +16,11 @@ #include "AbstractViewStateInterface.h" QString const Line3DOverlay::TYPE = "line3d"; +static const float DEFAULT_LINE_WIDTH = 0.02f; Line3DOverlay::Line3DOverlay() : - _geometryCacheID(DependencyManager::get()->allocateID()) + _geometryCacheID(DependencyManager::get()->allocateID()), + _lineWidth(DEFAULT_LINE_WIDTH) { } diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index 2a3c7caa99..2995363ad7 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -13,8 +13,6 @@ #include "Base3DOverlay.h" -static const float DEFAULT_LINE_WIDTH = 0.02f; - class Line3DOverlay : public Base3DOverlay { Q_OBJECT using Parent = Base3DOverlay; @@ -72,7 +70,7 @@ private: glm::vec3 _direction; // in parent frame float _length { 1.0 }; // in parent frame - float _lineWidth { DEFAULT_LINE_WIDTH }; + float _lineWidth { 0.0 }; float _glow { 0.0 }; int _geometryCacheID; }; From d53a29b958d40e752b1c342a2e1e2808c8727803 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 10 Nov 2017 12:24:19 -0700 Subject: [PATCH 31/55] correction --- interface/src/ui/overlays/Line3DOverlay.cpp | 4 +--- interface/src/ui/overlays/Line3DOverlay.h | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index eb19617bfc..a6b7242df2 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -16,11 +16,9 @@ #include "AbstractViewStateInterface.h" QString const Line3DOverlay::TYPE = "line3d"; -static const float DEFAULT_LINE_WIDTH = 0.02f; Line3DOverlay::Line3DOverlay() : - _geometryCacheID(DependencyManager::get()->allocateID()), - _lineWidth(DEFAULT_LINE_WIDTH) + _geometryCacheID(DependencyManager::get()->allocateID()) { } diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index 2995363ad7..79af937f23 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -70,7 +70,8 @@ private: glm::vec3 _direction; // in parent frame float _length { 1.0 }; // in parent frame - float _lineWidth { 0.0 }; + const float DEFAULT_LINE_WIDTH = 0.02f; + float _lineWidth { DEFAULT_LINE_WIDTH }; float _glow { 0.0 }; int _geometryCacheID; }; From d1318ae99eb48247deea1878e144bf1474c3fcc9 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Fri, 3 Nov 2017 11:51:03 -0700 Subject: [PATCH 32/55] 8495 No mirror camera in HMD mode --- interface/src/Application.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b21588958e..bd31fc398e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4441,7 +4441,7 @@ void Application::cameraModeChanged() { void Application::cameraMenuChanged() { auto menu = Menu::getInstance(); if (menu->isOptionChecked(MenuOption::FullscreenMirror)) { - if (_myCamera.getMode() != CAMERA_MODE_MIRROR) { + if (!isHMDMode() && _myCamera.getMode() != CAMERA_MODE_MIRROR) { _myCamera.setMode(CAMERA_MODE_MIRROR); getMyAvatar()->reset(false, false, false); // to reset any active MyAvatar::FollowHelpers } @@ -7271,6 +7271,10 @@ void Application::updateDisplayMode() { menu->setIsOptionChecked(MenuOption::FirstPerson, true); cameraMenuChanged(); } + + // Remove the mirror camera option from menu if in HMD mode + auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror); + mirrorAction->setVisible(!isHmd); Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } From 8596d78aa63432e069dac144ee9ceb66f8705b52 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 6 Nov 2017 08:03:07 -0700 Subject: [PATCH 33/55] Not posible to change to mirror mode using js --- interface/src/Application.cpp | 7 ++++++- libraries/shared/src/shared/Camera.cpp | 1 + libraries/shared/src/shared/Camera.h | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd31fc398e..7172a3eab7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4423,7 +4423,12 @@ void Application::cameraModeChanged() { Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); break; case CAMERA_MODE_MIRROR: - Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); + if (isHMDMode()) { + _myCamera.setMode(_myCamera.getLastMode()); + qDebug() << "Mirror mode is not available"; + } else { + Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); + } break; case CAMERA_MODE_INDEPENDENT: Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true); diff --git a/libraries/shared/src/shared/Camera.cpp b/libraries/shared/src/shared/Camera.cpp index ab841c4717..100124a416 100644 --- a/libraries/shared/src/shared/Camera.cpp +++ b/libraries/shared/src/shared/Camera.cpp @@ -85,6 +85,7 @@ void Camera::setOrientation(const glm::quat& orientation) { } void Camera::setMode(CameraMode mode) { + _lastMode = _mode; _mode = mode; emit modeUpdated(modeToString(mode)); } diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 3ad08bd719..11d4cf4254 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -56,6 +56,7 @@ public: void update(); CameraMode getMode() const { return _mode; } + CameraMode getLastMode() const { return _lastMode; } void setMode(CameraMode m); void loadViewFrustum(ViewFrustum& frustum) const; @@ -123,6 +124,7 @@ private: void decompose(); CameraMode _mode{ CAMERA_MODE_THIRD_PERSON }; + CameraMode _lastMode{ _mode }; glm::mat4 _transform; glm::mat4 _projection; From 5d4a3b65e473a0ead7b06c1f48017a573b3eb794 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 9 Nov 2017 18:27:16 -0700 Subject: [PATCH 34/55] Allow script to change to mirror camera in HMD --- interface/src/Application.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7172a3eab7..bd31fc398e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4423,12 +4423,7 @@ void Application::cameraModeChanged() { Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, true); break; case CAMERA_MODE_MIRROR: - if (isHMDMode()) { - _myCamera.setMode(_myCamera.getLastMode()); - qDebug() << "Mirror mode is not available"; - } else { - Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); - } + Menu::getInstance()->setIsOptionChecked(MenuOption::FullscreenMirror, true); break; case CAMERA_MODE_INDEPENDENT: Menu::getInstance()->setIsOptionChecked(MenuOption::IndependentMode, true); From 7af1a5ca6999f74283f22f4700ddf5cd17ca7512 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 13 Nov 2017 06:10:17 -0700 Subject: [PATCH 35/55] clean up unused lastmode --- libraries/shared/src/shared/Camera.cpp | 1 - libraries/shared/src/shared/Camera.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/libraries/shared/src/shared/Camera.cpp b/libraries/shared/src/shared/Camera.cpp index 100124a416..ab841c4717 100644 --- a/libraries/shared/src/shared/Camera.cpp +++ b/libraries/shared/src/shared/Camera.cpp @@ -85,7 +85,6 @@ void Camera::setOrientation(const glm::quat& orientation) { } void Camera::setMode(CameraMode mode) { - _lastMode = _mode; _mode = mode; emit modeUpdated(modeToString(mode)); } diff --git a/libraries/shared/src/shared/Camera.h b/libraries/shared/src/shared/Camera.h index 11d4cf4254..3ad08bd719 100644 --- a/libraries/shared/src/shared/Camera.h +++ b/libraries/shared/src/shared/Camera.h @@ -56,7 +56,6 @@ public: void update(); CameraMode getMode() const { return _mode; } - CameraMode getLastMode() const { return _lastMode; } void setMode(CameraMode m); void loadViewFrustum(ViewFrustum& frustum) const; @@ -124,7 +123,6 @@ private: void decompose(); CameraMode _mode{ CAMERA_MODE_THIRD_PERSON }; - CameraMode _lastMode{ _mode }; glm::mat4 _transform; glm::mat4 _projection; From b4b148367e959bb6ced05705663186574d206528 Mon Sep 17 00:00:00 2001 From: Nissim Hadar Date: Sat, 11 Nov 2017 18:58:12 -0800 Subject: [PATCH 36/55] Removed Keylight attenuation from .js (as well as .html). --- libraries/model/src/model/Haze.cpp | 2 +- scripts/system/html/entityProperties.html | 4 ++-- scripts/system/html/js/entityProperties.js | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/libraries/model/src/model/Haze.cpp b/libraries/model/src/model/Haze.cpp index c9c73bcee9..b56932e131 100644 --- a/libraries/model/src/model/Haze.cpp +++ b/libraries/model/src/model/Haze.cpp @@ -8,8 +8,8 @@ // 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 "Haze.h" using namespace model; diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 9453b476ee..8b2a088d83 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -623,7 +623,7 @@ -
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 0463ac4172..f54394a353 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1069,9 +1069,9 @@ function loaded() { elZoneHazeBackgroundBlend.value = properties.haze.hazeBackgroundBlend.toFixed(2); - elZoneHazeAttenuateKeyLight.checked = properties.haze.hazeAttenuateKeyLight; - elZoneHazeKeyLightRange.value = properties.haze.hazeKeyLightRange.toFixed(0); - elZoneHazeKeyLightAltitude.value = properties.haze.hazeKeyLightAltitude.toFixed(0); +// elZoneHazeAttenuateKeyLight.checked = properties.haze.hazeAttenuateKeyLight; +// elZoneHazeKeyLightRange.value = properties.haze.hazeKeyLightRange.toFixed(0); +// elZoneHazeKeyLightAltitude.value = properties.haze.hazeKeyLightAltitude.toFixed(0); elZoneStageLatitude.value = properties.stage.latitude.toFixed(2); elZoneStageLongitude.value = properties.stage.longitude.toFixed(2); @@ -1533,9 +1533,9 @@ function loaded() { elZoneHazeBackgroundBlend.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeBackgroundBlend')); - elZoneHazeAttenuateKeyLight.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('haze', 'hazeAttenuateKeyLight')); - elZoneHazeKeyLightRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightRange')); - elZoneHazeKeyLightAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightAltitude')); +// elZoneHazeAttenuateKeyLight.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('haze', 'hazeAttenuateKeyLight')); +// elZoneHazeKeyLightRange.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightRange')); +// elZoneHazeKeyLightAltitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeKeyLightAltitude')); elZoneStageLatitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'latitude')); elZoneStageLongitude.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('stage', 'longitude')); From 489e244342db3006c231e3cf18453cbb301f7894 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Tue, 14 Nov 2017 09:56:23 -0700 Subject: [PATCH 37/55] More accurate scale from SensorToWorldScale --- interface/src/raypick/LaserPointer.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/raypick/LaserPointer.cpp b/interface/src/raypick/LaserPointer.cpp index 6d29154be0..71a547533b 100644 --- a/interface/src/raypick/LaserPointer.cpp +++ b/interface/src/raypick/LaserPointer.cpp @@ -158,8 +158,6 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter } } - float avatarScale = DependencyManager::get()->getMyAvatar()->getAvatarScale(); - QVariant end = vec3toVariant(endVec); if (!renderState.getPathID().isNull()) { QVariantMap pathProps; @@ -168,7 +166,7 @@ void LaserPointer::updateRenderState(const RenderState& renderState, const Inter pathProps.insert("visible", true); pathProps.insert("ignoreRayIntersection", renderState.doesPathIgnoreRays()); if (_scaleWithAvatar) { - pathProps.insert("lineWidth", renderState.getLineWidth() * avatarScale); + pathProps.insert("lineWidth", renderState.getLineWidth() * DependencyManager::get()->getMyAvatar()->getSensorToWorldScale()); } qApp->getOverlays().editOverlay(renderState.getPathID(), pathProps); } From e201e203b849367255e2653d97c994cca1e0277f Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Tue, 14 Nov 2017 22:18:48 +0300 Subject: [PATCH 38/55] 8984 Opening tablet with "Enter" key displays the audio menu --- interface/resources/qml/hifi/tablet/Tablet.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml index 66e3dfdbbb..2a086bae94 100644 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ b/interface/resources/qml/hifi/tablet/Tablet.qml @@ -8,8 +8,8 @@ import "../audio" as HifiAudio Item { id: tablet objectName: "tablet" - property int rowIndex: 0 - property int columnIndex: 0 + property int rowIndex: 6 // by default + property int columnIndex: 1 // point to 'go to location' property int count: (flowMain.children.length - 1) // used to look up a button by its uuid From 462ec30cac0ba0c629319af0d25c6a9ec2c36d68 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 29 Aug 2017 16:24:34 -0700 Subject: [PATCH 39/55] Utilise Windows Job Object so child dies w/ parent --- .../src/AssignmentClientMonitor.cpp | 8 +++ libraries/shared/src/SharedUtil.cpp | 53 +++++++++++++++++++ libraries/shared/src/SharedUtil.h | 6 +++ 3 files changed, 67 insertions(+) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 5539d6a0bb..97f03d3cb4 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -28,6 +28,10 @@ const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor"; const int WAIT_FOR_CHILD_MSECS = 1000; +#ifdef Q_OS_WIN +HANDLE JOB_OBJECT = createJobObject(); +#endif + AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmentClientForks, const unsigned int minAssignmentClientForks, const unsigned int maxAssignmentClientForks, @@ -202,6 +206,10 @@ void AssignmentClientMonitor::spawnChildClient() { assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels); assignmentClient->start(QCoreApplication::applicationFilePath(), _childArguments); +#ifdef Q_OS_WIN + addProcessToJobObject(JOB_OBJECT, assignmentClient->processId()); +#endif + QString stdoutPath, stderrPath; if (_wantsChildFileLogging) { diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 99bdfc4d90..5f4adf9826 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -1113,3 +1113,56 @@ void watchParentProcess(int parentPID) { timer->start(); } #endif + + +#ifdef Q_OS_WIN +QString GetLastErrorAsString() { + //Get the error message, if any. + DWORD errorMessageID = ::GetLastError(); + if (errorMessageID == 0) + return QString(); //No error message has been recorded + + LPSTR messageBuffer = nullptr; + size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + + std::string message(messageBuffer, size); + + //Free the buffer. + LocalFree(messageBuffer); + + return QString::fromStdString(message); +} + +HANDLE createJobObject() { + HANDLE jobObject = CreateJobObject(nullptr, nullptr); + if (jobObject == nullptr) { + qWarning() << "Could NOT create job object:" << GetLastErrorAsString(); + return nullptr; + } + + JOBOBJECT_EXTENDED_LIMIT_INFORMATION JELI; + if (!QueryInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &JELI, sizeof(JELI), nullptr)) { + qWarning() << "Could NOT query job object information" << GetLastErrorAsString(); + return nullptr; + } + JELI.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if (!SetInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &JELI, sizeof(JELI))) { + qWarning() << "Could NOT set job object information" << GetLastErrorAsString(); + return nullptr; + } + + return jobObject; +} + +void addProcessToJobObject(HANDLE jobObject, DWORD processId) { + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); + if (hProcess == nullptr) { + qCritical() << "Could NOT open process" << GetLastErrorAsString(); + } + if (!AssignProcessToJobObject(jobObject, hProcess)) { + qCritical() << "Could NOT assign process to job object" << GetLastErrorAsString(); + } +} + +#endif diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 681418a263..10bcc16212 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -238,4 +238,10 @@ void setMaxCores(uint8_t maxCores); const QString PARENT_PID_OPTION = "parent-pid"; void watchParentProcess(int parentPID); + +#ifdef _WIN32 +HANDLE createJobObject(); +void addProcessToJobObject(HANDLE jobObject, DWORD processId); +#endif + #endif // hifi_SharedUtil_h From 6b5b905b2a6bc901671ff35b6e92c81fb1881dc1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 29 Aug 2017 16:25:20 -0700 Subject: [PATCH 40/55] Exit right away if the parent process died --- libraries/shared/src/SharedUtil.cpp | 6 +++--- libraries/shared/src/SharedUtil.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 5f4adf9826..b27cb3fb1c 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -1081,7 +1081,7 @@ void setMaxCores(uint8_t maxCores) { void quitWithParentProcess() { if (qApp) { qDebug() << "Parent process died, quitting"; - qApp->quit(); + exit(0); } } @@ -1134,7 +1134,7 @@ QString GetLastErrorAsString() { return QString::fromStdString(message); } -HANDLE createJobObject() { +void *createJobObject() { HANDLE jobObject = CreateJobObject(nullptr, nullptr); if (jobObject == nullptr) { qWarning() << "Could NOT create job object:" << GetLastErrorAsString(); @@ -1155,7 +1155,7 @@ HANDLE createJobObject() { return jobObject; } -void addProcessToJobObject(HANDLE jobObject, DWORD processId) { +void addProcessToJobObject(void *jobObject, qint64 processId) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if (hProcess == nullptr) { qCritical() << "Could NOT open process" << GetLastErrorAsString(); diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 10bcc16212..238532ea96 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -240,8 +240,8 @@ void watchParentProcess(int parentPID); #ifdef _WIN32 -HANDLE createJobObject(); -void addProcessToJobObject(HANDLE jobObject, DWORD processId); +void *createJobObject(); +void addProcessToJobObject(void *jobObject, qint64 processId); #endif #endif // hifi_SharedUtil_h From b31118fe002569e8e1df9d376d9a9af8d35ec17d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 31 Aug 2017 09:28:19 -0700 Subject: [PATCH 41/55] CR --- libraries/shared/src/SharedUtil.cpp | 24 ++++++++++++------------ libraries/shared/src/SharedUtil.h | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index b27cb3fb1c..cbfffde762 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -1116,39 +1116,39 @@ void watchParentProcess(int parentPID) { #ifdef Q_OS_WIN -QString GetLastErrorAsString() { - //Get the error message, if any. +QString getLastErrorAsString() { DWORD errorMessageID = ::GetLastError(); - if (errorMessageID == 0) - return QString(); //No error message has been recorded + if (errorMessageID == 0) { + return QString(); + } LPSTR messageBuffer = nullptr; size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); - std::string message(messageBuffer, size); + auto message = QString::fromLocal8Bit(messageBuffer, (int)size); //Free the buffer. LocalFree(messageBuffer); - return QString::fromStdString(message); + return message; } -void *createJobObject() { +void* createJobObject() { HANDLE jobObject = CreateJobObject(nullptr, nullptr); if (jobObject == nullptr) { - qWarning() << "Could NOT create job object:" << GetLastErrorAsString(); + qWarning() << "Could NOT create job object:" << getLastErrorAsString(); return nullptr; } JOBOBJECT_EXTENDED_LIMIT_INFORMATION JELI; if (!QueryInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &JELI, sizeof(JELI), nullptr)) { - qWarning() << "Could NOT query job object information" << GetLastErrorAsString(); + qWarning() << "Could NOT query job object information" << getLastErrorAsString(); return nullptr; } JELI.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; if (!SetInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &JELI, sizeof(JELI))) { - qWarning() << "Could NOT set job object information" << GetLastErrorAsString(); + qWarning() << "Could NOT set job object information" << getLastErrorAsString(); return nullptr; } @@ -1158,10 +1158,10 @@ void *createJobObject() { void addProcessToJobObject(void *jobObject, qint64 processId) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if (hProcess == nullptr) { - qCritical() << "Could NOT open process" << GetLastErrorAsString(); + qCritical() << "Could NOT open process" << getLastErrorAsString(); } if (!AssignProcessToJobObject(jobObject, hProcess)) { - qCritical() << "Could NOT assign process to job object" << GetLastErrorAsString(); + qCritical() << "Could NOT assign process to job object" << getLastErrorAsString(); } } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 238532ea96..fb5090200b 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -239,9 +239,9 @@ const QString PARENT_PID_OPTION = "parent-pid"; void watchParentProcess(int parentPID); -#ifdef _WIN32 -void *createJobObject(); -void addProcessToJobObject(void *jobObject, qint64 processId); +#ifdef Q_OS_WIN +void* createJobObject(); +void addProcessToJobObject(void* jobObject, qint64 processId); #endif #endif // hifi_SharedUtil_h From c5bd86a4bf401f836ef7bbab8227daf3002ce98e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 14 Nov 2017 21:54:40 +0100 Subject: [PATCH 42/55] Disabled bloom by default --- libraries/render-utils/src/BloomEffect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/BloomEffect.h b/libraries/render-utils/src/BloomEffect.h index 76ce1b8f52..5352c65e4d 100644 --- a/libraries/render-utils/src/BloomEffect.h +++ b/libraries/render-utils/src/BloomEffect.h @@ -23,7 +23,7 @@ class BloomConfig : public render::Task::Config { public: - BloomConfig() : render::Task::Config(true) {} + BloomConfig() : render::Task::Config(false) {} float size{ 0.8f }; From 05a38a78c517db0b3c646eac24ca9b1cb7824d57 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Nov 2017 14:08:27 -0800 Subject: [PATCH 43/55] don't send octree data without first query --- assignment-client/src/octree/OctreeSendThread.cpp | 5 +++-- libraries/octree/src/OctreeQuery.h | 2 +- libraries/octree/src/OctreeQueryNode.cpp | 6 ++++++ libraries/octree/src/OctreeQueryNode.h | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 89e3d403fc..024071db0a 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -82,8 +82,9 @@ bool OctreeSendThread::process() { if (auto node = _node.lock()) { OctreeQueryNode* nodeData = static_cast(node->getLinkedData()); - // Sometimes the node data has not yet been linked, in which case we can't really do anything - if (nodeData && !nodeData->isShuttingDown()) { + // If we don't have the OctreeQueryNode or it's uninitialized because we haven't received + // a query yet from the client then we can't send an entity data packet + if (nodeData && nodeData->hasReceivedFirstQuery() && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); packetDistributor(node, nodeData, viewFrustumChanged); } diff --git a/libraries/octree/src/OctreeQuery.h b/libraries/octree/src/OctreeQuery.h index fc9ea525e6..bbd0350baf 100644 --- a/libraries/octree/src/OctreeQuery.h +++ b/libraries/octree/src/OctreeQuery.h @@ -31,7 +31,7 @@ public: virtual ~OctreeQuery() {} int getBroadcastData(unsigned char* destinationBuffer); - int parseData(ReceivedMessage& message) override; + virtual int parseData(ReceivedMessage& message) override; // getters for camera details const glm::vec3& getCameraPosition() const { return _cameraPosition; } diff --git a/libraries/octree/src/OctreeQueryNode.cpp b/libraries/octree/src/OctreeQueryNode.cpp index c26b4ce77b..941bb6b536 100644 --- a/libraries/octree/src/OctreeQueryNode.cpp +++ b/libraries/octree/src/OctreeQueryNode.cpp @@ -18,6 +18,12 @@ #include #include +int OctreeQueryNode::parseData(ReceivedMessage& message) { + // set our flag to indicate that we've parsed for this query at least once + _hasReceivedFirstQuery = true; + + return OctreeQuery::parseData(message); +} void OctreeQueryNode::nodeKilled() { _isShuttingDown = true; diff --git a/libraries/octree/src/OctreeQueryNode.h b/libraries/octree/src/OctreeQueryNode.h index fd89a89949..fac118c628 100644 --- a/libraries/octree/src/OctreeQueryNode.h +++ b/libraries/octree/src/OctreeQueryNode.h @@ -35,6 +35,8 @@ public: void init(); // called after creation to set up some virtual items virtual PacketType getMyPacketType() const = 0; + virtual int parseData(ReceivedMessage& message) override; + void resetOctreePacket(); // resets octree packet to after "V" header void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet @@ -106,6 +108,8 @@ public: bool shouldForceFullScene() const { return _shouldForceFullScene; } void setShouldForceFullScene(bool shouldForceFullScene) { _shouldForceFullScene = shouldForceFullScene; } + bool hasReceivedFirstQuery() const { return _hasReceivedFirstQuery; } + private: OctreeQueryNode(const OctreeQueryNode &); OctreeQueryNode& operator= (const OctreeQueryNode&); @@ -153,6 +157,8 @@ private: QJsonObject _lastCheckJSONParameters; bool _shouldForceFullScene { false }; + + bool _hasReceivedFirstQuery { false }; }; #endif // hifi_OctreeQueryNode_h From 557ee458ecf01cbfcd44a8d3d3574e065c51bcc6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 14 Nov 2017 17:06:46 -0800 Subject: [PATCH 44/55] wait for node active socket before constructing packets --- assignment-client/src/octree/OctreeSendThread.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 024071db0a..3ae653307f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -82,9 +82,12 @@ bool OctreeSendThread::process() { if (auto node = _node.lock()) { OctreeQueryNode* nodeData = static_cast(node->getLinkedData()); - // If we don't have the OctreeQueryNode or it's uninitialized because we haven't received - // a query yet from the client then we can't send an entity data packet - if (nodeData && nodeData->hasReceivedFirstQuery() && !nodeData->isShuttingDown()) { + // If we don't have the OctreeQueryNode at all + // or it's uninitialized because we haven't received a query yet from the client + // or we don't know where we should send packets for this node + // or we're shutting down + // then we can't send an entity data packet + if (nodeData && nodeData->hasReceivedFirstQuery() && node->getActiveSocket() && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); packetDistributor(node, nodeData, viewFrustumChanged); } From f47a3e7d2ced239fdf16b259112b7ee23e228a74 Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 15 Nov 2017 09:42:57 +0100 Subject: [PATCH 45/55] 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 } } From 14275b1cf31090cb8e9a759202527e6efda43b2e Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Wed, 15 Nov 2017 15:42:04 +0100 Subject: [PATCH 46/55] Added asserts in LightStage to catch shadow disappearance when domain is automatically reloaded --- .../src/DeferredLightingEffect.cpp | 2 +- libraries/render-utils/src/LightClusters.cpp | 2 +- libraries/render-utils/src/LightStage.cpp | 45 ++++++++++++----- libraries/render-utils/src/LightStage.h | 50 +++++++++++-------- 4 files changed, 63 insertions(+), 36 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index dcb16c08f8..646b19198b 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -620,7 +620,7 @@ void RenderDeferredLocals::run(const render::RenderContextPointer& renderContext auto& lightIndices = lightClusters->_visibleLightIndices; if (!lightIndices.empty() && lightIndices[0] > 0) { // Bind the global list of lights and the visible lights this frame - batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->_lightArrayBuffer); + batch.setUniformBuffer(deferredLightingEffect->_localLightLocations->lightBufferUnit, lightClusters->_lightStage->getLightArrayBuffer()); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index ab1e194498..eedb9053c7 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -727,7 +727,7 @@ void DebugLightClusters::run(const render::RenderContextPointer& renderContext, batch.setModelTransform(Transform()); // Bind the Light CLuster data strucutre - batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->_lightArrayBuffer); + batch.setUniformBuffer(LIGHT_GPU_SLOT, lightClusters->_lightStage->getLightArrayBuffer()); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_FRUSTUM_GRID_SLOT, lightClusters->_frustumGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_GRID_SLOT, lightClusters->_clusterGridBuffer); batch.setUniformBuffer(LIGHT_CLUSTER_GRID_CLUSTER_CONTENT_SLOT, lightClusters->_clusterContentBuffer); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 160fa2deea..ba705e56cb 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -25,11 +25,17 @@ LightStage::Shadow::Schema::Schema() : } +gpu::FramebufferPointer LightStage::Shadow::framebuffer; +gpu::TexturePointer LightStage::Shadow::map; + 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; _schemaBuffer = std::make_shared(sizeof(Schema), (const gpu::Byte*) &schema); + + if (!framebuffer) { + framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); + map = framebuffer->getDepthStencilBuffer(); + } } void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, @@ -122,11 +128,9 @@ LightStage::Index LightStage::findLight(const LightPointer& light) const { } else { return (*found).second; } - } LightStage::Index LightStage::addLight(const LightPointer& light) { - auto found = _lightMap.find(light); if (found == _lightMap.end()) { auto lightId = _lights.newElement(light); @@ -137,6 +141,7 @@ LightStage::Index LightStage::addLight(const LightPointer& light) { if (lightId >= (Index) _descs.size()) { _descs.emplace_back(Desc()); } else { + assert(_descs[lightId].shadowId == INVALID_INDEX); _descs.emplace(_descs.begin() + lightId, Desc()); } @@ -155,6 +160,7 @@ LightStage::Index LightStage::addShadow(Index lightIndex) { auto light = getLight(lightIndex); Index shadowId = INVALID_INDEX; if (light) { + assert(_descs[lightIndex].shadowId == INVALID_INDEX); shadowId = _shadows.newElement(std::make_shared(light)); _descs[lightIndex].shadowId = shadowId; } @@ -162,18 +168,20 @@ LightStage::Index LightStage::addShadow(Index lightIndex) { } LightStage::LightPointer LightStage::removeLight(Index index) { - LightPointer removed = _lights.freeElement(index); - - if (removed) { + LightPointer removedLight = _lights.freeElement(index); + if (removedLight) { auto shadowId = _descs[index].shadowId; // Remove shadow if one exists for this light if (shadowId != INVALID_INDEX) { - _shadows.freeElement(shadowId); + auto removedShadow = _shadows.freeElement(shadowId); + assert(removedShadow); + assert(removedShadow->getLight() == removedLight); } - _lightMap.erase(removed); + _lightMap.erase(removedLight); _descs[index] = Desc(); } - return removed; + assert(_descs.size() <= index || _descs[index].shadowId == INVALID_INDEX); + return removedLight; } LightStage::LightPointer LightStage::getCurrentKeyLight() const { @@ -197,7 +205,9 @@ LightStage::ShadowPointer LightStage::getCurrentKeyShadow() const { if (!_currentFrame._sunLights.empty()) { keyLightId = _currentFrame._sunLights.front(); } - return getShadow(keyLightId); + auto shadow = getShadow(keyLightId); + assert(shadow == nullptr || shadow->getLight() == getLight(keyLightId)); + return shadow; } LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const { @@ -205,7 +215,18 @@ LightStage::LightAndShadow LightStage::getCurrentKeyLightAndShadow() const { if (!_currentFrame._sunLights.empty()) { keyLightId = _currentFrame._sunLights.front(); } - return LightAndShadow(getLight(keyLightId), getShadow(keyLightId)); + auto shadow = getShadow(keyLightId); + auto light = getLight(keyLightId); + assert(shadow == nullptr || shadow->getLight() == light); + return LightAndShadow(light, shadow); +} + +LightStage::Index LightStage::getShadowId(Index lightId) const { + if (checkLightId(lightId)) { + return _descs[lightId].shadowId; + } else { + return INVALID_INDEX; + } } void LightStage::updateLightArrayBuffer(Index lightId) { diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 052c8dd222..fa581c8315 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -58,10 +58,15 @@ public: const UniformBufferView& getBuffer() const { return _schemaBuffer; } - gpu::FramebufferPointer framebuffer; - gpu::TexturePointer map; + // Shadow maps are shared among all lights for the moment as only one key light + // is used. + static gpu::FramebufferPointer framebuffer; + static gpu::TexturePointer map; + + const model::LightPointer& getLight() const { return _light; } protected: + model::LightPointer _light; std::shared_ptr _frustum; @@ -78,16 +83,11 @@ public: }; UniformBufferView _schemaBuffer = nullptr; - friend class Light; }; + using ShadowPointer = std::shared_ptr; using Shadows = render::indexed_container::IndexedPointerVector; - struct Desc { - Index shadowId { INVALID_INDEX }; - }; - using Descs = std::vector; - Index findLight(const LightPointer& light) const; Index addLight(const LightPointer& light); @@ -105,20 +105,18 @@ public: return _lights.get(lightId); } - Index getShadowId(Index lightId) const { - if (checkLightId(lightId)) { - return _descs[lightId].shadowId; - } else { - return INVALID_INDEX; - } - } + Index getShadowId(Index lightId) const; + ShadowPointer getShadow(Index lightId) const { return _shadows.get(getShadowId(lightId)); } using LightAndShadow = std::pair; LightAndShadow getLightAndShadow(Index lightId) const { - return LightAndShadow(getLight(lightId), getShadow(lightId)); + auto light = getLight(lightId); + auto shadow = getShadow(lightId); + assert(shadow == nullptr || shadow->getLight() == light); + return LightAndShadow(light, shadow); } LightPointer getCurrentKeyLight() const; @@ -128,9 +126,8 @@ public: LightStage(); - Lights _lights; - LightMap _lightMap; - Descs _descs; + gpu::BufferPointer getLightArrayBuffer() const { return _lightArrayBuffer; } + void updateLightArrayBuffer(Index lightId); class Frame { public: @@ -159,15 +156,24 @@ public: Frame _currentFrame; - gpu::BufferPointer _lightArrayBuffer; - void updateLightArrayBuffer(Index lightId); +protected: + struct Desc { + Index shadowId{ INVALID_INDEX }; + }; + using Descs = std::vector; + + gpu::BufferPointer _lightArrayBuffer; + + Lights _lights; Shadows _shadows; + Descs _descs; + LightMap _lightMap; + }; using LightStagePointer = std::shared_ptr; - class LightStageSetup { public: using JobModel = render::Job::Model; From d538a9aaa8debb76476f234aa221f8dca21d40b1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 15 Nov 2017 09:04:04 -0800 Subject: [PATCH 47/55] fix typo making cylinders collide as sphere --- libraries/entities/src/ShapeEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 4115a606df..2771d22cdb 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -297,7 +297,7 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { const float MIN_RELATIVE_SPHERICAL_ERROR = 0.001f; if (diameter > MIN_DIAMETER && fabsf(diameter - entityDimensions.z) / diameter < MIN_RELATIVE_SPHERICAL_ERROR) { - _collisionShapeType = SHAPE_TYPE_SPHERE; + _collisionShapeType = SHAPE_TYPE_CYLINDER_Y; } else if (hullShapeCalculator) { hullShapeCalculator(this, info); _collisionShapeType = SHAPE_TYPE_SIMPLE_HULL; From e68ce976977e6b4fb6aa5eb26f6d4ad28396f0f2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 15 Nov 2017 11:19:54 -0800 Subject: [PATCH 48/55] Remove the number of socket change tracking --- interface/src/Application.cpp | 2 -- libraries/networking/src/LimitedNodeList.cpp | 2 -- libraries/networking/src/LimitedNodeList.h | 2 -- 3 files changed, 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bd31fc398e..26ed279150 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1700,8 +1700,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo lastLeftHandPose = leftHandPose; lastRightHandPose = rightHandPose; - properties["local_socket_changes"] = DependencyManager::get()->getStat(LOCAL_SOCKET_CHANGE_STAT).toInt(); - UserActivityLogger::getInstance().logAction("stats", properties); }); sendStatsTimer->start(); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 300a445ebd..a9ebc5481d 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "AccountManager.h" @@ -1110,7 +1109,6 @@ void LimitedNodeList::setLocalSocket(const HifiSockAddr& sockAddr) { qCInfo(networking) << "Local socket is" << sockAddr; } else { qCInfo(networking) << "Local socket has changed from" << _localSockAddr << "to" << sockAddr; - DependencyManager::get()->incrementStat(LOCAL_SOCKET_CHANGE_STAT); } _localSockAddr = sockAddr; diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 994f91db19..868e36f160 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -66,8 +66,6 @@ const QHostAddress DEFAULT_ASSIGNMENT_CLIENT_MONITOR_HOSTNAME = QHostAddress::Lo const QString USERNAME_UUID_REPLACEMENT_STATS_KEY = "$username"; -const QString LOCAL_SOCKET_CHANGE_STAT = "LocalSocketChanges"; - typedef std::pair UUIDNodePair; typedef tbb::concurrent_unordered_map NodeHash; From d8b1cb10dfb9a785128e6c1339a7362a89f98a10 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 14 Nov 2017 17:14:49 -0800 Subject: [PATCH 49/55] CR --- assignment-client/src/AssignmentClientMonitor.cpp | 4 ++-- libraries/shared/src/SharedUtil.cpp | 9 +++++---- libraries/shared/src/SharedUtil.h | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/assignment-client/src/AssignmentClientMonitor.cpp b/assignment-client/src/AssignmentClientMonitor.cpp index 97f03d3cb4..1868ccfafe 100644 --- a/assignment-client/src/AssignmentClientMonitor.cpp +++ b/assignment-client/src/AssignmentClientMonitor.cpp @@ -29,7 +29,7 @@ const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor const int WAIT_FOR_CHILD_MSECS = 1000; #ifdef Q_OS_WIN -HANDLE JOB_OBJECT = createJobObject(); +HANDLE PROCESS_GROUP = createProcessGroup(); #endif AssignmentClientMonitor::AssignmentClientMonitor(const unsigned int numAssignmentClientForks, @@ -207,7 +207,7 @@ void AssignmentClientMonitor::spawnChildClient() { assignmentClient->start(QCoreApplication::applicationFilePath(), _childArguments); #ifdef Q_OS_WIN - addProcessToJobObject(JOB_OBJECT, assignmentClient->processId()); + addProcessToGroup(PROCESS_GROUP, assignmentClient->processId()); #endif QString stdoutPath, stderrPath; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index cbfffde762..38a7a3165f 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -1124,7 +1124,7 @@ QString getLastErrorAsString() { LPSTR messageBuffer = nullptr; size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + nullptr, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, nullptr); auto message = QString::fromLocal8Bit(messageBuffer, (int)size); @@ -1134,7 +1134,8 @@ QString getLastErrorAsString() { return message; } -void* createJobObject() { +// All processes in the group will shut down with the process creating the group +void* createProcessGroup() { HANDLE jobObject = CreateJobObject(nullptr, nullptr); if (jobObject == nullptr) { qWarning() << "Could NOT create job object:" << getLastErrorAsString(); @@ -1155,12 +1156,12 @@ void* createJobObject() { return jobObject; } -void addProcessToJobObject(void *jobObject, qint64 processId) { +void addProcessToGroup(void* processGroup, qint64 processId) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if (hProcess == nullptr) { qCritical() << "Could NOT open process" << getLastErrorAsString(); } - if (!AssignProcessToJobObject(jobObject, hProcess)) { + if (!AssignProcessToJobObject(processGroup, hProcess)) { qCritical() << "Could NOT assign process to job object" << getLastErrorAsString(); } } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index fb5090200b..25051d45ac 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -240,8 +240,8 @@ void watchParentProcess(int parentPID); #ifdef Q_OS_WIN -void* createJobObject(); -void addProcessToJobObject(void* jobObject, qint64 processId); +void* createProcessGroup(); +void addProcessToGroup(void* processGroup, qint64 processId); #endif #endif // hifi_SharedUtil_h From e8c4878c8f0efdac37387742b7158c4fd12c04bc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 15 Nov 2017 11:25:18 -0800 Subject: [PATCH 50/55] Fix rezzing non-JSON marketplace items --- .../resources/qml/hifi/commerce/checkout/Checkout.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 3e7c23f2dd..6c4e020694 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -476,7 +476,9 @@ Rectangle { commerce.buy(itemId, itemPrice, true); } } else { - sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); + if (urlHandler.canHandleUrl(itemHref)) { + urlHandler.handleUrl(itemHref); + } } } } @@ -594,9 +596,7 @@ Rectangle { anchors.right: parent.right; text: root.isWearable ? "Wear It" : "Rez It" onClicked: { - if (urlHandler.canHandleUrl(root.itemHref)) { - urlHandler.handleUrl(root.itemHref); - } + sendToScript({method: 'checkout_rezClicked', itemHref: root.itemHref, isWearable: root.isWearable}); rezzedNotifContainer.visible = true; rezzedNotifContainerTimer.start(); } From b49891c0f868caab7c99e58011994e4e470fdd6c Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 15 Nov 2017 11:27:42 -0800 Subject: [PATCH 51/55] Bug fix for MyAvatar.getEyeHeight() --- libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 49d2431098..6bf9cc1666 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1579,7 +1579,7 @@ float Avatar::getEyeHeight() const { if (QThread::currentThread() != thread()) { float result = DEFAULT_AVATAR_EYE_HEIGHT; - BLOCKING_INVOKE_METHOD(const_cast(this), "getHeight", Q_RETURN_ARG(float, result)); + BLOCKING_INVOKE_METHOD(const_cast(this), "getEyeHeight", Q_RETURN_ARG(float, result)); return result; } From 78d89d886feae4f179cdf0af7b348607d9e7d4b4 Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Wed, 15 Nov 2017 23:55:21 +0300 Subject: [PATCH 52/55] 9264 dismiss keyboard after user finished typing in marketplace search bar and hit search or return key --- scripts/system/html/js/marketplacesInject.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 4b127baef8..1346bcd750 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -318,6 +318,15 @@ }); } + function injectUnfocusOnSearch() { + // unfocus input field on search, thus hiding virtual keyboard + $('#search-box').on('submit', function () { + if (document.activeElement) { + document.activeElement.blur(); + } + }); + } + function injectHiFiCode() { if (commerceMode) { maybeAddLogInButton(); @@ -347,6 +356,8 @@ maybeAddPurchasesButton(); } } + + injectUnfocusOnSearch(); } function injectHiFiItemPageCode() { @@ -386,6 +397,8 @@ maybeAddPurchasesButton(); } } + + injectUnfocusOnSearch(); } function updateClaraCode() { From 9564b7567b941b0c1bbc2cd749c14b5948b00eec Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 15 Nov 2017 13:39:21 -0800 Subject: [PATCH 53/55] fixing tablet in 3d person --- scripts/system/controllers/controllerDispatcher.js | 4 ++-- .../system/controllers/controllerModules/overlayLaserInput.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 37cd173cfa..ee3b90d7b5 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -389,7 +389,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Controller.enableMapping(MAPPING_NAME); this.leftControllerRayPick = RayPick.createRayPick({ - joint: "_CONTROLLER_LEFTHAND", + joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, @@ -403,7 +403,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); posOffset: getGrabPointSphereOffset(Controller.Standard.LeftHand, true) }); this.rightControllerRayPick = RayPick.createRayPick({ - joint: "_CONTROLLER_RIGHTHAND", + joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, enabled: true, maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, diff --git a/scripts/system/controllers/controllerModules/overlayLaserInput.js b/scripts/system/controllers/controllerModules/overlayLaserInput.js index 2d27f160c1..538a943901 100644 --- a/scripts/system/controllers/controllerModules/overlayLaserInput.js +++ b/scripts/system/controllers/controllerModules/overlayLaserInput.js @@ -362,7 +362,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.laserPointer = LaserPointers.createLaserPointer({ - joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", + joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", filter: RayPick.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), From bf0d55aa9892568a38d06a88ed768e97b4cf176a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 15 Nov 2017 15:04:24 -0700 Subject: [PATCH 54/55] 9267 Fix not restoring animations after changing view modes --- libraries/animation/src/Rig.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index f06156874b..78aa1f4ba8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -179,6 +179,11 @@ void Rig::restoreRoleAnimation(const QString& role) { } else { qCWarning(animation) << "Rig::restoreRoleAnimation could not find role " << role; } + + auto statesIter = _roleAnimStates.find(role); + if (statesIter != _roleAnimStates.end()) { + _roleAnimStates.erase(statesIter); + } } } else { qCWarning(animation) << "Rig::overrideRoleAnimation avatar not ready yet"; From 7bbc719d799b0f78a79e5288792e6db2907ceaf1 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 16 Nov 2017 08:53:12 -0800 Subject: [PATCH 55/55] Fix for black screen on HMD derived display plugins --- interface/src/Application.cpp | 3 +++ interface/src/Application.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 26ed279150..c53b2c993c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1823,6 +1823,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Preload Tablet sounds DependencyManager::get()->preloadSounds(); + _pendingIdleEvent = false; + _pendingRenderEvent = false; + qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); } diff --git a/interface/src/Application.h b/interface/src/Application.h index fbfb3979be..19a6dfdac1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -708,7 +708,7 @@ private: friend class RenderEventHandler; - std::atomic _pendingIdleEvent { false }; - std::atomic _pendingRenderEvent { false }; + std::atomic _pendingIdleEvent { true }; + std::atomic _pendingRenderEvent { true }; }; #endif // hifi_Application_h