mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 15:18:35 +02:00
Threshold now doesn't downsample anymore. Done in separate pass
This commit is contained in:
parent
76305c5285
commit
f55d44dfc3
4 changed files with 44 additions and 61 deletions
|
@ -21,15 +21,15 @@
|
||||||
|
|
||||||
#define BLOOM_BLUR_LEVEL_COUNT 3
|
#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;
|
_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);
|
||||||
assert(renderContext->args->hasViewFrustum());
|
assert(renderContext->args->hasViewFrustum());
|
||||||
|
|
||||||
|
@ -40,25 +40,23 @@ void ThresholdAndDownsampleJob::run(const render::RenderContextPointer& renderCo
|
||||||
|
|
||||||
assert(inputFrameBuffer->hasColor());
|
assert(inputFrameBuffer->hasColor());
|
||||||
|
|
||||||
auto inputColor = inputFrameBuffer->getRenderBuffer(0);
|
auto inputBuffer = inputFrameBuffer->getRenderBuffer(0);
|
||||||
auto sourceViewport = args->_viewport;
|
auto sourceViewport = args->_viewport;
|
||||||
auto fullSize = glm::ivec2(inputColor->getDimensions());
|
auto bufferSize = glm::ivec2(inputBuffer->getDimensions());
|
||||||
auto halfSize = fullSize / 2;
|
|
||||||
auto halfViewport = args->_viewport >> 1;
|
|
||||||
|
|
||||||
if (!_downsampledBuffer || _downsampledBuffer->getSize().x != halfSize.x || _downsampledBuffer->getSize().y != halfSize.y) {
|
if (!_outputBuffer || _outputBuffer->getSize() != inputFrameBuffer->getSize()) {
|
||||||
auto colorTexture = gpu::TexturePointer(gpu::Texture::createRenderBuffer(inputColor->getTexelFormat(), halfSize.x, halfSize.y,
|
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)));
|
gpu::Texture::SINGLE_MIP, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_LINEAR_MIP_POINT)));
|
||||||
|
|
||||||
_downsampledBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold"));
|
_outputBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("BloomThreshold"));
|
||||||
_downsampledBuffer->setRenderBuffer(0, colorTexture);
|
_outputBuffer->setRenderBuffer(0, colorTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int COLOR_MAP_SLOT = 0;
|
static const int COLOR_MAP_SLOT = 0;
|
||||||
static const int THRESHOLD_SLOT = 1;
|
static const int THRESHOLD_SLOT = 1;
|
||||||
|
|
||||||
if (!_pipeline) {
|
if (!_pipeline) {
|
||||||
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
|
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
|
||||||
auto ps = gpu::Shader::createPixel(std::string(BloomThreshold_frag));
|
auto ps = gpu::Shader::createPixel(std::string(BloomThreshold_frag));
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
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) {
|
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
|
||||||
batch.enableStereo(false);
|
batch.enableStereo(false);
|
||||||
|
|
||||||
batch.setViewportTransform(halfViewport);
|
batch.setViewportTransform(args->_viewport);
|
||||||
batch.setProjectionTransform(glm::mat4());
|
batch.setProjectionTransform(glm::mat4());
|
||||||
batch.resetViewTransform();
|
batch.resetViewTransform();
|
||||||
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(inputFrameBuffer->getSize(), args->_viewport));
|
batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, args->_viewport));
|
||||||
batch.setPipeline(_pipeline);
|
batch.setPipeline(_pipeline);
|
||||||
|
|
||||||
batch.setFramebuffer(_downsampledBuffer);
|
batch.setFramebuffer(_outputBuffer);
|
||||||
batch.setResourceTexture(COLOR_MAP_SLOT, inputColor);
|
batch.setResourceTexture(COLOR_MAP_SLOT, inputBuffer);
|
||||||
batch._glUniform1f(THRESHOLD_SLOT, _threshold);
|
batch._glUniform1f(THRESHOLD_SLOT, _threshold);
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
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() {
|
BloomApply::BloomApply() {
|
||||||
|
@ -287,14 +281,27 @@ void Bloom::configure(const Config& config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
void Bloom::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) {
|
||||||
const auto bloomInputBuffer = task.addJob<ThresholdAndDownsampleJob>("BloomThreshold", inputs);
|
const auto bloomInputBuffer = task.addJob<BloomThreshold>("BloomThreshold", inputs);
|
||||||
|
const auto bloomHalfInputBuffer = task.addJob<render::HalfDownsample>("BloomHalf", bloomInputBuffer);
|
||||||
|
const auto bloomQuarterInputBuffer = task.addJob<render::HalfDownsample>("BloomQuarter", bloomHalfInputBuffer);
|
||||||
|
|
||||||
|
#if 1
|
||||||
// Multi-scale blur
|
// Multi-scale blur
|
||||||
const auto blurFB0 = task.addJob<render::BlurGaussian>("BloomBlur0", bloomInputBuffer);
|
const auto blurFB0 = task.addJob<render::BlurGaussian>("BloomBlur0", bloomQuarterInputBuffer);
|
||||||
const auto halfBlurFB0 = task.addJob<render::HalfDownsample>("BloomHalfBlur0", blurFB0);
|
const auto halfBlurFB0 = task.addJob<render::HalfDownsample>("BloomHalfBlur0", blurFB0);
|
||||||
const auto blurFB1 = task.addJob<render::BlurGaussian>("BloomBlur1", halfBlurFB0, true);
|
const auto blurFB1 = task.addJob<render::BlurGaussian>("BloomBlur1", halfBlurFB0, true);
|
||||||
const auto halfBlurFB1 = task.addJob<render::HalfDownsample>("BloomHalfBlur1", blurFB1);
|
const auto halfBlurFB1 = task.addJob<render::HalfDownsample>("BloomHalfBlur1", blurFB1);
|
||||||
const auto blurFB2 = task.addJob<render::BlurGaussian>("BloomBlur2", halfBlurFB1, true);
|
const auto blurFB2 = task.addJob<render::BlurGaussian>("BloomBlur2", halfBlurFB1, true);
|
||||||
|
#else
|
||||||
|
// Multi-scale downsampling debug
|
||||||
|
const auto blurFB0 = bloomQuarterInputBuffer;
|
||||||
|
const auto blurFB1 = task.addJob<render::HalfDownsample>("BloomHalfBlur1", blurFB0);
|
||||||
|
const auto blurFB2 = task.addJob<render::HalfDownsample>("BloomHalfBlur2", blurFB1);
|
||||||
|
// This is only needed so as not to crash as we expect to have the three blur jobs
|
||||||
|
task.addJob<render::BlurGaussian>("BloomBlur0", bloomHalfInputBuffer, true);
|
||||||
|
task.addJob<render::BlurGaussian>("BloomBlur1", blurFB1, true);
|
||||||
|
task.addJob<render::BlurGaussian>("BloomBlur2", blurFB2, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
const auto& input = inputs.get<Inputs>();
|
const auto& input = inputs.get<Inputs>();
|
||||||
const auto& frameBuffer = input[1];
|
const auto& frameBuffer = input[1];
|
||||||
|
|
|
@ -25,7 +25,7 @@ public:
|
||||||
|
|
||||||
BloomConfig() : render::Task::Config(true) {}
|
BloomConfig() : render::Task::Config(true) {}
|
||||||
|
|
||||||
float size{ 0.45f };
|
float size{ 0.8f };
|
||||||
|
|
||||||
void setIntensity(float value);
|
void setIntensity(float value);
|
||||||
float getIntensity() const;
|
float getIntensity() const;
|
||||||
|
@ -35,7 +35,7 @@ signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThresholdConfig : public render::Job::Config {
|
class BloomThresholdConfig : public render::Job::Config {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty)
|
Q_PROPERTY(float threshold MEMBER threshold NOTIFY dirty)
|
||||||
|
|
||||||
|
@ -47,21 +47,21 @@ signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThresholdAndDownsampleJob {
|
class BloomThreshold {
|
||||||
public:
|
public:
|
||||||
using Inputs = render::VaryingSet2<DeferredFrameTransformPointer, gpu::FramebufferPointer>;
|
using Inputs = render::VaryingSet2<DeferredFrameTransformPointer, gpu::FramebufferPointer>;
|
||||||
using Outputs = gpu::FramebufferPointer;
|
using Outputs = gpu::FramebufferPointer;
|
||||||
using Config = ThresholdConfig;
|
using Config = BloomThresholdConfig;
|
||||||
using JobModel = render::Job::ModelIO<ThresholdAndDownsampleJob, Inputs, Outputs, Config>;
|
using JobModel = render::Job::ModelIO<BloomThreshold, Inputs, Outputs, Config>;
|
||||||
|
|
||||||
ThresholdAndDownsampleJob();
|
BloomThreshold();
|
||||||
|
|
||||||
void configure(const Config& config);
|
void configure(const Config& config);
|
||||||
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
|
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
gpu::FramebufferPointer _downsampledBuffer;
|
gpu::FramebufferPointer _outputBuffer;
|
||||||
gpu::PipelinePointer _pipeline;
|
gpu::PipelinePointer _pipeline;
|
||||||
float _threshold;
|
float _threshold;
|
||||||
};
|
};
|
||||||
|
@ -73,7 +73,7 @@ class BloomApplyConfig : public render::Job::Config {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
float intensity{ 0.5f };
|
float intensity{ 0.8f };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void dirty();
|
void dirty();
|
||||||
|
|
|
@ -17,29 +17,11 @@ in vec2 varTexCoord0;
|
||||||
out vec4 outFragColor;
|
out vec4 outFragColor;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
// Gather 2 by 2 quads from texture, threshold and downsample
|
vec4 color = texture(colorMap, varTexCoord0);
|
||||||
vec4 reds = textureGather(colorMap, varTexCoord0, 0);
|
float luminance = (color.r+color.g+color.b) / 3.0;
|
||||||
vec4 greens = textureGather(colorMap, varTexCoord0, 1);
|
float mask = clamp((luminance-threshold)*0.25, 0, 1);
|
||||||
vec4 blues = textureGather(colorMap, varTexCoord0, 2);
|
|
||||||
|
|
||||||
vec3 texel0 = vec3(reds.x, greens.x, blues.x);
|
color *= mask;
|
||||||
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);
|
|
||||||
|
|
||||||
vec4 luminances;
|
outFragColor = vec4(color.rgb, 1.0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,15 +48,12 @@ void HalfDownsample::run(const RenderContextPointer& renderContext, const gpu::F
|
||||||
|
|
||||||
resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer);
|
resampledFrameBuffer = getResampledFrameBuffer(sourceFramebuffer);
|
||||||
|
|
||||||
static auto TEXCOORD_RECT_SLOT = 1;
|
|
||||||
|
|
||||||
if (!_pipeline) {
|
if (!_pipeline) {
|
||||||
auto vs = gpu::StandardShaderLib::getDrawTexcoordRectTransformUnitQuadVS();
|
auto vs = gpu::StandardShaderLib::getDrawTransformUnitQuadVS();
|
||||||
auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS();
|
auto ps = gpu::StandardShaderLib::getDrawTextureOpaquePS();
|
||||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
slotBindings.insert(gpu::Shader::Binding(std::string("texcoordRect"), TEXCOORD_RECT_SLOT));
|
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
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.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(bufferSize, viewport));
|
||||||
batch.setResourceTexture(0, sourceFramebuffer->getRenderBuffer(0));
|
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);
|
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue