Add Job::Config to AmbientOcclusion

This commit is contained in:
Zach Pomerantz 2016-01-22 17:04:55 -08:00
parent ba61c1f865
commit 772aedde91
5 changed files with 176 additions and 186 deletions

View file

@ -32,6 +32,44 @@
#include "ssao_makeHorizontalBlur_frag.h"
#include "ssao_makeVerticalBlur_frag.h"
void AmbientOcclusionEffectConfig::setRadius(float newRadius) {
radius = std::max(0.01f, radius);
}
void AmbientOcclusionEffectConfig::setObscuranceLevel(float level) {
level = std::max(0.01f, level);
}
void AmbientOcclusionEffectConfig::setFalloffBias(float bias) {
bias = std::max(0.0f, std::min(bias, 0.2f));
}
void AmbientOcclusionEffectConfig::setEdgeSharpness(float sharpness) {
sharpness = std::max(0.0f, (float)sharpness);
}
void AmbientOcclusionEffectConfig::setBlurDeviation(float deviation) {
deviation = std::max(0.0f, deviation);
}
void AmbientOcclusionEffectConfig::setNumSpiralTurns(float numTurns) {
numTurns = std::max(0.0f, (float)numTurns);
}
void AmbientOcclusionEffectConfig::setNumSamples(int numSamples) {
numSamples = std::max(1.0f, (float) numSamples);
}
void AmbientOcclusionEffectConfig::setResolutionLevel(int level) {
const int MAX_RESOLUTION_LEVEL = 4;
level = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL));
}
void AmbientOcclusionEffectConfig::setBlurRadius(int radius) {
const int MAX_BLUR_RADIUS = 6;
radius = std::max(0, std::min(MAX_BLUR_RADIUS, radius));
}
class GaussianDistribution {
public:
@ -100,6 +138,80 @@ AmbientOcclusionEffect::AmbientOcclusionEffect() {
_parametersBuffer = gpu::BufferView(std::make_shared<gpu::Buffer>(sizeof(Parameters), (const gpu::Byte*) &parameters));
}
void AmbientOcclusionEffect::configure(const Config& configuration) {
bool shouldUpdateGaussion = false;
const double RADIUS_POWER = 6.0;
const auto& radius = configuration.radius;
if (radius != getRadius()) {
auto& current = _parametersBuffer.edit<Parameters>().radiusInfo;
current.x = radius;
current.y = radius * radius;
current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER));
}
if (configuration.obscuranceLevel != getObscuranceLevel()) {
auto& current = _parametersBuffer.edit<Parameters>().radiusInfo;
current.w = configuration.obscuranceLevel;
}
if (configuration.falloffBias != getFalloffBias()) {
auto& current = _parametersBuffer.edit<Parameters>().ditheringInfo;
current.z = configuration.falloffBias;
}
if (configuration.edgeSharpness != getEdgeSharpness()) {
auto& current = _parametersBuffer.edit<Parameters>().blurInfo;
current.x = configuration.edgeSharpness;
}
if (configuration.blurDeviation != getBlurDeviation()) {
auto& current = _parametersBuffer.edit<Parameters>().blurInfo;
current.z = configuration.blurDeviation;
shouldUpdateGaussion = true;
}
if (configuration.numSpiralTurns != getNumSpiralTurns()) {
auto& current = _parametersBuffer.edit<Parameters>().sampleInfo;
current.z = configuration.numSpiralTurns;
}
if (configuration.numSamples != getNumSamples()) {
auto& current = _parametersBuffer.edit<Parameters>().sampleInfo;
current.x = configuration.numSamples;
current.y = 1.0f / configuration.numSamples;
}
const auto& resolutionLevel = configuration.resolutionLevel;
if (resolutionLevel != getResolutionLevel()) {
auto& current = _parametersBuffer.edit<Parameters>().resolutionInfo;
current.x = (float)resolutionLevel;
// Communicate the change to the Framebuffer cache
DependencyManager::get<FramebufferCache>()->setAmbientOcclusionResolutionLevel(resolutionLevel);
}
if (configuration.blurRadius != getBlurRadius()) {
auto& current = _parametersBuffer.edit<Parameters>().blurInfo;
current.y = (float)configuration.blurRadius;
shouldUpdateGaussion = true;
}
if (configuration.ditheringEnabled != isDitheringEnabled()) {
auto& current = _parametersBuffer.edit<Parameters>().ditheringInfo;
current.x = (float)configuration.ditheringEnabled;
}
if (configuration.borderingEnabled != isBorderingEnabled()) {
auto& current = _parametersBuffer.edit<Parameters>().ditheringInfo;
current.w = (float)configuration.borderingEnabled;
}
if (shouldUpdateGaussion) {
updateGaussianDistribution();
}
}
const gpu::PipelinePointer& AmbientOcclusionEffect::getPyramidPipeline() {
if (!_pyramidPipeline) {
auto vs = gpu::StandardShaderLib::getDrawViewportQuadTransformTexcoordVS();
@ -200,103 +312,6 @@ void AmbientOcclusionEffect::setDepthInfo(float nearZ, float farZ) {
_frameTransformBuffer.edit<FrameTransform>().depthInfo = glm::vec4(nearZ*farZ, farZ -nearZ, -farZ, 0.0f);
}
void AmbientOcclusionEffect::setResolutionLevel(int level) {
const int MAX_RESOLUTION_LEVEL = 4;
level = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL));
if (level != getResolutionLevel()) {
auto& current = _parametersBuffer.edit<Parameters>().resolutionInfo;
current.x = (float)level;
// Communicate the change to the Framebuffer cache
DependencyManager::get<FramebufferCache>()->setAmbientOcclusionResolutionLevel(level);
}
}
void AmbientOcclusionEffect::setRadius(float radius) {
const double RADIUS_POWER = 6.0;
radius = std::max(0.01f, radius);
if (radius != getRadius()) {
auto& current = _parametersBuffer.edit<Parameters>().radiusInfo;
current.x = radius;
current.y = radius * radius;
current.z = (float)(1.0 / pow((double)radius, RADIUS_POWER));
}
}
void AmbientOcclusionEffect::setLevel(float level) {
level = std::max(0.01f, level);
if (level != getLevel()) {
auto& current = _parametersBuffer.edit<Parameters>().radiusInfo;
current.w = level;
}
}
void AmbientOcclusionEffect::setDithering(bool enabled) {
if (enabled != isDitheringEnabled()) {
auto& current = _parametersBuffer.edit<Parameters>().ditheringInfo;
current.x = (float)enabled;
}
}
void AmbientOcclusionEffect::setBordering(bool enabled) {
if (enabled != isBorderingEnabled()) {
auto& current = _parametersBuffer.edit<Parameters>().ditheringInfo;
current.w = (float)enabled;
}
}
void AmbientOcclusionEffect::setFalloffBias(float bias) {
bias = std::max(0.0f, std::min(bias, 0.2f));
if (bias != getFalloffBias()) {
auto& current = _parametersBuffer.edit<Parameters>().ditheringInfo;
current.z = (float)bias;
}
}
void AmbientOcclusionEffect::setNumSamples(int numSamples) {
numSamples = std::max(1.0f, (float) numSamples);
if (numSamples != getNumSamples()) {
auto& current = _parametersBuffer.edit<Parameters>().sampleInfo;
current.x = numSamples;
current.y = 1.0f / numSamples;
}
}
void AmbientOcclusionEffect::setNumSpiralTurns(float numTurns) {
numTurns = std::max(0.0f, (float)numTurns);
if (numTurns != getNumSpiralTurns()) {
auto& current = _parametersBuffer.edit<Parameters>().sampleInfo;
current.z = numTurns;
}
}
void AmbientOcclusionEffect::setEdgeSharpness(float sharpness) {
sharpness = std::max(0.0f, (float)sharpness);
if (sharpness != getEdgeSharpness()) {
auto& current = _parametersBuffer.edit<Parameters>().blurInfo;
current.x = sharpness;
}
}
void AmbientOcclusionEffect::setBlurRadius(int radius) {
const int MAX_BLUR_RADIUS = 6;
radius = std::max(0, std::min(MAX_BLUR_RADIUS, radius));
if (radius != getBlurRadius()) {
auto& current = _parametersBuffer.edit<Parameters>().blurInfo;
current.y = (float)radius;
updateGaussianDistribution();
}
}
void AmbientOcclusionEffect::setBlurDeviation(float deviation) {
deviation = std::max(0.0f, deviation);
if (deviation != getBlurDeviation()) {
auto& current = _parametersBuffer.edit<Parameters>().blurInfo;
current.z = deviation;
updateGaussianDistribution();
}
}
void AmbientOcclusionEffect::updateGaussianDistribution() {
auto coefs = _parametersBuffer.edit<Parameters>()._gaussianCoefs;
GaussianDistribution::evalSampling(coefs, Parameters::GAUSSIAN_COEFS_LENGTH, getBlurRadius(), getBlurDeviation());
@ -417,6 +432,8 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
}
_gpuTimer.end(batch);
});
// Update the timer
std::static_pointer_cast<Config>(renderContext->jobConfig)->gpuTime = _gpuTimer.getAverage();
}

View file

@ -16,63 +16,75 @@
#include "render/DrawTask.h"
class AmbientOcclusionEffectConfig : public render::Job::Config {
Q_OBJECT
public:
AmbientOcclusionEffectConfig() : render::Job::Config(false) {}
Q_PROPERTY(float radius MEMBER radius WRITE setRadius NOTIFY dirty)
Q_PROPERTY(float obscuranceLevel MEMBER obscuranceLevel WRITE setObscuranceLevel NOTIFY dirty)
Q_PROPERTY(float falloffBias MEMBER falloffBias WRITE setFalloffBias NOTIFY dirty)
Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness NOTIFY dirty)
Q_PROPERTY(float blurDeviation MEMBER blurDeviation WRITE setBlurDeviation NOTIFY dirty)
Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns WRITE setNumSpiralTurns NOTIFY dirty)
Q_PROPERTY(int numSamples MEMBER numSamples WRITE setNumSamples NOTIFY dirty)
Q_PROPERTY(int resolutionLevel MEMBER resolutionLevel WRITE setResolutionLevel NOTIFY dirty)
Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius NOTIFY dirty)
Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty)
Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
Q_PROPERTY(double gpuTime READ getGpuTime)
void setRadius(float radius);
void setObscuranceLevel(float obscuranceLevel);
void setFalloffBias(float falloffBias);
void setEdgeSharpness(float edgeSharpness);
void setBlurDeviation(float blurDeviation);
void setNumSpiralTurns(float numSpiralTurns);
void setNumSamples(int numSamples);
void setResolutionLevel(int resolutionLevel);
void setBlurRadius(int blurRadius);
double getGpuTime() { return gpuTime; }
float radius{ 0.5f };
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{ 11 };
int resolutionLevel{ 1 };
int blurRadius{ 4 }; // 0 means no blurring
bool ditheringEnabled{ true }; // randomize the distribution of rays per pixel, should always be true
bool borderingEnabled{ true }; // avoid evaluating information from non existing pixels out of the frame, should always be true
double gpuTime{ 0.0 };
signals:
void dirty();
};
class AmbientOcclusionEffect {
public:
using Config = AmbientOcclusionEffectConfig;
using JobModel = render::Job::Model<AmbientOcclusionEffect, Config>;
AmbientOcclusionEffect();
void configure(const Config& configuration);
void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext);
void setResolutionLevel(int level);
int getResolutionLevel() const { return _parametersBuffer.get<Parameters>().resolutionInfo.x; }
void setRadius(float radius);
float getRadius() const { return _parametersBuffer.get<Parameters>().radiusInfo.x; }
// Obscurance level which intensify or dim down the obscurance effect
void setLevel(float level);
float getLevel() const { return _parametersBuffer.get<Parameters>().radiusInfo.w; }
// On to randomize the distribution of rays per pixel, should always be true
void setDithering(bool enabled);
bool isDitheringEnabled() const { return _parametersBuffer.get<Parameters>().ditheringInfo.x; }
// On to avoid evaluating information from non existing pixels Out of the frame, should always be true
void setBordering(bool enabled);
bool isBorderingEnabled() const { return _parametersBuffer.get<Parameters>().ditheringInfo.w; }
// Faloff Bias
void setFalloffBias(float bias);
int getFalloffBias() const { return (int)_parametersBuffer.get<Parameters>().ditheringInfo.z; }
// Number of samples per pixel to evaluate the Obscurance
void setNumSamples(int numSamples);
int getNumSamples() const { return (int)_parametersBuffer.get<Parameters>().sampleInfo.x; }
// Number of spiral turns defining an angle span to distribute the samples ray directions
void setNumSpiralTurns(float numTurns);
float getNumSpiralTurns() const { return _parametersBuffer.get<Parameters>().sampleInfo.z; }
// Edge blurring setting
void setEdgeSharpness(float sharpness);
int getEdgeSharpness() const { return (int)_parametersBuffer.get<Parameters>().blurInfo.x; }
// Blurring Radius
// 0 means no blurring
const int MAX_BLUR_RADIUS = 6;
void setBlurRadius(int radius);
int getBlurRadius() const { return (int)_parametersBuffer.get<Parameters>().blurInfo.y; }
void setBlurDeviation(float deviation);
float getObscuranceLevel() const { return _parametersBuffer.get<Parameters>().radiusInfo.w; }
float getFalloffBias() const { return (float)_parametersBuffer.get<Parameters>().ditheringInfo.z; }
float getEdgeSharpness() const { return (float)_parametersBuffer.get<Parameters>().blurInfo.x; }
float getBlurDeviation() const { return _parametersBuffer.get<Parameters>().blurInfo.z; }
double getGPUTime() const { return _gpuTimer.getAverage(); }
float getNumSpiralTurns() const { return _parametersBuffer.get<Parameters>().sampleInfo.z; }
int getNumSamples() const { return (int)_parametersBuffer.get<Parameters>().sampleInfo.x; }
int getResolutionLevel() const { return _parametersBuffer.get<Parameters>().resolutionInfo.x; }
int getBlurRadius() const { return (int)_parametersBuffer.get<Parameters>().blurInfo.y; }
bool isDitheringEnabled() const { return _parametersBuffer.get<Parameters>().ditheringInfo.x; }
bool isBorderingEnabled() const { return _parametersBuffer.get<Parameters>().ditheringInfo.w; }
using JobModel = render::Job::Model<AmbientOcclusionEffect>;
private:
void updateGaussianDistribution();
void setDepthInfo(float nearZ, float farZ);

View file

@ -173,21 +173,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
setDrawHitEffect(renderContext->getDrawHitEffect());
// TODO: turn on/off AO through menu item
setOcclusionStatus(renderContext->getOcclusionStatus());
if (_occlusionJobIndex >= 0) {
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setResolutionLevel(renderContext->getAmbientOcclusion().resolutionLevel);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setRadius(renderContext->getAmbientOcclusion().radius);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setLevel(renderContext->getAmbientOcclusion().level);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setNumSamples(renderContext->getAmbientOcclusion().numSamples);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setNumSpiralTurns(renderContext->getAmbientOcclusion().numSpiralTurns);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setDithering(renderContext->getAmbientOcclusion().ditheringEnabled);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setFalloffBias(renderContext->getAmbientOcclusion().falloffBias);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setEdgeSharpness(renderContext->getAmbientOcclusion().edgeSharpness);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setBlurRadius(renderContext->getAmbientOcclusion().blurRadius);
_jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().setBlurDeviation(renderContext->getAmbientOcclusion().blurDeviation);
}
setAntialiasingStatus(renderContext->getFxaaStatus());
// TODO: Allow runtime manipulation of culling ShouldRenderFunctor
@ -199,12 +185,6 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
for (auto job : _jobs) {
job.run(sceneContext, renderContext);
}
if (_occlusionJobIndex >= 0 && renderContext->getOcclusionStatus()) {
renderContext->getAmbientOcclusion().gpuTime = _jobs[_occlusionJobIndex].edit<AmbientOcclusionEffect>().getGPUTime();
} else {
renderContext->getAmbientOcclusion().gpuTime = 0.0;
}
};
void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {

View file

@ -13,10 +13,10 @@
using namespace render;
RenderContext::RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect)
RenderContext::RenderContext(int drawStatus, bool drawHitEffect)
: _args{ nullptr },
_drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect },
_ambientOcclusion{ ao } {}
_drawStatus{ drawStatus }, _drawHitEffect{ drawHitEffect } {
}
void RenderContext::setOptions(bool occlusion, bool fxaa, bool showOwned, bool shadowMap) {
_occlusionStatus = occlusion;

View file

@ -32,28 +32,11 @@ class JobConfig;
class RenderContext {
public:
class AmbientOcclusion {
public:
int resolutionLevel { 1 };
float radius { 0.5f }; // radius in meters of the AO effect
float level { 0.5f }; // Level of the obscrance value
int numSamples { 11 }; // Num Samples per pixel
float numSpiralTurns { 7.0f };
bool ditheringEnabled { true };
float falloffBias { 0.01f };
float edgeSharpness { 1.0f };
int blurRadius { 4 };
float blurDeviation { 2.5f};
double gpuTime { 0.0 };
};
RenderContext(AmbientOcclusion ao, int drawStatus, bool drawHitEffect);
RenderContext(int drawStatus, bool drawHitEffect);
RenderContext() {};
void setArgs(RenderArgs* args) { _args = args; }
RenderArgs* getArgs() { return _args; }
AmbientOcclusion& getAmbientOcclusion() { return _ambientOcclusion; }
int getDrawStatus() { return _drawStatus; }
bool getDrawHitEffect() { return _drawHitEffect; }
bool getOcclusionStatus() { return _occlusionStatus; }
@ -71,8 +54,6 @@ protected:
bool _occlusionStatus { false };
bool _fxaaStatus { false };
bool _shadowMapStatus { false };
AmbientOcclusion _ambientOcclusion;
};
typedef std::shared_ptr<RenderContext> RenderContextPointer;