mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
Multiple gaussians as Unreal. First draft
This commit is contained in:
parent
27b9f3516d
commit
27a0fb62d3
6 changed files with 332 additions and 17 deletions
|
@ -10,18 +10,145 @@
|
|||
//
|
||||
#include "BloomEffect.h"
|
||||
|
||||
#include "gpu/Context.h"
|
||||
#include "gpu/StandardShaderLib.h"
|
||||
|
||||
#include <render/BlurTask.h>
|
||||
|
||||
#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<render::BlurGaussian>();
|
||||
blurConfig->setProperty("mix", value*0.5f);
|
||||
/* auto blurConfig = getConfig<render::BlurGaussian>();
|
||||
blurConfig->setProperty("mix", value*0.5f);*/
|
||||
}
|
||||
|
||||
void BloomConfig::setSize(float value) {
|
||||
auto& blurJob = static_cast<render::Task::TaskConcept*>(_task)->_jobs.front();
|
||||
/* auto& blurJob = static_cast<render::Task::TaskConcept*>(_task)->_jobs.front();
|
||||
auto& gaussianBlur = blurJob.edit<render::BlurGaussian>();
|
||||
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<render::BlurGaussian>();
|
||||
blurConfig->setProperty("filterScale", 3.0f);
|
||||
/* auto blurConfig = config.getConfig<render::BlurGaussian>();
|
||||
blurConfig->setProperty("filterScale", 3.0f);*/
|
||||
}
|
||||
|
||||
void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||
const auto& blurInput = inputs;
|
||||
task.addJob<render::BlurGaussian>("Blur", blurInput);
|
||||
const auto halfSizeBuffer = task.addJob<ThresholdAndDownsampleJob>("BloomThreshold", inputs);
|
||||
|
||||
const auto debugInput = DebugBloom::Inputs(inputs.get<Bloom::Inputs>().get1(), halfSizeBuffer).asVarying();
|
||||
task.addJob<DebugBloom>("DebugBloom", debugInput);
|
||||
}
|
||||
|
|
|
@ -14,27 +14,87 @@
|
|||
|
||||
#include <render/Engine.h>
|
||||
|
||||
#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<DeferredFrameTransformPointer, gpu::FramebufferPointer>;
|
||||
using Outputs = gpu::FramebufferPointer;
|
||||
using Config = ThresholdConfig;
|
||||
using JobModel = render::Job::ModelIO<ThresholdAndDownsampleJob, Inputs, Outputs, Config>;
|
||||
|
||||
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<gpu::FramebufferPointer, gpu::FramebufferPointer>;
|
||||
using Config = DebugBloomConfig;
|
||||
using JobModel = render::Job::ModelI<DebugBloom, Inputs, Config>;
|
||||
|
||||
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<DeferredFrameTransformPointer, gpu::FramebufferPointer>;
|
||||
using Config = BloomConfig;
|
||||
using JobModel = render::Task::ModelI<Bloom, Inputs, Config>;
|
||||
|
||||
Bloom();
|
||||
|
|
40
libraries/render-utils/src/BloomThreshold.slf
Normal file
40
libraries/render-utils/src/BloomThreshold.slf
Normal file
|
@ -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);
|
||||
}
|
|
@ -170,7 +170,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
|
|||
const auto toneAndPostRangeTimer = task.addJob<BeginGPURangeTimer>("BeginToneAndPostRangeTimer", "PostToneOverlaysAntialiasing");
|
||||
|
||||
// Add bloom
|
||||
const auto bloomInputs = lightingFramebuffer;
|
||||
const auto bloomInputs = Bloom::Inputs(deferredFrameTransform, lightingFramebuffer).asVarying();
|
||||
task.addJob<Bloom>("Bloom", bloomInputs);
|
||||
|
||||
// Lighting Buffer ready for tone mapping
|
||||
|
|
66
scripts/developer/utilities/render/bloom.qml
Normal file
66
scripts/developer/utilities/render/bloom.qml
Normal file
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
20
scripts/developer/utilities/render/debugBloom.js
Normal file
20
scripts/developer/utilities/render/debugBloom.js
Normal file
|
@ -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(); });
|
Loading…
Reference in a new issue