mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
Two group of config settings for SSAO and HBAO
This commit is contained in:
parent
6fcd63ed64
commit
dfe9deb154
6 changed files with 384 additions and 152 deletions
|
@ -206,23 +206,87 @@ gpu::TexturePointer AmbientOcclusionFramebuffer::getNormalTexture() {
|
|||
|
||||
AmbientOcclusionEffectConfig::AmbientOcclusionEffectConfig() :
|
||||
render::GPUJobConfig::Persistent(QStringList() << "Render" << "Engine" << "Ambient Occlusion", false),
|
||||
radius{ 0.7f },
|
||||
perspectiveScale{ 1.0f },
|
||||
obscuranceLevel{ 0.15f },
|
||||
falloffAngle{ 0.1f },
|
||||
edgeSharpness{ 1.0f },
|
||||
blurDeviation{ 2.5f },
|
||||
numSpiralTurns{ 7.0f },
|
||||
numSamples{ 1 },
|
||||
resolutionLevel{ 2 },
|
||||
blurRadius{ 4 },
|
||||
|
||||
ssaoRadius{ 1.0f },
|
||||
ssaoObscuranceLevel{ 0.4f },
|
||||
ssaoFalloffAngle{ 0.1f },
|
||||
ssaoNumSamples{ 32 },
|
||||
ssaoNumSpiralTurns{ 7.0f },
|
||||
|
||||
hbaoRadius{ 0.7f },
|
||||
hbaoObscuranceLevel{ 0.75f },
|
||||
hbaoFalloffAngle{ 0.3f },
|
||||
hbaoNumSamples{ 1 },
|
||||
|
||||
ditheringEnabled{ true },
|
||||
borderingEnabled{ true },
|
||||
fetchMipsEnabled{ true },
|
||||
horizonBased{ true },
|
||||
horizonBased{ false },
|
||||
jitterEnabled{ false }{
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setSSAORadius(float newRadius) {
|
||||
ssaoRadius = std::max(0.01f, newRadius); emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setSSAOObscuranceLevel(float level) {
|
||||
ssaoObscuranceLevel = std::max(0.01f, level);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setSSAOFalloffAngle(float bias) {
|
||||
ssaoFalloffAngle = std::max(0.0f, std::min(bias, 1.0f));
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setSSAONumSpiralTurns(float turns) {
|
||||
ssaoNumSpiralTurns = std::max(0.0f, (float)turns);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setSSAONumSamples(int samples) {
|
||||
ssaoNumSamples = std::max(1.0f, (float)samples);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setHBAORadius(float newRadius) {
|
||||
hbaoRadius = std::max(0.01f, newRadius); emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setHBAOObscuranceLevel(float level) {
|
||||
hbaoObscuranceLevel = std::max(0.01f, level);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setHBAOFalloffAngle(float bias) {
|
||||
hbaoFalloffAngle = std::max(0.0f, std::min(bias, 1.0f));
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setHBAONumSamples(int samples) {
|
||||
hbaoNumSamples = std::max(1.0f, (float)samples);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setEdgeSharpness(float sharpness) {
|
||||
edgeSharpness = std::max(0.0f, (float)sharpness);
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setResolutionLevel(int level) {
|
||||
resolutionLevel = std::max(0, std::min(level, MAX_RESOLUTION_LEVEL));
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffectConfig::setBlurRadius(int radius) {
|
||||
blurRadius = std::max(0, std::min(MAX_BLUR_RADIUS, radius));
|
||||
emit dirty();
|
||||
}
|
||||
|
||||
AmbientOcclusionEffect::AOParameters::AOParameters() {
|
||||
_resolutionInfo = glm::vec4{ 0.0f };
|
||||
_radiusInfo = glm::vec4{ 0.0f };
|
||||
|
@ -242,42 +306,17 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
DependencyManager::get<DeferredLightingEffect>()->setAmbientOcclusionEnabled(config.enabled);
|
||||
|
||||
bool shouldUpdateBlurs = false;
|
||||
bool shouldUpdateTechnique = false;
|
||||
|
||||
_isJitterEnabled = config.jitterEnabled;
|
||||
|
||||
const double RADIUS_POWER = 6.0;
|
||||
const auto& radius = config.radius;
|
||||
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 (!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()) {
|
||||
auto& current = _aoParametersBuffer.edit()._radiusInfo;
|
||||
current.w = config.obscuranceLevel;
|
||||
}
|
||||
|
||||
if (config.falloffAngle != _aoParametersBuffer->getFalloffCosAngle()) {
|
||||
auto& current = _aoParametersBuffer.edit()._falloffInfo;
|
||||
current.x = config.falloffAngle;
|
||||
current.y = 1.0f / (1.0f - current.x);
|
||||
// Compute sin from cos
|
||||
current.z = sqrtf(1.0f - config.falloffAngle * config.falloffAngle);
|
||||
current.w = 1.0f / current.z;
|
||||
if (!_framebuffer) {
|
||||
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
||||
shouldUpdateBlurs = true;
|
||||
}
|
||||
|
||||
// Update bilateral blur
|
||||
{
|
||||
if (config.blurRadius != _hblurParametersBuffer->getBlurRadius() || _blurEdgeSharpness != config.edgeSharpness) {
|
||||
const float BLUR_EDGE_DISTANCE_SCALE = float(10000 * SSAO_DEPTH_KEY_SCALE);
|
||||
const float BLUR_EDGE_NORMAL_SCALE = 2.0f;
|
||||
|
||||
|
@ -287,6 +326,8 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
float blurRadialScale = 1.0f / (2.0f*blurRadialSigma*blurRadialSigma);
|
||||
glm::vec3 blurScales = -glm::vec3(blurRadialScale, glm::vec2(BLUR_EDGE_DISTANCE_SCALE, BLUR_EDGE_NORMAL_SCALE) * config.edgeSharpness);
|
||||
|
||||
_blurEdgeSharpness = config.edgeSharpness;
|
||||
|
||||
hblur.x = blurScales.x;
|
||||
hblur.y = blurScales.y;
|
||||
hblur.z = blurScales.z;
|
||||
|
@ -298,33 +339,10 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
vblur.w = (float)config.blurRadius;
|
||||
}
|
||||
|
||||
if (config.numSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
|
||||
auto& current = _aoParametersBuffer.edit()._sampleInfo;
|
||||
current.z = config.numSpiralTurns;
|
||||
}
|
||||
|
||||
if (config.numSamples != _aoParametersBuffer->getNumSamples()) {
|
||||
auto& current = _aoParametersBuffer.edit()._sampleInfo;
|
||||
current.x = config.numSamples;
|
||||
current.y = 1.0f / config.numSamples;
|
||||
|
||||
// Regenerate offsets
|
||||
const int B = 3;
|
||||
const float invB = 1.0f / (float)B;
|
||||
|
||||
for (int i = 0; i < _randomSamples.size(); i++) {
|
||||
int index = i+1; // Indices start at 1, not 0
|
||||
float f = 1.0f;
|
||||
float r = 0.0f;
|
||||
|
||||
while (index > 0) {
|
||||
f = f * invB;
|
||||
r = r + f * (float)(index % B);
|
||||
index = index / B;
|
||||
}
|
||||
_randomSamples[i] = r * 2.0f * M_PI / config.numSamples;
|
||||
}
|
||||
updateJitterSamples();
|
||||
if (_aoParametersBuffer->isHorizonBased() != config.horizonBased) {
|
||||
auto& current = _aoParametersBuffer.edit()._resolutionInfo;
|
||||
current.y = config.horizonBased & 1;
|
||||
shouldUpdateTechnique = true;
|
||||
}
|
||||
|
||||
if (config.fetchMipsEnabled != _aoParametersBuffer->isFetchMipsEnabled()) {
|
||||
|
@ -332,11 +350,6 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
current.w = (float)config.fetchMipsEnabled;
|
||||
}
|
||||
|
||||
if (!_framebuffer) {
|
||||
_framebuffer = std::make_shared<AmbientOcclusionFramebuffer>();
|
||||
shouldUpdateBlurs = true;
|
||||
}
|
||||
|
||||
if (config.perspectiveScale != _aoParametersBuffer->getPerspectiveScale()) {
|
||||
_aoParametersBuffer.edit()._resolutionInfo.z = config.perspectiveScale;
|
||||
}
|
||||
|
@ -357,11 +370,102 @@ void AmbientOcclusionEffect::configure(const Config& config) {
|
|||
current.w = (float)config.borderingEnabled;
|
||||
}
|
||||
|
||||
if (config.horizonBased) {
|
||||
// Configure for HBAO
|
||||
const auto& radius = config.hbaoRadius;
|
||||
if (shouldUpdateTechnique || radius != _aoParametersBuffer->getRadius()) {
|
||||
auto& current = _aoParametersBuffer.edit()._radiusInfo;
|
||||
current.x = radius;
|
||||
current.y = radius * radius;
|
||||
current.z = 1.0f / current.y;
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.hbaoObscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
|
||||
auto& current = _aoParametersBuffer.edit()._radiusInfo;
|
||||
current.w = config.hbaoObscuranceLevel;
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.hbaoFalloffAngle != _aoParametersBuffer->getFalloffAngle()) {
|
||||
auto& current = _aoParametersBuffer.edit()._falloffInfo;
|
||||
current.x = config.hbaoFalloffAngle;
|
||||
current.y = 1.0f / (1.0f - current.x);
|
||||
// Compute sin from cos
|
||||
current.z = sqrtf(1.0f - config.hbaoFalloffAngle * config.hbaoFalloffAngle);
|
||||
current.w = 1.0f / current.z;
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.hbaoNumSamples != _aoParametersBuffer->getNumSamples()) {
|
||||
auto& current = _aoParametersBuffer.edit()._sampleInfo;
|
||||
current.x = config.hbaoNumSamples;
|
||||
current.y = 1.0f / config.hbaoNumSamples;
|
||||
updateRandomSamples();
|
||||
updateJitterSamples();
|
||||
}
|
||||
} else {
|
||||
// Configure for SSAO
|
||||
const double RADIUS_POWER = 6.0;
|
||||
const auto& radius = config.ssaoRadius;
|
||||
if (shouldUpdateTechnique || radius != _aoParametersBuffer->getRadius()) {
|
||||
auto& current = _aoParametersBuffer.edit()._radiusInfo;
|
||||
current.x = radius;
|
||||
current.y = radius * radius;
|
||||
current.z = (float)(10.0 / pow((double)radius, RADIUS_POWER));
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.ssaoObscuranceLevel != _aoParametersBuffer->getObscuranceLevel()) {
|
||||
auto& current = _aoParametersBuffer.edit()._radiusInfo;
|
||||
current.w = config.ssaoObscuranceLevel;
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.ssaoFalloffAngle != _aoParametersBuffer->getFalloffAngle()) {
|
||||
auto& current = _aoParametersBuffer.edit()._falloffInfo;
|
||||
current.x = config.ssaoFalloffAngle;
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.ssaoNumSpiralTurns != _aoParametersBuffer->getNumSpiralTurns()) {
|
||||
auto& current = _aoParametersBuffer.edit()._sampleInfo;
|
||||
current.z = config.ssaoNumSpiralTurns;
|
||||
}
|
||||
|
||||
if (shouldUpdateTechnique || config.ssaoNumSamples != _aoParametersBuffer->getNumSamples()) {
|
||||
auto& current = _aoParametersBuffer.edit()._sampleInfo;
|
||||
current.x = config.ssaoNumSamples;
|
||||
current.y = 1.0f / config.ssaoNumSamples;
|
||||
updateRandomSamples();
|
||||
updateJitterSamples();
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldUpdateBlurs) {
|
||||
updateBlurParameters();
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::updateRandomSamples() {
|
||||
// Regenerate offsets
|
||||
if (_aoParametersBuffer->isHorizonBased()) {
|
||||
const int B = 3;
|
||||
const float invB = 1.0f / (float)B;
|
||||
float sampleScale = 2.0f * M_PI / _aoParametersBuffer->getNumSamples();
|
||||
|
||||
for (int i = 0; i < _randomSamples.size(); i++) {
|
||||
int index = i + 1; // Indices start at 1, not 0
|
||||
float f = 1.0f;
|
||||
float r = 0.0f;
|
||||
|
||||
while (index > 0) {
|
||||
f = f * invB;
|
||||
r = r + f * (float)(index % B);
|
||||
index = index / B;
|
||||
}
|
||||
_randomSamples[i] = r * sampleScale;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < _randomSamples.size(); i++) {
|
||||
_randomSamples[i] = randFloat() * 2.0f * M_PI;
|
||||
}
|
||||
}
|
||||
}
|
||||
void AmbientOcclusionEffect::updateBlurParameters() {
|
||||
const auto resolutionLevel = _aoParametersBuffer->getResolutionLevel();
|
||||
auto& vblur = _vblurParametersBuffer.edit();
|
||||
|
@ -477,9 +581,14 @@ int AmbientOcclusionEffect::getDepthResolutionLevel() const {
|
|||
}
|
||||
|
||||
void AmbientOcclusionEffect::updateJitterSamples() {
|
||||
for (int splitId = 0; splitId < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT; splitId++) {
|
||||
auto& sample = _aoFrameParametersBuffer[splitId].edit();
|
||||
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
|
||||
if (_aoParametersBuffer->isHorizonBased()) {
|
||||
for (int splitId = 0; splitId < SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT; splitId++) {
|
||||
auto& sample = _aoFrameParametersBuffer[splitId].edit();
|
||||
sample._angleInfo.x = _randomSamples[splitId + SSAO_RANDOM_SAMPLE_COUNT * _frameId];
|
||||
}
|
||||
} else {
|
||||
auto& sample = _aoFrameParametersBuffer[0].edit();
|
||||
sample._angleInfo.x = _randomSamples[_frameId];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -594,57 +703,69 @@ void AmbientOcclusionEffect::run(const render::RenderContextPointer& renderConte
|
|||
batch.setPipeline(occlusionPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoDepth, occlusionDepthTexture);
|
||||
|
||||
if (_aoParametersBuffer->isHorizonBased()) {
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
||||
{
|
||||
const auto uvScale = glm::vec3(
|
||||
(splitSize.x * SSAO_SPLIT_COUNT) / float(occlusionViewport.z),
|
||||
(splitSize.y * SSAO_SPLIT_COUNT) / float(occlusionViewport.w),
|
||||
1.0f);
|
||||
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionViewport.z, occlusionViewport.w);
|
||||
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize);
|
||||
Transform model;
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
||||
{
|
||||
const auto uvScale = glm::vec3(
|
||||
(splitSize.x * SSAO_SPLIT_COUNT) / float(occlusionViewport.z),
|
||||
(splitSize.y * SSAO_SPLIT_COUNT) / float(occlusionViewport.w),
|
||||
1.0f);
|
||||
const auto postPixelOffset = glm::vec2(0.5f) / glm::vec2(occlusionViewport.z, occlusionViewport.w);
|
||||
const auto prePixelOffset = glm::vec2(0.5f * uvScale.x, 0.5f * uvScale.y) / glm::vec2(splitSize);
|
||||
Transform model;
|
||||
|
||||
batch.setViewportTransform(splitViewport);
|
||||
batch.setViewportTransform(splitViewport);
|
||||
|
||||
model.setScale(uvScale);
|
||||
for (int y = 0; y < SSAO_SPLIT_COUNT; y++) {
|
||||
for (int x = 0; x < SSAO_SPLIT_COUNT; x++) {
|
||||
const int splitIndex = x + y * SSAO_SPLIT_COUNT;
|
||||
const auto uvTranslate = glm::vec3(
|
||||
postPixelOffset.x * (2 * x + 1) - prePixelOffset.x,
|
||||
postPixelOffset.y * (2 * y + 1) - prePixelOffset.y,
|
||||
0.0f
|
||||
model.setScale(uvScale);
|
||||
for (int y = 0; y < SSAO_SPLIT_COUNT; y++) {
|
||||
for (int x = 0; x < SSAO_SPLIT_COUNT; x++) {
|
||||
const int splitIndex = x + y * SSAO_SPLIT_COUNT;
|
||||
const auto uvTranslate = glm::vec3(
|
||||
postPixelOffset.x * (2 * x + 1) - prePixelOffset.x,
|
||||
postPixelOffset.y * (2 * y + 1) - prePixelOffset.y,
|
||||
0.0f
|
||||
);
|
||||
model.setTranslation(uvTranslate);
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(splitIndex));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[splitIndex]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
model.setTranslation(uvTranslate);
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(_framebuffer->getOcclusionSplitFramebuffer(splitIndex));
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[splitIndex]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
model.setIdentity();
|
||||
batch.setModelTransform(model);
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
#endif
|
||||
} else {
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoNormal, occlusionNormalTexture);
|
||||
#endif
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setUniformBuffer(render_utils::slot::buffer::SsaoFrameParams, _aoFrameParametersBuffer[0]);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
}
|
||||
|
||||
batch.popProfileRange();
|
||||
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
// Gather back the four separate renders into one interleaved one
|
||||
batch.pushProfileRange("Gather");
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setPipeline(gatherPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, _framebuffer->getOcclusionSplitTexture());
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.popProfileRange();
|
||||
if (_aoParametersBuffer->isHorizonBased()) {
|
||||
// Gather back the four separate renders into one interleaved one
|
||||
batch.pushProfileRange("Gather");
|
||||
batch.setViewportTransform(occlusionViewport);
|
||||
batch.setModelTransform(Transform());
|
||||
batch.setFramebuffer(occlusionFBO);
|
||||
batch.setPipeline(gatherPipeline);
|
||||
batch.setResourceTexture(render_utils::slot::texture::SsaoOcclusion, _framebuffer->getOcclusionSplitTexture());
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 4);
|
||||
batch.popProfileRange();
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
|
|
|
@ -84,42 +84,61 @@ class AmbientOcclusionEffectConfig : public render::GPUJobConfig::Persistent {
|
|||
Q_PROPERTY(bool borderingEnabled MEMBER borderingEnabled NOTIFY dirty)
|
||||
Q_PROPERTY(bool fetchMipsEnabled MEMBER fetchMipsEnabled NOTIFY dirty)
|
||||
Q_PROPERTY(bool jitterEnabled MEMBER jitterEnabled 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(float edgeSharpness MEMBER edgeSharpness WRITE setEdgeSharpness)
|
||||
Q_PROPERTY(int blurRadius MEMBER blurRadius WRITE setBlurRadius)
|
||||
|
||||
// SSAO
|
||||
Q_PROPERTY(float ssaoRadius MEMBER ssaoRadius WRITE setSSAORadius)
|
||||
Q_PROPERTY(float ssaoObscuranceLevel MEMBER ssaoObscuranceLevel WRITE setSSAOObscuranceLevel)
|
||||
Q_PROPERTY(float ssaoFalloffAngle MEMBER ssaoFalloffAngle WRITE setSSAOFalloffAngle)
|
||||
Q_PROPERTY(float ssaoNumSpiralTurns MEMBER ssaoNumSpiralTurns WRITE setSSAONumSpiralTurns)
|
||||
Q_PROPERTY(int ssaoNumSamples MEMBER ssaoNumSamples WRITE setSSAONumSamples)
|
||||
|
||||
// HBAO
|
||||
Q_PROPERTY(float hbaoRadius MEMBER hbaoRadius WRITE setHBAORadius)
|
||||
Q_PROPERTY(float hbaoObscuranceLevel MEMBER hbaoObscuranceLevel WRITE setHBAOObscuranceLevel)
|
||||
Q_PROPERTY(float hbaoFalloffAngle MEMBER hbaoFalloffAngle WRITE setHBAOFalloffAngle)
|
||||
Q_PROPERTY(int hbaoNumSamples MEMBER hbaoNumSamples WRITE setHBAONumSamples)
|
||||
|
||||
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(); }
|
||||
void setEdgeSharpness(float sharpness);
|
||||
void setResolutionLevel(int level);
|
||||
void setBlurRadius(int radius);
|
||||
|
||||
void setSSAORadius(float newRadius);
|
||||
void setSSAOObscuranceLevel(float level);
|
||||
void setSSAOFalloffAngle(float bias);
|
||||
void setSSAONumSpiralTurns(float turns);
|
||||
void setSSAONumSamples(int samples);
|
||||
|
||||
void setHBAORadius(float newRadius);
|
||||
void setHBAOObscuranceLevel(float level);
|
||||
void setHBAOFalloffAngle(float bias);
|
||||
void setHBAONumSamples(int samples);
|
||||
|
||||
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
|
||||
int resolutionLevel;
|
||||
|
||||
float ssaoRadius;
|
||||
float ssaoObscuranceLevel; // intensify or dim down the obscurance effect
|
||||
float ssaoFalloffAngle;
|
||||
float ssaoNumSpiralTurns; // defining an angle span to distribute the samples ray directions
|
||||
int ssaoNumSamples;
|
||||
|
||||
float hbaoRadius;
|
||||
float hbaoObscuranceLevel; // intensify or dim down the obscurance effect
|
||||
float hbaoFalloffAngle;
|
||||
int hbaoNumSamples;
|
||||
|
||||
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
|
||||
|
@ -154,7 +173,7 @@ public:
|
|||
float getRadius() const { return _radiusInfo.x; }
|
||||
float getPerspectiveScale() const { return _resolutionInfo.z; }
|
||||
float getObscuranceLevel() const { return _radiusInfo.w; }
|
||||
float getFalloffCosAngle() const { return (float)_falloffInfo.x; }
|
||||
float getFalloffAngle() const { return (float)_falloffInfo.x; }
|
||||
|
||||
float getNumSpiralTurns() const { return _sampleInfo.z; }
|
||||
int getNumSamples() const { return (int)_sampleInfo.x; }
|
||||
|
@ -176,7 +195,7 @@ private:
|
|||
BlurParameters();
|
||||
|
||||
float getEdgeSharpness() const { return (float)_blurInfo.x; }
|
||||
int getBlurRadius() const { return (int)_blurInfo.y; }
|
||||
int getBlurRadius() const { return (int)_blurInfo.w; }
|
||||
|
||||
};
|
||||
using BlurParametersBuffer = gpu::StructBuffer<BlurParameters>;
|
||||
|
@ -185,6 +204,7 @@ private:
|
|||
|
||||
void updateBlurParameters();
|
||||
void updateFramebufferSizes();
|
||||
void updateRandomSamples();
|
||||
void updateJitterSamples();
|
||||
|
||||
int getDepthResolutionLevel() const;
|
||||
|
@ -193,6 +213,7 @@ private:
|
|||
FrameParametersBuffer _aoFrameParametersBuffer[SSAO_SPLIT_COUNT*SSAO_SPLIT_COUNT];
|
||||
BlurParametersBuffer _vblurParametersBuffer;
|
||||
BlurParametersBuffer _hblurParametersBuffer;
|
||||
float _blurEdgeSharpness{ 0.0f };
|
||||
|
||||
static const gpu::PipelinePointer& getOcclusionPipeline();
|
||||
static const gpu::PipelinePointer& getBilateralBlurPipeline();
|
||||
|
|
|
@ -86,7 +86,7 @@ void LinearDepthFramebuffer::allocate() {
|
|||
const uint16_t HALF_LINEAR_DEPTH_MAX_MIP_LEVEL = 5;
|
||||
// Point sampling of the depth, as well as the clamp to edge, are needed for the AmbientOcclusionEffect with HBAO
|
||||
const auto depthSamplerHalf = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_POINT, gpu::Sampler::WRAP_CLAMP);
|
||||
_halfLinearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::FLOAT, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL,
|
||||
_halfLinearDepthTexture = gpu::Texture::createRenderBuffer(gpu::Element(gpu::SCALAR, gpu::HALF, gpu::RED), _halfFrameSize.x, _halfFrameSize.y, HALF_LINEAR_DEPTH_MAX_MIP_LEVEL,
|
||||
depthSamplerHalf);
|
||||
|
||||
_halfNormalTexture = gpu::Texture::createRenderBuffer(gpu::Element::COLOR_RGBA_32, _halfFrameSize.x, _halfFrameSize.y, gpu::Texture::SINGLE_MIP,
|
||||
|
|
|
@ -107,11 +107,14 @@ float getRadius2() {
|
|||
return params._radiusInfo.y;
|
||||
}
|
||||
float getInvRadius6() {
|
||||
return mix(params._radiusInfo.z, 1.0, isHorizonBased());
|
||||
}
|
||||
float getInvRadius2() {
|
||||
return params._radiusInfo.z;
|
||||
}
|
||||
|
||||
float getObscuranceScaling() {
|
||||
return params._radiusInfo.z * params._radiusInfo.w;
|
||||
return getInvRadius6() * params._radiusInfo.w;
|
||||
}
|
||||
|
||||
float isDitheringEnabled() {
|
||||
|
@ -161,15 +164,24 @@ float getAngleDitheringWorldPos(in vec3 pixelWorldPos) {
|
|||
return isDitheringEnabled() * float(((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) + (3 * pixelPos.y ^ pixelPos.z + pixelPos.x * pixelPos.z)) * 10);
|
||||
}
|
||||
|
||||
float getAngleDitheringSplit() {
|
||||
return isDitheringEnabled() * frameParams._angleInfo.x;
|
||||
}
|
||||
|
||||
float getAngleDithering(in ivec2 pixelPos) {
|
||||
#if SSAO_USE_QUAD_SPLIT
|
||||
return isDitheringEnabled() * frameParams._angleInfo.x;
|
||||
return getAngleDitheringSplit();
|
||||
#else
|
||||
// Hash function used in the AlchemyAO paper
|
||||
return isDitheringEnabled() * float((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10);
|
||||
return getAngleDitheringPixelPos(pixelPos);
|
||||
#endif
|
||||
}
|
||||
|
||||
float getAngleDitheringPixelPos(in ivec2 pixelPos) {
|
||||
// Hash function used in the AlchemyAO paper
|
||||
return isDitheringEnabled() * float((3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10);
|
||||
}
|
||||
|
||||
float evalDiskRadius(float Zeye, vec2 sideImageSize) {
|
||||
// Choose the screen-space sample radius
|
||||
// proportional to the projected area of the sphere
|
||||
|
@ -413,7 +425,7 @@ float evalVisibilitySSAO(in vec3 centerPosition, in vec3 centerNormal, in vec3 t
|
|||
#define HBAO_USE_OVERHANG_HACK 0
|
||||
|
||||
float computeWeightForHorizon(float horizonLimit, float distanceSquared) {
|
||||
return max(0.0, 1.0 - distanceSquared / getRadius2());
|
||||
return max(0.0, 1.0 - distanceSquared * getInvRadius2());
|
||||
}
|
||||
|
||||
float computeWeightedHorizon(float horizonLimit, float distanceSquared) {
|
||||
|
|
|
@ -37,13 +37,18 @@ void main(void) {
|
|||
|
||||
// Stereo side info based on the real viewport size of this pass
|
||||
vec2 sideDepthSize = getDepthTextureSideSize(0);
|
||||
ivec2 sideOcclusionSize = ivec2( getOcclusionSplitSideSize() );
|
||||
ivec2 sideOcclusionSize;
|
||||
if (isHorizonBased()) {
|
||||
sideOcclusionSize = ivec2( getOcclusionSplitSideSize() );
|
||||
} else {
|
||||
sideOcclusionSize = ivec2( getOcclusionSideSize() );
|
||||
}
|
||||
ivec4 side = getStereoSideInfoFromWidth(fragPixelPos.x, sideOcclusionSize.x);
|
||||
// From now on, fragUVPos is the UV pos in the side
|
||||
fragUVPos.x = mix(fragUVPos.x, fragUVPos.x * 2.0 - getStereoSide(side), isStereo());
|
||||
|
||||
fragUVPos = snapToTexel(fragUVPos, sideDepthSize);
|
||||
|
||||
|
||||
// The position and normal of the pixel fragment in Eye space
|
||||
vec2 deltaDepthUV = vec2(2.0) / sideDepthSize;
|
||||
vec3 fragPositionES = buildPosition(side, fragUVPos);
|
||||
|
@ -58,7 +63,7 @@ void main(void) {
|
|||
}
|
||||
|
||||
// Let's make noise
|
||||
float randomPatternRotationAngle = getAngleDithering(fragPixelPos);
|
||||
float randomPatternRotationAngle = 0.0;
|
||||
|
||||
// Accumulate the obscurance for each samples
|
||||
float obscuranceSum = 0.0;
|
||||
|
@ -66,22 +71,24 @@ void main(void) {
|
|||
float invNumSamples = getInvNumSamples();
|
||||
|
||||
if (isHorizonBased()) {
|
||||
randomPatternRotationAngle = getAngleDithering(fragPixelPos);
|
||||
|
||||
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 *= invNumSamples;
|
||||
#if HBAO_USE_COS_ANGLE
|
||||
obscuranceSum *= 0.5;
|
||||
obscuranceSum = 1.0 - obscuranceSum * getObscuranceScaling();
|
||||
#else
|
||||
obscuranceSum *= 0.5;
|
||||
obscuranceSum = mix(1.0, obscuranceSum, getObscuranceScaling());
|
||||
#endif
|
||||
} else {
|
||||
// Steps are in the depth texture resolution
|
||||
vec2 depthTexFragPixelPos = fragUVPos * sideDepthSize;
|
||||
|
||||
randomPatternRotationAngle = getAngleDitheringPixelPos(fragPixelPos) + getAngleDitheringSplit();
|
||||
|
||||
for (int i = 0; i < numSamples; ++i) {
|
||||
vec3 tap = getTapLocationClampedSSAO(i, randomPatternRotationAngle, diskPixelRadius, depthTexFragPixelPos, sideDepthSize);
|
||||
vec2 tapUV = fragUVPos + tap.xy * deltaDepthUV;
|
||||
|
@ -90,7 +97,7 @@ void main(void) {
|
|||
obscuranceSum += float(tap.z > 0.0) * evalVisibilitySSAO(fragPositionES, fragNormalES, tapPositionES);
|
||||
}
|
||||
obscuranceSum *= invNumSamples;
|
||||
obscuranceSum = 1.0 - obscuranceSum * obscuranceSum * getObscuranceScaling();
|
||||
obscuranceSum = 1.0 - obscuranceSum * getObscuranceScaling();
|
||||
}
|
||||
|
||||
float occlusion = clamp(obscuranceSum, 0.0, 1.0);
|
||||
|
|
|
@ -33,11 +33,6 @@ Rectangle {
|
|||
|
||||
Repeater {
|
||||
model: [
|
||||
"Radius:radius:2.0:false",
|
||||
"Level:obscuranceLevel:1.0:false",
|
||||
"Num Taps:numSamples:16:true",
|
||||
"Taps Spiral:numSpiralTurns:10.0:false",
|
||||
"Falloff Angle:falloffAngle:1.0:false",
|
||||
"Blur Edge Sharpness:edgeSharpness:1.0:false",
|
||||
"Blur Radius:blurRadius:15.0:true",
|
||||
"Resolution Downscale:resolutionLevel:2:true",
|
||||
|
@ -102,5 +97,81 @@ Rectangle {
|
|||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
TabView {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 400
|
||||
|
||||
Tab {
|
||||
title: "SSAO"
|
||||
|
||||
Rectangle {
|
||||
color: hifi.colors.baseGray;
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: hifi.dimensions.contentMargin.x
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
"Radius:ssaoRadius:2.0:false",
|
||||
"Level:ssaoObscuranceLevel:1.0:false",
|
||||
"Num Taps:ssaoNumSamples:64:true",
|
||||
"Taps Spiral:ssaoNumSpiralTurns:10.0:false",
|
||||
"Falloff Angle:ssaoFalloffAngle:1.0:false",
|
||||
]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
integral: (modelData.split(":")[3] == 'true')
|
||||
config: Render.getConfig("RenderMainView.AmbientOcclusion")
|
||||
property: modelData.split(":")[1]
|
||||
max: modelData.split(":")[2]
|
||||
min: 0.0
|
||||
height:38
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
title: "HBAO"
|
||||
|
||||
Rectangle {
|
||||
color: hifi.colors.baseGray;
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.margins: hifi.dimensions.contentMargin.x
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
"Radius:hbaoRadius:2.0:false",
|
||||
"Level:hbaoObscuranceLevel:1.0:false",
|
||||
"Num Taps:hbaoNumSamples:6:true",
|
||||
"Falloff Angle:hbaoFalloffAngle:1.0:false",
|
||||
]
|
||||
ConfigSlider {
|
||||
label: qsTr(modelData.split(":")[0])
|
||||
integral: (modelData.split(":")[3] == 'true')
|
||||
config: Render.getConfig("RenderMainView.AmbientOcclusion")
|
||||
property: modelData.split(":")[1]
|
||||
max: modelData.split(":")[2]
|
||||
min: 0.0
|
||||
height:38
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue