Added config parameter to switch between HBAO / SSAO

This commit is contained in:
Olivier Prat 2018-09-27 16:39:42 +02:00
parent 94a162893a
commit 349a8b39ad
6 changed files with 51 additions and 53 deletions

View file

@ -202,36 +202,24 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() : AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false), render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false),
#if SSAO_USE_HORIZON_BASED
radius{ 0.3f }, radius{ 0.3f },
#else
radius{ 0.5f },
#endif
perspectiveScale{ 1.0f }, perspectiveScale{ 1.0f },
obscuranceLevel{ 0.5f }, obscuranceLevel{ 0.5f },
#if SSAO_USE_HORIZON_BASED
falloffAngle{ 0.3f }, falloffAngle{ 0.3f },
#else
falloffAngle{ 0.01f },
#endif
edgeSharpness{ 1.0f }, edgeSharpness{ 1.0f },
blurDeviation{ 2.5f }, blurDeviation{ 2.5f },
numSpiralTurns{ 7.0f }, numSpiralTurns{ 7.0f },
#if SSAO_USE_HORIZON_BASED
numSamples{ 1 }, numSamples{ 1 },
#else
numSamples{ 16 },
#endif
resolutionLevel{ 2 }, resolutionLevel{ 2 },
blurRadius{ 4 }, blurRadius{ 4 },
ditheringEnabled{ true }, ditheringEnabled{ true },
borderingEnabled{ true }, borderingEnabled{ true },
fetchMipsEnabled{ true } { fetchMipsEnabled{ true },
horizonBased{ true } {
} }
AmbientOcclusionEffect::AOParameters::AOParameters() { AmbientOcclusionEffect::AOParameters::AOParameters() {
_resolutionInfo = { -1.0f, 0.0f, 1.0f, 0.0f }; _resolutionInfo = { -1.0f, 1.0f, 1.0f, 0.0f };
_radiusInfo = { 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f }; _radiusInfo = { 0.5f, 0.5f * 0.5f, 1.0f / (0.25f * 0.25f * 0.25f), 1.0f };
_ditheringInfo = { 0.0f, 0.0f, 0.01f, 1.0f }; _ditheringInfo = { 0.0f, 0.0f, 0.01f, 1.0f };
_sampleInfo = { 11.0f, 1.0f / 11.0f, 7.0f, 1.0f }; _sampleInfo = { 11.0f, 1.0f / 11.0f, 7.0f, 1.0f };
@ -251,14 +239,19 @@ void AmbientOcclusionEffect::configure(const Config& config) {
const double RADIUS_POWER = 6.0; const double RADIUS_POWER = 6.0;
const auto& radius = config.radius; const auto& radius = config.radius;
if (radius != _aoParametersBuffer->getRadius()) { if (radius != _aoParametersBuffer->getRadius() || config.horizonBased != _aoParametersBuffer->isHorizonBased()) {
auto& current = _aoParametersBuffer.edit()._radiusInfo; auto& current = _aoParametersBuffer.edit()._radiusInfo;
current.x = radius; current.x = radius;
current.y = radius * radius; current.y = radius * radius;
current.z = 10.0f; current.z = 10.0f;
#if !SSAO_USE_HORIZON_BASED if (!config.horizonBased) {
current.z *= (float)(1.0 / pow((double)radius, RADIUS_POWER)); current.z *= (float)(1.0 / pow((double)radius, RADIUS_POWER));
#endif }
}
if (config.horizonBased != _aoParametersBuffer->isHorizonBased()) {
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
current.y = config.horizonBased & 1;
} }
if (config.obscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) { if (config.obscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
@ -501,6 +494,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
const auto depthResolutionLevel = getDepthResolutionLevel(); const auto depthResolutionLevel = getDepthResolutionLevel();
const auto depthResolutionScale = powf(0.5f, depthResolutionLevel); const auto depthResolutionScale = powf(0.5f, depthResolutionLevel);
const auto isHorizonBased = _aoParametersBuffer->isHorizonBased();
auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture(); auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
auto occlusionDepthTexture = linearDepthTexture; auto occlusionDepthTexture = linearDepthTexture;
@ -538,9 +532,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
auto occlusionPipeline = getOcclusionPipeline(); auto occlusionPipeline = getOcclusionPipeline();
auto firstHBlurPipeline = getHBlurPipeline(); auto firstHBlurPipeline = getHBlurPipeline();
auto lastVBlurPipeline = getVBlurPipeline(); auto lastVBlurPipeline = getVBlurPipeline();
#if SSAO_USE_HORIZON_BASED
auto mipCreationPipeline = getMipCreationPipeline(); auto mipCreationPipeline = getMipCreationPipeline();
#endif
#if SSAO_USE_QUAD_SPLIT #if SSAO_USE_QUAD_SPLIT
auto gatherPipeline = getGatherPipeline(); auto gatherPipeline = getGatherPipeline();
auto buildNormalsPipeline = getBuildNormalsPipeline(); auto buildNormalsPipeline = getBuildNormalsPipeline();
@ -571,14 +563,14 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
batch.setProjectionTransform(glm::mat4()); batch.setProjectionTransform(glm::mat4());
batch.setModelTransform(Transform()); batch.setModelTransform(Transform());
batch.pushProfileRange("Depth Mip Generation");
// We need this with the mips levels // We need this with the mips levels
#if SSAO_USE_HORIZON_BASED batch.pushProfileRange("Depth Mip Generation");
batch.setPipeline(mipCreationPipeline); if (isHorizonBased) {
batch.generateTextureMipsWithPipeline(occlusionDepthTexture); batch.setPipeline(mipCreationPipeline);
#else batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
batch.generateTextureMips(occlusionDepthTexture); } else {
#endif batch.generateTextureMips(occlusionDepthTexture);
}
batch.popProfileRange(); batch.popProfileRange();
#if SSAO_USE_QUAD_SPLIT #if SSAO_USE_QUAD_SPLIT
@ -731,8 +723,6 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage());
} }
DebugAmbientOcclusion::DebugAmbientOcclusion() { DebugAmbientOcclusion::DebugAmbientOcclusion() {
} }

View file

@ -79,6 +79,7 @@ using AmbientOcclusionFramebufferPointer = std::shared_ptr<AmbientOcclusionFrame
class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent { class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty) Q_PROPERTY(bool enabled MEMBER enabled NOTIFY dirty)
Q_PROPERTY(bool horizonBased MEMBER horizonBased NOTIFY dirty)
Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty) Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled NOTIFY dirty)
Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty) Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
Q_PROPERTY(bool fetchMipsEnabled MEMBER fetchMipsEnabled NOTIFY dirty) Q_PROPERTY(bool fetchMipsEnabled MEMBER fetchMipsEnabled NOTIFY dirty)
@ -118,6 +119,7 @@ public:
int numSamples; int numSamples;
int resolutionLevel; int resolutionLevel;
int blurRadius; // 0 means no blurring int blurRadius; // 0 means no blurring
bool horizonBased; // Use horizon based AO
bool ditheringEnabled; // randomize the distribution of taps per pixel, should always be true 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 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 bool fetchMipsEnabled; // fetch taps in sub mips to otpimize cache, should always be true
@ -154,8 +156,10 @@ public:
int getNumSamples() const { return (int)_sampleInfo.x; } int getNumSamples() const { return (int)_sampleInfo.x; }
bool isFetchMipsEnabled() const { return _sampleInfo.w; } bool isFetchMipsEnabled() const { return _sampleInfo.w; }
bool isDitheringEnabled() const { return _ditheringInfo.x; } bool isDitheringEnabled() const { return _ditheringInfo.x != 0.0f; }
bool isBorderingEnabled() const { return _ditheringInfo.w; } bool isBorderingEnabled() const { return _ditheringInfo.w != 0.0f; }
bool isHorizonBased() const { return _resolutionInfo.y != 0.0f; }
}; };
using AOParametersBuffer = gpu::StructBuffer<AOParameters>; using AOParametersBuffer = gpu::StructBuffer<AOParameters>;

View file

@ -51,6 +51,10 @@ int getResolutionLevel() {
return int(params._resolutionInfo.x); return int(params._resolutionInfo.x);
} }
bool isHorizonBased() {
return params._resolutionInfo.y!=0.0;
}
vec2 getNormalsSideSize() { vec2 getNormalsSideSize() {
return params._sideSizes[0].xy; return params._sideSizes[0].xy;
} }

View file

@ -51,9 +51,9 @@ void main(void) {
// Choose the screen-space sample radius // Choose the screen-space sample radius
float diskPixelRadius = evalDiskRadius(fragPositionES.z, sideDepthSize); float diskPixelRadius = evalDiskRadius(fragPositionES.z, sideDepthSize);
#if SSAO_USE_HORIZON_BASED if (isHorizonBased()) {
diskPixelRadius = min(diskPixelRadius, SSAO_HBAO_MAX_RADIUS); diskPixelRadius = min(diskPixelRadius, SSAO_HBAO_MAX_RADIUS);
#endif }
// Let's make noise // Let's make noise
float randomPatternRotationAngle = getAngleDithering(fragPixelPos); float randomPatternRotationAngle = getAngleDithering(fragPixelPos);
@ -63,24 +63,24 @@ void main(void) {
int numSamples = int(getNumSamples()); int numSamples = int(getNumSamples());
float invNumSamples = getInvNumSamples(); float invNumSamples = getInvNumSamples();
// Steps are in the depth texture resolution if (isHorizonBased()) {
vec2 depthTexFragPixelPos = fragUVPos * sideDepthSize; for (int i = 0; i < numSamples; ++i) {
for (int i = 0; i < numSamples; ++i) { vec3 deltaTap = getUnitTapLocation(i, 1.0, randomPatternRotationAngle, PI);
#if SSAO_USE_HORIZON_BASED obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragNormalES);
vec3 deltaTap = getUnitTapLocation(i, 1.0, randomPatternRotationAngle, PI); }
obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragNormalES); obscuranceSum *= 0.5 / PI;
#else } else {
vec3 tap = getTapLocationClampedSSAO(i, randomPatternRotationAngle, diskPixelRadius, depthTexFragPixelPos, sideDepthSize); // Steps are in the depth texture resolution
vec2 tapUV = fragUVPos + tap.xy * deltaDepthUV; vec2 depthTexFragPixelPos = fragUVPos * sideDepthSize;
vec2 tapMipZ = fetchTapWithUV(side, tapUV, tap.z);
vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapMipZ.y, tapUV);
obscuranceSum += float(tap.z > 0.0) * evalVisibilitySSAO(fragPositionES, fragNormalES, tapPositionES);
#endif
}
#if SSAO_USE_HORIZON_BASED for (int i = 0; i < numSamples; ++i) {
obscuranceSum *= 0.5 / PI; vec3 tap = getTapLocationClampedSSAO(i, randomPatternRotationAngle, diskPixelRadius, depthTexFragPixelPos, sideDepthSize);
#endif vec2 tapUV = fragUVPos + tap.xy * deltaDepthUV;
vec2 tapMipZ = fetchTap(side, tapUV, tap.z);
vec3 tapPositionES = evalEyePositionFromZeye(side.x, tapMipZ.y, tapUV);
obscuranceSum += float(tap.z > 0.0) * evalVisibilitySSAO(fragPositionES, fragNormalES, tapPositionES);
}
}
float occlusion = clamp(1.0 - obscuranceSum * getObscuranceScaling() * invNumSamples, 0.0, 1.0); float occlusion = clamp(1.0 - obscuranceSum * getObscuranceScaling() * invNumSamples, 0.0, 1.0);

View file

@ -14,7 +14,6 @@
#ifndef RENDER_UTILS_SSAO_SHARED_H #ifndef RENDER_UTILS_SSAO_SHARED_H
#define RENDER_UTILS_SSAO_SHARED_H #define RENDER_UTILS_SSAO_SHARED_H
#define SSAO_USE_HORIZON_BASED 1
#define SSAO_USE_QUAD_SPLIT 1 #define SSAO_USE_QUAD_SPLIT 1
#if SSAO_USE_QUAD_SPLIT #if SSAO_USE_QUAD_SPLIT

View file

@ -58,6 +58,7 @@ Rectangle {
Column { Column {
Repeater { Repeater {
model: [ model: [
"horizonBased:horizonBased",
"ditheringEnabled:ditheringEnabled", "ditheringEnabled:ditheringEnabled",
"fetchMipsEnabled:fetchMipsEnabled", "fetchMipsEnabled:fetchMipsEnabled",
"borderingEnabled:borderingEnabled" "borderingEnabled:borderingEnabled"