overte-HifiExperiments/libraries/render-utils/src/AmbientOcclusionEffect.h

224 lines
8.8 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();
// Update the source framebuffer size which will drive the allocation of all the other resources.
void 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;
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 falloffBias MEMBER falloffBias WRITE setFalloffBias)
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() : render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false) {}
const int MAX_RESOLUTION_LEVEL = 4;
const int MAX_BLUR_RADIUS = 6;
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 setFalloffBias(float bias) { falloffBias = std::max(0.0f, std::min(bias, 0.2f)); 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{ 0.5f };
float perspectiveScale{ 1.0f };
float obscuranceLevel{ 0.5f }; // intensify or dim down the obscurance effect
float falloffBias{ 0.01f };
float edgeSharpness{ 1.0f };
float blurDeviation{ 2.5f };
float numSpiralTurns{ 7.0f }; // defining an angle span to distribute the samples ray directions
int numSamples{ 16 };
int resolutionLevel{ 1 };
int blurRadius{ 4 }; // 0 means no blurring
bool ditheringEnabled{ true }; // randomize the distribution of taps per pixel, should always be true
bool borderingEnabled{ true }; // avoid evaluating information from non existing pixels out of the frame, should always be true
bool fetchMipsEnabled{ true }; // 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);
// Class describing the uniform buffer with all the parameters common to the AO shaders
class Parameters {
public:
// Resolution info
glm::vec4 resolutionInfo { -1.0f, 0.0f, 1.0f, 0.0f };
// radius info is { R, R^2, 1 / R^6, ObscuranceScale}
glm::vec4 radiusInfo{ 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f };
// Dithering info
glm::vec4 ditheringInfo { 0.0f, 0.0f, 0.01f, 1.0f };
// Sampling info
glm::vec4 sampleInfo { 11.0f, 1.0f/11.0f, 7.0f, 1.0f };
// Blurring info
glm::vec4 blurInfo { 1.0f, 3.0f, 2.0f, 0.0f };
// gaussian distribution coefficients first is the sampling radius (max is 6)
const static int GAUSSIAN_COEFS_LENGTH = 8;
float _gaussianCoefs[GAUSSIAN_COEFS_LENGTH];
Parameters() {}
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 getFalloffBias() 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 ParametersBuffer = gpu::StructBuffer<Parameters>;
private:
void updateGaussianDistribution();
ParametersBuffer _parametersBuffer;
const gpu::PipelinePointer& getOcclusionPipeline();
const gpu::PipelinePointer& getHBlurPipeline(); // first
const gpu::PipelinePointer& getVBlurPipeline(); // second
gpu::PipelinePointer _occlusionPipeline;
gpu::PipelinePointer _hBlurPipeline;
gpu::PipelinePointer _vBlurPipeline;
AmbientOcclusionFramebufferPointer _framebuffer;
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(true) {}
bool showCursorPixel{ false };
glm::vec2 debugCursorTexcoord{ 0.5f, 0.5f };
signals:
void dirty();
};
class DebugAmbientOcclusion {
public:
using Inputs = render::VaryingSet4<DeferredFrameTransformPointer, DeferredFramebufferPointer, LinearDepthFramebufferPointer, AmbientOcclusionEffect::ParametersBuffer>;
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