mirror of
https://github.com/lubosz/overte.git
synced 2025-04-10 03:42:45 +02:00
Added config parameter to switch between HBAO / SSAO
This commit is contained in:
parent
94a162893a
commit
349a8b39ad
6 changed files with 51 additions and 53 deletions
|
@ -202,36 +202,24 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
|
|||
|
||||
AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
|
||||
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false),
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
radius{ 0.3f },
|
||||
#else
|
||||
radius{ 0.5f },
|
||||
#endif
|
||||
perspectiveScale{ 1.0f },
|
||||
obscuranceLevel{ 0.5f },
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
falloffAngle{ 0.3f },
|
||||
#else
|
||||
falloffAngle{ 0.01f },
|
||||
#endif
|
||||
edgeSharpness{ 1.0f },
|
||||
blurDeviation{ 2.5f },
|
||||
numSpiralTurns{ 7.0f },
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
numSamples{ 1 },
|
||||
#else
|
||||
numSamples{ 16 },
|
||||
#endif
|
||||
resolutionLevel{ 2 },
|
||||
blurRadius{ 4 },
|
||||
ditheringEnabled{ true },
|
||||
borderingEnabled{ true },
|
||||
fetchMipsEnabled{ true } {
|
||||
|
||||
fetchMipsEnabled{ true },
|
||||
horizonBased{ true } {
|
||||
}
|
||||
|
||||
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 };
|
||||
_ditheringInfo = { 0.0f, 0.0f, 0.01f, 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 auto& radius = config.radius;
|
||||
if (radius != _aoParametersBuffer->getRadius()) {
|
||||
if (radius != _aoParametersBuffer->getRadius() || config.horizonBased != _aoParametersBuffer->isHorizonBased()) {
|
||||
auto& current = _aoParametersBuffer.edit()._radiusInfo;
|
||||
current.x = radius;
|
||||
current.y = radius * radius;
|
||||
current.z = 10.0f;
|
||||
#if !SSAO_USE_HORIZON_BASED
|
||||
current.z *= (float)(1.0 / pow((double)radius, RADIUS_POWER));
|
||||
#endif
|
||||
if (!config.horizonBased) {
|
||||
current.z *= (float)(1.0 / pow((double)radius, RADIUS_POWER));
|
||||
}
|
||||
}
|
||||
|
||||
if (config.horizonBased != _aoParametersBuffer->isHorizonBased()) {
|
||||
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
|
||||
current.y = config.horizonBased & 1;
|
||||
}
|
||||
|
||||
if (config.obscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
|
||||
|
@ -501,6 +494,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
|
||||
const auto depthResolutionLevel = getDepthResolutionLevel();
|
||||
const auto depthResolutionScale = powf(0.5f, depthResolutionLevel);
|
||||
const auto isHorizonBased = _aoParametersBuffer->isHorizonBased();
|
||||
|
||||
auto linearDepthTexture = linearDepthFramebuffer->getLinearDepthTexture();
|
||||
auto occlusionDepthTexture = linearDepthTexture;
|
||||
|
@ -538,9 +532,7 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
auto occlusionPipeline = getOcclusionPipeline();
|
||||
auto firstHBlurPipeline = getHBlurPipeline();
|
||||
auto lastVBlurPipeline = getVBlurPipeline();
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
auto mipCreationPipeline = getMipCreationPipeline();
|
||||
#endif
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
auto gatherPipeline = getGatherPipeline();
|
||||
auto buildNormalsPipeline = getBuildNormalsPipeline();
|
||||
|
@ -571,14 +563,14 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
batch.setProjectionTransform(glm::mat4());
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
batch.pushProfileRange("Depth Mip Generation");
|
||||
// We need this with the mips levels
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
batch.setPipeline(mipCreationPipeline);
|
||||
batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
|
||||
#else
|
||||
batch.generateTextureMips(occlusionDepthTexture);
|
||||
#endif
|
||||
batch.pushProfileRange("Depth Mip Generation");
|
||||
if (isHorizonBased) {
|
||||
batch.setPipeline(mipCreationPipeline);
|
||||
batch.generateTextureMipsWithPipeline(occlusionDepthTexture);
|
||||
} else {
|
||||
batch.generateTextureMips(occlusionDepthTexture);
|
||||
}
|
||||
batch.popProfileRange();
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
|
@ -731,8 +723,6 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage());
|
||||
}
|
||||
|
||||
|
||||
|
||||
DebugAmbientOcclusion::DebugAmbientOcclusion() {
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ using AmbientOcclusionFramebufferPointer = std::shared_ptr<AmbientOcclusionFrame
|
|||
class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
|
||||
Q_OBJECT
|
||||
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 borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
|
||||
Q_PROPERTY(bool fetchMipsEnabled MEMBER fetchMipsEnabled NOTIFY dirty)
|
||||
|
@ -118,6 +119,7 @@ public:
|
|||
int numSamples;
|
||||
int resolutionLevel;
|
||||
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 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
|
||||
|
@ -154,8 +156,10 @@ public:
|
|||
int getNumSamples() const { return (int)_sampleInfo.x; }
|
||||
bool isFetchMipsEnabled() const { return _sampleInfo.w; }
|
||||
|
||||
bool isDitheringEnabled() const { return _ditheringInfo.x; }
|
||||
bool isBorderingEnabled() const { return _ditheringInfo.w; }
|
||||
bool isDitheringEnabled() const { return _ditheringInfo.x != 0.0f; }
|
||||
bool isBorderingEnabled() const { return _ditheringInfo.w != 0.0f; }
|
||||
bool isHorizonBased() const { return _resolutionInfo.y != 0.0f; }
|
||||
|
||||
};
|
||||
using AOParametersBuffer = gpu::StructBuffer<AOParameters>;
|
||||
|
||||
|
|
|
@ -51,6 +51,10 @@ int getResolutionLevel() {
|
|||
return int(params._resolutionInfo.x);
|
||||
}
|
||||
|
||||
bool isHorizonBased() {
|
||||
return params._resolutionInfo.y!=0.0;
|
||||
}
|
||||
|
||||
vec2 getNormalsSideSize() {
|
||||
return params._sideSizes[0].xy;
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ void main(void) {
|
|||
|
||||
// Choose the screen-space sample radius
|
||||
float diskPixelRadius = evalDiskRadius(fragPositionES.z, sideDepthSize);
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
diskPixelRadius = min(diskPixelRadius, SSAO_HBAO_MAX_RADIUS);
|
||||
#endif
|
||||
if (isHorizonBased()) {
|
||||
diskPixelRadius = min(diskPixelRadius, SSAO_HBAO_MAX_RADIUS);
|
||||
}
|
||||
|
||||
// Let's make noise
|
||||
float randomPatternRotationAngle = getAngleDithering(fragPixelPos);
|
||||
|
@ -63,24 +63,24 @@ void main(void) {
|
|||
int numSamples = int(getNumSamples());
|
||||
float invNumSamples = getInvNumSamples();
|
||||
|
||||
// Steps are in the depth texture resolution
|
||||
vec2 depthTexFragPixelPos = fragUVPos * sideDepthSize;
|
||||
for (int i = 0; i < numSamples; ++i) {
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
vec3 deltaTap = getUnitTapLocation(i, 1.0, randomPatternRotationAngle, PI);
|
||||
obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragNormalES);
|
||||
#else
|
||||
vec3 tap = getTapLocationClampedSSAO(i, randomPatternRotationAngle, diskPixelRadius, depthTexFragPixelPos, sideDepthSize);
|
||||
vec2 tapUV = fragUVPos + tap.xy * deltaDepthUV;
|
||||
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 (isHorizonBased()) {
|
||||
for (int i = 0; i < numSamples; ++i) {
|
||||
vec3 deltaTap = getUnitTapLocation(i, 1.0, randomPatternRotationAngle, PI);
|
||||
obscuranceSum += evalVisibilityHBAO(side, fragUVPos, deltaDepthUV, deltaTap.xy, diskPixelRadius, fragPositionES, fragNormalES);
|
||||
}
|
||||
obscuranceSum *= 0.5 / PI;
|
||||
} else {
|
||||
// Steps are in the depth texture resolution
|
||||
vec2 depthTexFragPixelPos = fragUVPos * sideDepthSize;
|
||||
|
||||
#if SSAO_USE_HORIZON_BASED
|
||||
obscuranceSum *= 0.5 / PI;
|
||||
#endif
|
||||
for (int i = 0; i < numSamples; ++i) {
|
||||
vec3 tap = getTapLocationClampedSSAO(i, randomPatternRotationAngle, diskPixelRadius, depthTexFragPixelPos, sideDepthSize);
|
||||
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);
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#ifndef RENDER_UTILS_SSAO_SHARED_H
|
||||
#define RENDER_UTILS_SSAO_SHARED_H
|
||||
|
||||
#define SSAO_USE_HORIZON_BASED 1
|
||||
#define SSAO_USE_QUAD_SPLIT 1
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
|
|
|
@ -58,6 +58,7 @@ Rectangle {
|
|||
Column {
|
||||
Repeater {
|
||||
model: [
|
||||
"horizonBased:horizonBased",
|
||||
"ditheringEnabled:ditheringEnabled",
|
||||
"fetchMipsEnabled:fetchMipsEnabled",
|
||||
"borderingEnabled:borderingEnabled"
|
||||
|
|
Loading…
Reference in a new issue