overte-HifiExperiments/libraries/render-utils/src/AmbientOcclusionEffect.h
2018-09-19 17:24:31 +02:00

242 lines
9.2 KiB
C++

//
// AmbientOcclusionEffect.h
// libraries/render-utils/src/
//
// Created by Niraj Venkat on 7/15/15.
// Copyright 2015 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_AmbientOcclusionEffect_h
#define hifi_AmbientOcclusionEffect_h
#include <string>
#include <DependencyManager.h>
#include "render/DrawTask.h"
#include "DeferredFrameTransform.h"
#include "DeferredFramebuffer.h"
#include "SurfaceGeometryPass.h"
class AmbientOcclusionFramebuffer {
public:
AmbientOcclusionFramebuffer();
gpu::FramebufferPointer getOcclusionFramebuffer();
gpu::TexturePointer getOcclusionTexture();
gpu::FramebufferPointer getOcclusionBlurredFramebuffer();
gpu::TexturePointer getOcclusionBlurredTexture();
gpu::FramebufferPointer getNormalFramebuffer();
gpu::TexturePointer getNormalTexture();
// Update the source framebuffer size which will drive the allocation of all the other resources.
bool updateLinearDepth(const gpu::TexturePointer& linearDepthBuffer);
gpu::TexturePointer getLinearDepthTexture();
const glm::ivec2& getSourceFrameSize() const { return _frameSize; }
protected:
void clear();
void allocate();
gpu::TexturePointer _linearDepthTexture;
gpu::FramebufferPointer _occlusionFramebuffer;
gpu::TexturePointer _occlusionTexture;
gpu::FramebufferPointer _occlusionBlurredFramebuffer;
gpu::TexturePointer _occlusionBlurredTexture;
gpu::FramebufferPointer _normalFramebuffer;
gpu::TexturePointer _normalTexture;
glm::ivec2 _frameSize;
};
using AmbientOcclusionFramebufferPointer = std::shared_ptr<AmbientOcclusionFramebuffer>;
class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
Q_OBJECT
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty)
Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty)
Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
Q_PROPERTY(bool fetchMipsEnabled MEMBER fetchMipsEnabled NOTIFY dirty)
Q_PROPERTY(float radius MEMBER radius WRITE setRadius)
Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel)
Q_PROPERTY(float falloffAngle MEMBER falloffAngle WRITE setFalloffAngle)
Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness)
Q_PROPERTY(float blurDeviation MEMBER blurDeviation WRITE setBlurDeviation)
Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns WRITE setNumSpiralTurns)
Q_PROPERTY(int numSamples MEMBER numSamples WRITE setNumSamples)
Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel)
Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius)
public:
AmbientOcclusionEffectConfig();
const int MAX_RESOLUTION_LEVEL = 4;
const int MAX_BLUR_RADIUS = 15;
void setRadius(float newRadius) { radius = std::max(0.01f, newRadius); emit dirty(); }
void setObscuranceLevel(float level) { obscuranceLevel = std::max(0.01f, level); emit dirty(); }
void setFalloffAngle(float bias) { falloffAngle = std::max(0.0f, std::min(bias, 1.0f)); emit dirty(); }
void setEdgeSharpness(float sharpness) { edgeSharpness = std::max(0.0f, (float)sharpness); emit dirty(); }
void setBlurDeviation(float deviation) { blurDeviation = std::max(0.0f, deviation); emit dirty(); }
void setNumSpiralTurns(float turns) { numSpiralTurns = std::max(0.0f, (float)turns); emit dirty(); }
void setNumSamples(int samples) { numSamples = std::max(1.0f, (float)samples); emit dirty(); }
void setResolutionLevel(int level) { resolutionLevel = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL)); emit dirty(); }
void setBlurRadius(int radius) { blurRadius = std::max(0, std::min(MAX_BLUR_RADIUS, radius)); emit dirty(); }
float radius;
float perspectiveScale;
float obscuranceLevel; // intensify or dim down the obscurance effect
float falloffAngle;
float edgeSharpness;
float blurDeviation;
float numSpiralTurns; // defining an angle span to distribute the samples ray directions
int numSamples;
int resolutionLevel;
int blurRadius; // 0 means no blurring
bool ditheringEnabled; // randomize the distribution of taps per pixel, should always be true
bool borderingEnabled; // avoid evaluating information from non existing pixels out of the frame, should always be true
bool fetchMipsEnabled; // fetch taps in sub mips to otpimize cache, should always be true
signals:
void dirty();
};
class AmbientOcclusionEffect {
public:
using Inputs = render::VaryingSet3<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer>;
using Outputs = render::VaryingSet2<AmbientOcclusionFramebufferPointer, gpu::BufferView>;
using Config = AmbientOcclusionEffectConfig;
using JobModel = render::Job::ModelIO<AmbientOcclusionEffect, Inputs, Outputs, Config>;
AmbientOcclusionEffect();
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs, Outputs& outputs);
#include "ssao_shared.h"
// Class describing the uniform buffer with all the parameters common to the AO shaders
class AOParameters : public AmbientOcclusionParams {
public:
AOParameters();
int getResolutionLevel() const { return _resolutionInfo.x; }
float getRadius() const { return _radiusInfo.x; }
float getPerspectiveScale() const { return _resolutionInfo.z; }
float getObscuranceLevel() const { return _radiusInfo.w; }
float getFalloffAngle() const { return (float)_ditheringInfo.z; }
float getEdgeSharpness() const { return (float)_blurInfo.x; }
float getBlurDeviation() const { return _blurInfo.z; }
float getNumSpiralTurns() const { return _sampleInfo.z; }
int getNumSamples() const { return (int)_sampleInfo.x; }
bool isFetchMipsEnabled() const { return _sampleInfo.w; }
int getBlurRadius() const { return (int)_blurInfo.y; }
bool isDitheringEnabled() const { return _ditheringInfo.x; }
bool isBorderingEnabled() const { return _ditheringInfo.w; }
};
using AOParametersBuffer = gpu::StructBuffer<AOParameters>;
private:
// Class describing the uniform buffer with all the parameters common to the bilateral blur shaders
class BlurParameters {
public:
glm::vec4 scaleHeight{ 0.0f };
BlurParameters() {}
};
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
using FrameParametersBuffer = gpu::StructBuffer< AmbientOcclusionFrameParams>;
void updateGaussianDistribution();
void updateBlurParameters();
AOParametersBuffer _aoParametersBuffer;
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT];
BlurParametersBuffer _vblurParametersBuffer;
BlurParametersBuffer _hblurParametersBuffer;
static const gpu::PipelinePointer& getOcclusionPipeline();
static const gpu::PipelinePointer& getHBlurPipeline(); // first
static const gpu::PipelinePointer& getVBlurPipeline(); // second
static const gpu::PipelinePointer& getMipCreationPipeline();
static const gpu::PipelinePointer& getGatherPipeline();
static const gpu::PipelinePointer& getBuildNormalsPipeline();
static gpu::PipelinePointer _occlusionPipeline;
static gpu::PipelinePointer _hBlurPipeline;
static gpu::PipelinePointer _vBlurPipeline;
static gpu::PipelinePointer _mipCreationPipeline;
static gpu::PipelinePointer _gatherPipeline;
static gpu::PipelinePointer _buildNormalsPipeline;
AmbientOcclusionFramebufferPointer _framebuffer;
std::array<float, 16 * SSAO_SPLIT_COUNT> _randomSamples;
int _frameId{ 0 };
gpu::RangeTimerPointer _gpuTimer;
friend class DebugAmbientOcclusion;
};
class DebugAmbientOcclusionConfig : public render::Job::Config {
Q_OBJECT
Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty)
Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty)
public:
DebugAmbientOcclusionConfig() : render::Job::Config(false) {}
bool showCursorPixel{ false };
glm::vec2 debugCursorTexcoord{ 0.5f, 0.5f };
signals:
void dirty();
};
class DebugAmbientOcclusion {
public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::AOParametersBuffer>;
using Config = DebugAmbientOcclusionConfig;
using JobModel = render::Job::ModelI<DebugAmbientOcclusion, Inputs, Config>;
DebugAmbientOcclusion();
void configure(const Config& config);
void run(const render::RenderContextPointer& renderContext, const Inputs& inputs);
private:
// Class describing the uniform buffer with all the parameters common to the debug AO shaders
class Parameters {
public:
// Pixel info
glm::vec4 pixelInfo { 0.0f, 0.0f, 0.0f, 0.0f };
Parameters() {}
};
gpu::StructBuffer<Parameters> _parametersBuffer;
const gpu::PipelinePointer& getDebugPipeline();
gpu::PipelinePointer _debugPipeline;
bool _showCursorPixel{ false };
};
#endif // hifi_AmbientOcclusionEffect_h