mirror of
https://github.com/lubosz/overte.git
synced 2025-04-25 00:03:16 +02:00
Merge branch 'bloom' of github.com:SamGondelman/hifi into bloom
This commit is contained in:
commit
397ff6fb3b
11 changed files with 434 additions and 125 deletions
18
libraries/graphics/src/graphics/Bloom.cpp
Normal file
18
libraries/graphics/src/graphics/Bloom.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Bloom.cpp
|
||||
// libraries/graphics/src/graphics
|
||||
//
|
||||
// Created by Sam Gondelman on 8/7/2018
|
||||
// Copyright 2018 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 "Bloom.h"
|
||||
|
||||
using namespace graphics;
|
||||
|
||||
const float Bloom::INITIAL_BLOOM_INTENSITY { 0.25f };
|
||||
const float Bloom::INITIAL_BLOOM_THRESHOLD { 0.7f };
|
||||
const float Bloom::INITIAL_BLOOM_SIZE { 0.9f };
|
44
libraries/graphics/src/graphics/Bloom.h
Normal file
44
libraries/graphics/src/graphics/Bloom.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// Bloom.h
|
||||
// libraries/graphics/src/graphics
|
||||
//
|
||||
// Created by Sam Gondelman on 8/7/2018
|
||||
// Copyright 2018 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_model_Bloom_h
|
||||
#define hifi_model_Bloom_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace graphics {
|
||||
class Bloom {
|
||||
public:
|
||||
// Initial values
|
||||
static const float INITIAL_BLOOM_INTENSITY;
|
||||
static const float INITIAL_BLOOM_THRESHOLD;
|
||||
static const float INITIAL_BLOOM_SIZE;
|
||||
|
||||
Bloom() {}
|
||||
|
||||
void setBloomIntensity(const float bloomIntensity) { _bloomIntensity = bloomIntensity; }
|
||||
void setBloomThreshold(const float bloomThreshold) { _bloomThreshold = bloomThreshold; }
|
||||
void setBloomSize(const float bloomSize) { _bloomSize = bloomSize; }
|
||||
void setBloomActive(const bool isBloomActive) { _isBloomActive = isBloomActive; }
|
||||
|
||||
float getBloomIntensity() { return _bloomIntensity; }
|
||||
float getBloomThreshold() { return _bloomThreshold; }
|
||||
float getBloomSize() { return _bloomSize; }
|
||||
bool getBloomActive() { return _isBloomActive; }
|
||||
|
||||
private:
|
||||
bool _isBloomActive { false };
|
||||
float _bloomIntensity { INITIAL_BLOOM_INTENSITY };
|
||||
float _bloomThreshold {INITIAL_BLOOM_THRESHOLD };
|
||||
float _bloomSize { INITIAL_BLOOM_SIZE };
|
||||
};
|
||||
using BloomPointer = std::shared_ptr<Bloom>;
|
||||
}
|
||||
#endif // hifi_model_Bloom_h
|
|
@ -25,11 +25,7 @@ BloomThreshold::BloomThreshold(unsigned int downsamplingFactor) {
|
|||
_parameters.edit()._sampleCount = downsamplingFactor;
|
||||
}
|
||||
|
||||
void BloomThreshold::configure(const Config& config) {
|
||||
if (_parameters.get()._threshold != config.threshold) {
|
||||
_parameters.edit()._threshold = config.threshold;
|
||||
}
|
||||
}
|
||||
void BloomThreshold::configure(const Config& config) {}
|
||||
|
||||
void BloomThreshold::run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs) {
|
||||
assert(renderContext->args);
|
||||
|
@ -39,6 +35,7 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
|
||||
const auto frameTransform = inputs.get0();
|
||||
const auto inputFrameBuffer = inputs.get1();
|
||||
const auto bloom = inputs.get2();
|
||||
|
||||
assert(inputFrameBuffer->hasColor());
|
||||
|
||||
|
@ -68,6 +65,28 @@ void BloomThreshold::run(const render::RenderContextPointer& renderContext, cons
|
|||
|
||||
glm::ivec4 viewport{ 0, 0, bufferSize.x, bufferSize.y };
|
||||
|
||||
if (!bloom || !bloom->getBloomActive()) {
|
||||
outputs = _outputBuffer;
|
||||
return;
|
||||
}
|
||||
|
||||
_parameters.edit()._threshold = bloom->getBloomThreshold();
|
||||
|
||||
//{
|
||||
// std::string blurName { "BloomBlurN" };
|
||||
// auto sigma = 0.5f + bloom->getBloomSize() * 3.5f;
|
||||
// auto task = static_cast<render::Task::TaskConcept*>(this);
|
||||
|
||||
// for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) {
|
||||
// blurName.back() = '0' + i;
|
||||
// auto blurJobIt = task->editJob(blurName);
|
||||
// assert(blurJobIt != task->_jobs.end());
|
||||
// auto& gaussianBlur = blurJobIt->edit<render::BlurGaussian>();
|
||||
// auto gaussianBlurParams = gaussianBlur.getParameters();
|
||||
// gaussianBlurParams->setFilterGaussianTaps(9, sigma);
|
||||
// }
|
||||
//}
|
||||
|
||||
gpu::doInBatch("BloomThreshold::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
||||
|
@ -90,16 +109,7 @@ BloomApply::BloomApply() {
|
|||
|
||||
}
|
||||
|
||||
void BloomApply::configure(const Config& config) {
|
||||
const auto newIntensity = config.intensity / 3.0f;
|
||||
|
||||
if (_parameters.get()._intensities.x != newIntensity) {
|
||||
auto& parameters = _parameters.edit();
|
||||
parameters._intensities.x = newIntensity;
|
||||
parameters._intensities.y = newIntensity;
|
||||
parameters._intensities.z = newIntensity;
|
||||
}
|
||||
}
|
||||
void BloomApply::configure(const Config& config) {}
|
||||
|
||||
void BloomApply::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) {
|
||||
assert(renderContext->args);
|
||||
|
@ -123,8 +133,19 @@ 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 auto bloom = inputs.get4();
|
||||
const glm::ivec4 viewport{ 0, 0, framebufferSize.x, framebufferSize.y };
|
||||
|
||||
if (!bloom || !bloom->getBloomActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto newIntensity = bloom->getBloomIntensity() / 3.0f;
|
||||
auto& parameters = _parameters.edit();
|
||||
parameters._intensities.x = newIntensity;
|
||||
parameters._intensities.y = newIntensity;
|
||||
parameters._intensities.z = newIntensity;
|
||||
|
||||
gpu::doInBatch("BloomApply::run", args->_context, [&](gpu::Batch& batch) {
|
||||
batch.enableStereo(false);
|
||||
|
||||
|
@ -266,43 +287,9 @@ void DebugBloom::run(const render::RenderContextPointer& renderContext, const In
|
|||
});
|
||||
}
|
||||
|
||||
void BloomConfig::setIntensity(float value) {
|
||||
auto task = static_cast<render::Task::TaskConcept*>(_task);
|
||||
auto blurJobIt = task->editJob("BloomApply");
|
||||
assert(blurJobIt != task->_jobs.end());
|
||||
blurJobIt->getConfiguration()->setProperty("intensity", value);
|
||||
}
|
||||
BloomEffect::BloomEffect() {}
|
||||
|
||||
float BloomConfig::getIntensity() const {
|
||||
auto task = static_cast<render::Task::TaskConcept*>(_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 = 0.5f+value*3.5f;
|
||||
auto task = static_cast<render::Task::TaskConcept*>(_task);
|
||||
|
||||
for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) {
|
||||
blurName.back() = '0' + i;
|
||||
auto blurJobIt = task->editJob(blurName);
|
||||
assert(blurJobIt != task->_jobs.end());
|
||||
auto& gaussianBlur = blurJobIt->edit<render::BlurGaussian>();
|
||||
auto gaussianBlurParams = gaussianBlur.getParameters();
|
||||
gaussianBlurParams->setFilterGaussianTaps(9, sigma);
|
||||
}
|
||||
auto blurJobIt = task->getJob("BloomApply");
|
||||
assert(blurJobIt != task->_jobs.end());
|
||||
blurJobIt->getConfiguration()->setProperty("sigma", sigma);
|
||||
}
|
||||
|
||||
Bloom::Bloom() {
|
||||
|
||||
}
|
||||
|
||||
void Bloom::configure(const Config& config) {
|
||||
void BloomEffect::configure(const Config& config) {
|
||||
std::string blurName{ "BloomBlurN" };
|
||||
|
||||
for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) {
|
||||
|
@ -312,7 +299,7 @@ void Bloom::configure(const Config& config) {
|
|||
}
|
||||
}
|
||||
|
||||
void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||
void BloomEffect::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||
// Start by computing threshold of color buffer input at quarter resolution
|
||||
const auto bloomInputBuffer = task.addJob<BloomThreshold>("BloomThreshold", inputs, 4U);
|
||||
|
||||
|
@ -325,7 +312,7 @@ void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying
|
|||
const auto& frameBuffer = input[1];
|
||||
|
||||
// Mix all blur levels at quarter resolution
|
||||
const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2).asVarying();
|
||||
const auto applyInput = BloomApply::Inputs(bloomInputBuffer, blurFB0, blurFB1, blurFB2, input.get2()).asVarying();
|
||||
task.addJob<BloomApply>("BloomApply", applyInput);
|
||||
// And then blend result in additive manner on top of final color buffer
|
||||
const auto drawInput = BloomDraw::Inputs(frameBuffer, bloomInputBuffer).asVarying();
|
||||
|
|
|
@ -14,42 +14,21 @@
|
|||
|
||||
#include <render/Engine.h>
|
||||
|
||||
#include "graphics/Bloom.h"
|
||||
|
||||
#include "DeferredFrameTransform.h"
|
||||
|
||||
class BloomConfig : public render::Task::Config {
|
||||
Q_OBJECT
|
||||
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(false) {}
|
||||
|
||||
float size{ 0.7f };
|
||||
|
||||
void setIntensity(float value);
|
||||
float getIntensity() const;
|
||||
void setSize(float value);
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class BloomThresholdConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
float threshold{ 0.9f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class BloomThreshold {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<DeferredFrameTransformPointer, gpu::FramebufferPointer>;
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, graphics::BloomPointer>;
|
||||
using Outputs = gpu::FramebufferPointer;
|
||||
using Config = BloomThresholdConfig;
|
||||
using JobModel = render::Job::ModelIO<BloomThreshold, Inputs, Outputs, Config>;
|
||||
|
@ -71,21 +50,11 @@ private:
|
|||
|
||||
class BloomApplyConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float intensity MEMBER intensity NOTIFY dirty)
|
||||
Q_PROPERTY(float sigma MEMBER sigma NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
float intensity{ 0.25f };
|
||||
float sigma{ 1.0f };
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class BloomApply {
|
||||
public:
|
||||
using Inputs = render::VaryingSet4<gpu::FramebufferPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, gpu::FramebufferPointer>;
|
||||
using Inputs = render::VaryingSet5<gpu::FramebufferPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, gpu::FramebufferPointer, graphics::BloomPointer>;
|
||||
using Config = BloomApplyConfig;
|
||||
using JobModel = render::Job::ModelI<BloomApply, Inputs, Config>;
|
||||
|
||||
|
@ -118,7 +87,7 @@ private:
|
|||
|
||||
class DebugBloomConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int mode MEMBER mode NOTIFY dirty)
|
||||
Q_PROPERTY(int mode MEMBER mode NOTIFY dirty)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -155,13 +124,13 @@ private:
|
|||
DebugBloomConfig::Mode _mode;
|
||||
};
|
||||
|
||||
class Bloom {
|
||||
class BloomEffect {
|
||||
public:
|
||||
using Inputs = render::VaryingSet2<DeferredFrameTransformPointer, gpu::FramebufferPointer>;
|
||||
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, gpu::FramebufferPointer, graphics::BloomPointer>;
|
||||
using Config = BloomConfig;
|
||||
using JobModel = render::Task::ModelI<Bloom, Inputs, Config>;
|
||||
using JobModel = render::Task::ModelI<BloomEffect, Inputs, Config>;
|
||||
|
||||
Bloom();
|
||||
BloomEffect();
|
||||
|
||||
void configure(const Config& config);
|
||||
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs);
|
||||
|
|
80
libraries/render-utils/src/BloomStage.cpp
Normal file
80
libraries/render-utils/src/BloomStage.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// BloomStage.cpp
|
||||
//
|
||||
// Created by Sam Gondelman on 8/7/2018
|
||||
// Copyright 2018 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 "BloomStage.h"
|
||||
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include <gpu/Context.h>
|
||||
|
||||
std::string BloomStage::_stageName { "BLOOM_STAGE"};
|
||||
const BloomStage::Index BloomStage::INVALID_INDEX { render::indexed_container::INVALID_INDEX };
|
||||
|
||||
FetchBloomStage::FetchBloomStage() {
|
||||
_bloom = std::make_shared<graphics::Bloom>();
|
||||
}
|
||||
|
||||
void FetchBloomStage::configure(const Config& config) {
|
||||
_bloom->setBloomIntensity(config.bloomIntensity);
|
||||
_bloom->setBloomThreshold(config.bloomThreshold);
|
||||
_bloom->setBloomSize(config.bloomSize);
|
||||
_bloom->setBloomActive(config.isBloomActive);
|
||||
}
|
||||
|
||||
BloomStage::Index BloomStage::findBloom(const BloomPointer& bloom) const {
|
||||
auto found = _bloomMap.find(bloom);
|
||||
if (found != _bloomMap.end()) {
|
||||
return INVALID_INDEX;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
BloomStage::Index BloomStage::addBloom(const BloomPointer& bloom) {
|
||||
auto found = _bloomMap.find(bloom);
|
||||
if (found == _bloomMap.end()) {
|
||||
auto bloomId = _blooms.newElement(bloom);
|
||||
// Avoid failing to allocate a bloom, just pass
|
||||
if (bloomId != INVALID_INDEX) {
|
||||
// Insert the bloom and its index in the reverse map
|
||||
_bloomMap.insert(BloomMap::value_type(bloom, bloomId));
|
||||
}
|
||||
return bloomId;
|
||||
} else {
|
||||
return (*found).second;
|
||||
}
|
||||
}
|
||||
|
||||
BloomStage::BloomPointer BloomStage::removeBloom(Index index) {
|
||||
BloomPointer removed = _blooms.freeElement(index);
|
||||
if (removed) {
|
||||
_bloomMap.erase(removed);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
BloomStageSetup::BloomStageSetup() {}
|
||||
|
||||
void BloomStageSetup::run(const render::RenderContextPointer& renderContext) {
|
||||
auto stage = renderContext->_scene->getStage(BloomStage::getName());
|
||||
if (!stage) {
|
||||
renderContext->_scene->resetStage(BloomStage::getName(), std::make_shared<BloomStage>());
|
||||
}
|
||||
}
|
||||
|
||||
void FetchBloomStage::run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom) {
|
||||
auto bloomStage = renderContext->_scene->getStage<BloomStage>();
|
||||
assert(bloomStage);
|
||||
|
||||
bloom = nullptr;
|
||||
if (bloomStage->_currentFrame._blooms.size() != 0) {
|
||||
auto bloomId = bloomStage->_currentFrame._blooms.front();
|
||||
bloom = bloomStage->getBloom(bloomId);
|
||||
}
|
||||
}
|
122
libraries/render-utils/src/BloomStage.h
Normal file
122
libraries/render-utils/src/BloomStage.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
//
|
||||
// BloomStage.h
|
||||
|
||||
// Created by Sam Gondelman on 8/7/2018
|
||||
// Copyright 2018 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_BloomStage_h
|
||||
#define hifi_render_utils_BloomStage_h
|
||||
|
||||
#include <graphics/Stage.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <render/IndexedContainer.h>
|
||||
#include <render/Stage.h>
|
||||
|
||||
#include <render/Forward.h>
|
||||
#include <render/DrawTask.h>
|
||||
#include <graphics/Bloom.h>
|
||||
|
||||
// Bloom stage to set up bloom-related rendering tasks
|
||||
class BloomStage : public render::Stage {
|
||||
public:
|
||||
static std::string _stageName;
|
||||
static const std::string& getName() { return _stageName; }
|
||||
|
||||
using Index = render::indexed_container::Index;
|
||||
static const Index INVALID_INDEX;
|
||||
static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; }
|
||||
|
||||
using BloomPointer = graphics::BloomPointer;
|
||||
using Blooms = render::indexed_container::IndexedPointerVector<graphics::Bloom>;
|
||||
using BloomMap = std::unordered_map<BloomPointer, Index>;
|
||||
|
||||
using BloomIndices = std::vector<Index>;
|
||||
|
||||
Index findBloom(const BloomPointer& bloom) const;
|
||||
Index addBloom(const BloomPointer& bloom);
|
||||
|
||||
BloomPointer removeBloom(Index index);
|
||||
|
||||
bool checkBloomId(Index index) const { return _blooms.checkIndex(index); }
|
||||
|
||||
Index getNumBlooms() const { return _blooms.getNumElements(); }
|
||||
Index getNumFreeBlooms() const { return _blooms.getNumFreeIndices(); }
|
||||
Index getNumAllocatedBlooms() const { return _blooms.getNumAllocatedIndices(); }
|
||||
|
||||
BloomPointer getBloom(Index bloomId) const {
|
||||
return _blooms.get(bloomId);
|
||||
}
|
||||
|
||||
Blooms _blooms;
|
||||
BloomMap _bloomMap;
|
||||
|
||||
class Frame {
|
||||
public:
|
||||
Frame() {}
|
||||
|
||||
void clear() { _blooms.clear(); }
|
||||
|
||||
void pushBloom(BloomStage::Index index) { _blooms.emplace_back(index); }
|
||||
|
||||
BloomStage::BloomIndices _blooms;
|
||||
};
|
||||
|
||||
Frame _currentFrame;
|
||||
};
|
||||
using BloomStagePointer = std::shared_ptr<BloomStage>;
|
||||
|
||||
class BloomStageSetup {
|
||||
public:
|
||||
using JobModel = render::Job::Model<BloomStageSetup>;
|
||||
|
||||
BloomStageSetup();
|
||||
void run(const render::RenderContextPointer& renderContext);
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
class FetchBloomConfig : public render::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(float bloomIntensity MEMBER bloomIntensity WRITE setBloomIntensity NOTIFY dirty);
|
||||
Q_PROPERTY(float bloomThreshold MEMBER bloomThreshold WRITE setBloomThreshold NOTIFY dirty);
|
||||
Q_PROPERTY(float bloomSize MEMBER bloomSize WRITE setBloomSize NOTIFY dirty);
|
||||
Q_PROPERTY(bool isBloomActive MEMBER isBloomActive WRITE setBloomActive NOTIFY dirty);
|
||||
|
||||
public:
|
||||
FetchBloomConfig() : render::Job::Config() {}
|
||||
|
||||
float bloomIntensity { graphics::Bloom::INITIAL_BLOOM_INTENSITY };
|
||||
float bloomThreshold { graphics::Bloom::INITIAL_BLOOM_THRESHOLD };
|
||||
float bloomSize { graphics::Bloom::INITIAL_BLOOM_SIZE };
|
||||
|
||||
bool isBloomActive { false };
|
||||
|
||||
public slots:
|
||||
void setBloomIntensity(const float value) { bloomIntensity = value; emit dirty(); }
|
||||
void setBloomThreshold(const float value) { bloomThreshold = value; emit dirty(); }
|
||||
void setBloomSize(const float value) { bloomSize = value; emit dirty(); }
|
||||
void setBloomActive(const bool active) { isBloomActive = active; emit dirty(); }
|
||||
|
||||
signals:
|
||||
void dirty();
|
||||
};
|
||||
|
||||
class FetchBloomStage {
|
||||
public:
|
||||
using Config = FetchBloomConfig;
|
||||
using JobModel = render::Job::ModelO<FetchBloomStage, graphics::BloomPointer, Config>;
|
||||
|
||||
FetchBloomStage();
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const render::RenderContextPointer& renderContext, graphics::BloomPointer& bloom);
|
||||
|
||||
private:
|
||||
graphics::BloomPointer _bloom;
|
||||
};
|
||||
#endif
|
|
@ -163,6 +163,5 @@ public:
|
|||
|
||||
private:
|
||||
graphics::HazePointer _haze;
|
||||
gpu::PipelinePointer _hazePipeline;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "TextureCache.h"
|
||||
#include "ZoneRenderer.h"
|
||||
#include "FadeEffect.h"
|
||||
#include "BloomStage.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
|
||||
#include "AmbientOcclusionEffect.h"
|
||||
|
@ -171,7 +172,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto velocityBufferOutputs = task.addJob<VelocityBufferPass>("VelocityBuffer", velocityBufferInputs);
|
||||
const auto velocityBuffer = velocityBufferOutputs.getN<VelocityBufferPass::Outputs>(0);
|
||||
|
||||
// Clear Light, Haze and Skybox Stages and render zones from the general metas bucket
|
||||
// Clear Light, Haze, Bloom, and Skybox Stages and render zones from the general metas bucket
|
||||
const auto zones = task.addJob<ZoneRendererTask>("ZoneRenderer", metas);
|
||||
|
||||
// Draw Lights just add the lights to the current list of lights to deal with. NOt really gpu job for now.
|
||||
|
@ -240,8 +241,9 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
task.addJob<Antialiasing>("Antialiasing", antialiasingInputs);
|
||||
|
||||
// Add bloom
|
||||
const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying();
|
||||
task.addJob<Bloom>("Bloom", bloomInputs);
|
||||
const auto bloomModel = task.addJob<FetchBloomStage>("BloomModel");
|
||||
const auto bloomInputs = BloomEffect::Inputs(deferredFrameTransform, lightingFramebuffer, bloomModel).asVarying();
|
||||
task.addJob<BloomEffect>("Bloom", bloomInputs);
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
const auto toneMappingInputs = ToneMappingDeferred::Inputs(lightingFramebuffer, scaledPrimaryFramebuffer).asVarying();
|
||||
|
|
|
@ -21,11 +21,12 @@
|
|||
#include "StencilMaskPass.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
|
||||
#include "render-utils/ShaderConstants.h"
|
||||
#include "StencilMaskPass.h"
|
||||
#include "DeferredLightingEffect.h"
|
||||
|
||||
#include "BloomStage.h"
|
||||
|
||||
namespace ru {
|
||||
using render_utils::slot::texture::Texture;
|
||||
using render_utils::slot::buffer::Buffer;
|
||||
|
@ -63,7 +64,7 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu
|
|||
}
|
||||
|
||||
void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) {
|
||||
// Grab light, background and haze stages and clear them
|
||||
// Grab light, background, haze, and bloom stages and clear them
|
||||
auto lightStage = context->_scene->getStage<LightStage>();
|
||||
assert(lightStage);
|
||||
lightStage->_currentFrame.clear();
|
||||
|
@ -76,6 +77,10 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs)
|
|||
assert(hazeStage);
|
||||
hazeStage->_currentFrame.clear();
|
||||
|
||||
auto bloomStage = context->_scene->getStage<BloomStage>();
|
||||
assert(bloomStage);
|
||||
bloomStage->_currentFrame.clear();
|
||||
|
||||
// call render over the zones to grab their components in the correct order first...
|
||||
render::renderItems(context, inputs);
|
||||
|
||||
|
@ -84,6 +89,7 @@ void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs)
|
|||
lightStage->_currentFrame.pushAmbientLight(lightStage->getDefaultLight());
|
||||
backgroundStage->_currentFrame.pushBackground(0);
|
||||
hazeStage->_currentFrame.pushHaze(0);
|
||||
bloomStage->_currentFrame.pushBloom(0);
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() {
|
||||
|
|
|
@ -678,6 +678,52 @@
|
|||
</div>
|
||||
</fieldset-->
|
||||
</fieldset>
|
||||
<fieldset class="minor">
|
||||
<legend class="sub-section-header zone-group zone-section">
|
||||
Bloom
|
||||
</legend>
|
||||
<form>
|
||||
<input type="radio" name="bloomMode" value="inherit" id="property-zone-bloom-mode-inherit" checked> Inherit
|
||||
<input type="radio" name="bloomMode" value="disabled" id="property-zone-bloom-mode-disabled"> Off
|
||||
<input type="radio" name="bloomMode" value="enabled" id="property-zone-bloom-mode-enabled"> On
|
||||
</form>
|
||||
<fieldset class="zone-group zone-section bloom-section property gen fstuple">
|
||||
<div class="tuple">
|
||||
<div>
|
||||
<br>
|
||||
<table>
|
||||
<td><label>Bloom Intensity 0</label></td>
|
||||
<td><input type="range" class="slider" id="property-zone-bloom-intensity" min="0" max="1" step="0.01"></td>
|
||||
<td><label>1</label>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="zone-group zone-section bloom-section property gen fstuple">
|
||||
<div class="tuple">
|
||||
<div>
|
||||
<br>
|
||||
<table>
|
||||
<td><label>Bloom Threshold 0</label></td>
|
||||
<td><input type="range" class="slider" id="property-zone-bloom-threshold" min="0" max="1" step="0.01"></td>
|
||||
<td><label>1</label>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="zone-group zone-section bloom-section property gen fstuple">
|
||||
<div class="tuple">
|
||||
<div>
|
||||
<br>
|
||||
<table>
|
||||
<td><label>Bloom Size 0</label></td>
|
||||
<td><input type="range" class="slider" id="property-zone-bloom-size" min="0" max="2" step="0.01"></td>
|
||||
<td><label>2</label>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
<fieldset id="text" class="major">
|
||||
<legend class="section-header text-group text-section">
|
||||
|
|
|
@ -839,7 +839,7 @@ function loaded() {
|
|||
var elZoneHazeModeInherit = document.getElementById("property-zone-haze-mode-inherit");
|
||||
var elZoneHazeModeDisabled = document.getElementById("property-zone-haze-mode-disabled");
|
||||
var elZoneHazeModeEnabled = document.getElementById("property-zone-haze-mode-enabled");
|
||||
|
||||
|
||||
var elZoneHazeRange = document.getElementById("property-zone-haze-range");
|
||||
var elZoneHazeColor = document.getElementById("property-zone-haze-color");
|
||||
var elZoneHazeColorRed = document.getElementById("property-zone-haze-color-red");
|
||||
|
@ -858,6 +858,15 @@ function loaded() {
|
|||
|
||||
var elZoneHazeBackgroundBlend = document.getElementById("property-zone-haze-background-blend");
|
||||
|
||||
// Bloom
|
||||
var elZoneBloomModeInherit = document.getElementById("property-zone-bloom-mode-inherit");
|
||||
var elZoneBloomModeDisabled = document.getElementById("property-zone-bloom-mode-disabled");
|
||||
var elZoneBloomModeEnabled = document.getElementById("property-zone-bloom-mode-enabled");
|
||||
|
||||
var elZoneBloomIntensity = document.getElementById("property-zone-bloom-intensity");
|
||||
var elZoneBloomThreshold = document.getElementById("property-zone-bloom-threshold");
|
||||
var elZoneBloomSize = document.getElementById("property-zone-bloom-size");
|
||||
|
||||
var elZoneSkyboxColor = document.getElementById("property-zone-skybox-color");
|
||||
var elZoneSkyboxColorRed = document.getElementById("property-zone-skybox-color-red");
|
||||
var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green");
|
||||
|
@ -914,19 +923,19 @@ function loaded() {
|
|||
deleteJSONMaterialEditor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
elTypeIcon.style.display = "none";
|
||||
elType.innerHTML = "<i>No selection</i>";
|
||||
elPropertiesList.className = '';
|
||||
|
||||
|
||||
elID.value = "";
|
||||
elName.value = "";
|
||||
elLocked.checked = false;
|
||||
elVisible.checked = false;
|
||||
|
||||
|
||||
elParentID.value = "";
|
||||
elParentJointIndex.value = "";
|
||||
|
||||
|
||||
elColorRed.value = "";
|
||||
elColorGreen.value = "";
|
||||
elColorBlue.value = "";
|
||||
|
@ -935,15 +944,15 @@ function loaded() {
|
|||
elPositionX.value = "";
|
||||
elPositionY.value = "";
|
||||
elPositionZ.value = "";
|
||||
|
||||
|
||||
elRotationX.value = "";
|
||||
elRotationY.value = "";
|
||||
elRotationZ.value = "";
|
||||
|
||||
|
||||
elDimensionsX.value = "";
|
||||
elDimensionsY.value = "";
|
||||
elDimensionsZ.value = "";
|
||||
|
||||
|
||||
elRegistrationX.value = "";
|
||||
elRegistrationY.value = "";
|
||||
elRegistrationZ.value = "";
|
||||
|
@ -965,14 +974,14 @@ function loaded() {
|
|||
elAccelerationX.value = "";
|
||||
elAccelerationY.value = "";
|
||||
elAccelerationZ.value = "";
|
||||
|
||||
|
||||
elRestitution.value = "";
|
||||
elFriction.value = "";
|
||||
elDensity.value = "";
|
||||
|
||||
|
||||
elCollisionless.checked = false;
|
||||
elDynamic.checked = false;
|
||||
|
||||
|
||||
elCollideStatic.checked = false;
|
||||
elCollideKinematic.checked = false;
|
||||
elCollideDynamic.checked = false;
|
||||
|
@ -989,27 +998,27 @@ function loaded() {
|
|||
elCloneableGroup.style.display = "none";
|
||||
elCloneableLimit.value = "";
|
||||
elCloneableLifetime.value = "";
|
||||
|
||||
showElements(document.getElementsByClassName('can-cast-shadow-section'), true);
|
||||
|
||||
showElements(document.getElementsByClassName('can-cast-shadow-section'), true);
|
||||
elCanCastShadow.checked = false;
|
||||
|
||||
|
||||
elCollisionSoundURL.value = "";
|
||||
elLifetime.value = "";
|
||||
elScriptURL.value = "";
|
||||
elServerScripts.value = "";
|
||||
elHyperlinkHref.value = "";
|
||||
elDescription.value = "";
|
||||
|
||||
|
||||
deleteJSONEditor();
|
||||
elUserData.value = "";
|
||||
showUserDataTextArea();
|
||||
showSaveUserDataButton();
|
||||
showNewJSONEditorButton();
|
||||
|
||||
|
||||
// Shape Properties
|
||||
elShape.value = "Cube";
|
||||
setDropdownText(elShape);
|
||||
|
||||
|
||||
// Light Properties
|
||||
elLightSpotLight.checked = false;
|
||||
elLightColor.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")";
|
||||
|
@ -1020,7 +1029,7 @@ function loaded() {
|
|||
elLightFalloffRadius.value = "";
|
||||
elLightExponent.value = "";
|
||||
elLightCutoff.value = "";
|
||||
|
||||
|
||||
// Model Properties
|
||||
elModelURL.value = "";
|
||||
elCompoundShapeURL.value = "";
|
||||
|
@ -1037,7 +1046,7 @@ function loaded() {
|
|||
elModelAnimationAllowTranslation.checked = false;
|
||||
elModelTextures.value = "";
|
||||
elModelOriginalTextures.value = "";
|
||||
|
||||
|
||||
// Zone Properties
|
||||
elZoneFlyingAllowed.checked = false;
|
||||
elZoneGhostingAllowed.checked = false;
|
||||
|
@ -1067,6 +1076,9 @@ function loaded() {
|
|||
elZoneHazeAltitudeEffect.checked = false;
|
||||
elZoneHazeBaseRef.value = "";
|
||||
elZoneHazeCeiling.value = "";
|
||||
elZoneBloomIntensity.value = "";
|
||||
elZoneBloomThreshold.value = "";
|
||||
elZoneBloomSize.value = "";
|
||||
elZoneSkyboxColor.style.backgroundColor = "rgb(" + 0 + "," + 0 + "," + 0 + ")";
|
||||
elZoneSkyboxColorRed.value = "";
|
||||
elZoneSkyboxColorGreen.value = "";
|
||||
|
@ -1076,7 +1088,8 @@ function loaded() {
|
|||
showElements(document.getElementsByClassName('skybox-section'), true);
|
||||
showElements(document.getElementsByClassName('ambient-section'), true);
|
||||
showElements(document.getElementsByClassName('haze-section'), true);
|
||||
|
||||
showElements(document.getElementsByClassName('bloom-section'), true);
|
||||
|
||||
// Text Properties
|
||||
elTextText.value = "";
|
||||
elTextLineHeight.value = "";
|
||||
|
@ -1089,14 +1102,14 @@ function loaded() {
|
|||
elTextBackgroundColorRed.value = "";
|
||||
elTextBackgroundColorGreen.value = "";
|
||||
elTextBackgroundColorBlue.value = "";
|
||||
|
||||
|
||||
// Image Properties
|
||||
elImageURL.value = "";
|
||||
|
||||
|
||||
// Web Properties
|
||||
elWebSourceURL.value = "";
|
||||
elWebDPI.value = "";
|
||||
|
||||
|
||||
// Material Properties
|
||||
elMaterialURL.value = "";
|
||||
elParentMaterialNameNumber.value = "";
|
||||
|
@ -1107,13 +1120,13 @@ function loaded() {
|
|||
elMaterialMappingScaleX.value = "";
|
||||
elMaterialMappingScaleY.value = "";
|
||||
elMaterialMappingRot.value = "";
|
||||
|
||||
|
||||
deleteJSONMaterialEditor();
|
||||
elMaterialData.value = "";
|
||||
showMaterialDataTextArea();
|
||||
showSaveMaterialDataButton();
|
||||
showNewJSONMaterialEditorButton();
|
||||
|
||||
|
||||
disableProperties();
|
||||
} else if (data.selections.length > 1) {
|
||||
deleteJSONEditor();
|
||||
|
@ -1250,7 +1263,7 @@ function loaded() {
|
|||
elCloneableGroup.style.display = elCloneable.checked ? "block": "none";
|
||||
elCloneableLimit.value = properties.cloneLimit;
|
||||
elCloneableLifetime.value = properties.cloneLifetime;
|
||||
|
||||
|
||||
var grabbablesSet = false;
|
||||
var parsedUserData = {};
|
||||
try {
|
||||
|
@ -1476,6 +1489,14 @@ function loaded() {
|
|||
elZoneHazeBaseRef.value = properties.haze.hazeBaseRef.toFixed(0);
|
||||
elZoneHazeCeiling.value = properties.haze.hazeCeiling.toFixed(0);
|
||||
|
||||
elZoneBloomModeInherit.checked = (properties.bloomMode === 'inherit');
|
||||
elZoneBloomModeDisabled.checked = (properties.bloomMode === 'disabled');
|
||||
elZoneBloomModeEnabled.checked = (properties.bloomMode === 'enabled');
|
||||
|
||||
elZoneBloomIntensity.value = properties.bloom.bloomIntensity.toFixed(2);
|
||||
elZoneBloomThreshold.value = properties.bloom.bloomThreshold.toFixed(2);
|
||||
elZoneBloomSize.value = properties.bloom.bloomSize.toFixed(2);
|
||||
|
||||
elShapeType.value = properties.shapeType;
|
||||
elCompoundShapeURL.value = properties.compoundShapeURL;
|
||||
|
||||
|
@ -1502,6 +1523,9 @@ function loaded() {
|
|||
|
||||
showElements(document.getElementsByClassName('haze-section'),
|
||||
elZoneHazeModeEnabled.checked);
|
||||
|
||||
showElements(document.getElementsByClassName('bloom-section'),
|
||||
elZoneBloomModeEnabled.checked);
|
||||
} else if (properties.type === "PolyVox") {
|
||||
elVoxelVolumeSizeX.value = properties.voxelVolumeSize.x.toFixed(2);
|
||||
elVoxelVolumeSizeY.value = properties.voxelVolumeSize.y.toFixed(2);
|
||||
|
@ -2067,6 +2091,18 @@ function loaded() {
|
|||
elZoneHazeBackgroundBlend.addEventListener('change',
|
||||
createEmitGroupNumberPropertyUpdateFunction('haze', 'hazeBackgroundBlend'));
|
||||
|
||||
// Bloom
|
||||
var bloomModeChanged = createZoneComponentModeChangedFunction('bloomMode',
|
||||
elZoneBloomModeInherit, elZoneBloomModeDisabled, elZoneBloomModeEnabled);
|
||||
|
||||
elZoneBloomModeInherit.addEventListener('change', bloomModeChanged);
|
||||
elZoneBloomModeDisabled.addEventListener('change', bloomModeChanged);
|
||||
elZoneBloomModeEnabled.addEventListener('change', bloomModeChanged);
|
||||
|
||||
elZoneBloomIntensity.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomIntensity'));
|
||||
elZoneBloomThreshold.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomThreshold'));
|
||||
elZoneBloomSize.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('bloom', 'bloomSize'));
|
||||
|
||||
var zoneSkyboxColorChangeFunction = createEmitGroupColorPropertyUpdateFunction('skybox', 'color',
|
||||
elZoneSkyboxColorRed, elZoneSkyboxColorGreen, elZoneSkyboxColorBlue);
|
||||
elZoneSkyboxColorRed.addEventListener('change', zoneSkyboxColorChangeFunction);
|
||||
|
|
Loading…
Reference in a new issue