mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 11:33:44 +02:00
Exposing many more controls of the AO in order to adjust the effect
This commit is contained in:
parent
89d2d102f6
commit
0285d48de3
8 changed files with 108 additions and 21 deletions
|
@ -109,6 +109,21 @@ panel.newSlider("Ambient Occlusion Level", 0.0, 1.0,
|
|||
function() { return Render.ambientOcclusion.level; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Num Samples", 1, 32,
|
||||
function (value) { Render.ambientOcclusion.numSamples = value; },
|
||||
function() { return Render.ambientOcclusion.numSamples; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newSlider("Ambient Occlusion Num Spiral Turns", 0.0, 30.0,
|
||||
function (value) { Render.ambientOcclusion.numSpiralTurns = value; },
|
||||
function() { return Render.ambientOcclusion.numSpiralTurns; },
|
||||
function (value) { return (value); });
|
||||
|
||||
panel.newCheckbox("Ambient Occlusion Dithering",
|
||||
function (value) { Render.ambientOcclusion.ditheringEnabled = value; },
|
||||
function() { return Render.ambientOcclusion.ditheringEnabled; },
|
||||
function (value) { return (value); });
|
||||
|
||||
var tickTackPeriod = 500;
|
||||
|
||||
function updateCounters() {
|
||||
|
|
|
@ -177,11 +177,35 @@ void AmbientOcclusionEffect::setLevel(float level) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void AmbientOcclusionEffect::setDithering(bool enabled) {
|
||||
if (enabled != isDitheringEnabled()) {
|
||||
auto& current = _parametersBuffer.edit<Parameters>()._performanceCaps;
|
||||
current.x = (float)enabled;
|
||||
auto& current = _parametersBuffer.edit<Parameters>()._sampleInfo;
|
||||
current.w = (float)enabled;
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::setNumSamples(int numSamples) {
|
||||
numSamples = std::max(1.f, (float) numSamples);
|
||||
if (numSamples != getNumSamples()) {
|
||||
auto& current = _parametersBuffer.edit<Parameters>()._sampleInfo;
|
||||
current.x = numSamples;
|
||||
current.y = 1.0 / numSamples;
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::setNumSpiralTurns(float numTurns) {
|
||||
numTurns = std::max(0.f, (float)numTurns);
|
||||
if (numTurns != getNumSpiralTurns()) {
|
||||
auto& current = _parametersBuffer.edit<Parameters>()._sampleInfo;
|
||||
current.z = numTurns;
|
||||
}
|
||||
}
|
||||
|
||||
void AmbientOcclusionEffect::setEdgeSharpness(float sharpness) {
|
||||
sharpness = std::max(0.f, (float)sharpness);
|
||||
if (sharpness != getEdgeSharpness()) {
|
||||
auto& current = _parametersBuffer.edit<Parameters>()._blurInfo;
|
||||
current.x = sharpness;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,6 +338,8 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
|
|||
setDepthInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip());
|
||||
_parametersBuffer.edit<Parameters>()._projection[0] = monoProjMat;
|
||||
_parametersBuffer.edit<Parameters>()._pixelInfo = args->_viewport;
|
||||
_parametersBuffer.edit<Parameters>()._ditheringInfo.y += 0.25f;
|
||||
|
||||
|
||||
auto pyramidPipeline = getPyramidPipeline();
|
||||
auto occlusionPipeline = getOcclusionPipeline();
|
||||
|
|
|
@ -31,8 +31,19 @@ public:
|
|||
float getLevel() const { return _parametersBuffer.get<Parameters>()._radiusInfo.w; }
|
||||
|
||||
void setDithering(bool enabled);
|
||||
bool isDitheringEnabled() const { return _parametersBuffer.get<Parameters>()._performanceCaps.x; }
|
||||
bool isDitheringEnabled() const { return _parametersBuffer.get<Parameters>()._ditheringInfo.w; }
|
||||
|
||||
// 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; }
|
||||
|
||||
using JobModel = render::Task::Job::Model<AmbientOcclusionEffect>;
|
||||
|
||||
|
@ -45,8 +56,12 @@ private:
|
|||
public:
|
||||
// radius info is { R, R^2, 1 / R^6, ObscuranceScale}
|
||||
glm::vec4 _radiusInfo{ 0.5, 0.5 * 0.5, 1.0 / (0.25 * 0.25 * 0.25), 1.0 };
|
||||
// Performance parameters to adjust the effect
|
||||
glm::vec4 _performanceCaps{ 1.0, 1.0, 1.0, 1.0 };
|
||||
// Dithering info
|
||||
glm::vec4 _ditheringInfo{ 1.0, 0.0, 0.0, 0.0 };
|
||||
// Sampling info
|
||||
glm::vec4 _sampleInfo{ 11.0, 1.0/11.0, 7.0, 1.0 };
|
||||
// Blurring info
|
||||
glm::vec4 _blurInfo{ 1.0, 0.0, 0.0, 0.0 };
|
||||
// Pixel info is { viemport width height and stereo on off}
|
||||
glm::vec4 _pixelInfo;
|
||||
// Depth info is { n.f, f - n, -f}
|
||||
|
|
|
@ -183,7 +183,10 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
|
|||
if (_occlusionJobIndex >= 0) {
|
||||
_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>().setEdgeSharpness(renderContext->getAmbientOcclusion().edgeSharpness);
|
||||
}
|
||||
|
||||
setAntialiasingStatus(renderContext->getFxaaStatus());
|
||||
|
|
|
@ -72,7 +72,10 @@ namespace RenderScripting {
|
|||
public:
|
||||
Q_PROPERTY(float radius MEMBER radius)
|
||||
Q_PROPERTY(float level MEMBER level)
|
||||
Q_PROPERTY(int numSamples MEMBER numSamples)
|
||||
Q_PROPERTY(float numSpiralTurns MEMBER numSpiralTurns)
|
||||
Q_PROPERTY(bool ditheringEnabled MEMBER ditheringEnabled)
|
||||
Q_PROPERTY(float edgeSharpness MEMBER edgeSharpness)
|
||||
};
|
||||
using AmbientOcclusionPointer = std::unique_ptr<AmbientOcclusion>;
|
||||
};
|
||||
|
|
|
@ -33,7 +33,9 @@ vec2 unpackOcclusionDepth(vec3 raw) {
|
|||
|
||||
struct AmbientOcclusionParams {
|
||||
vec4 _radiusInfo;
|
||||
vec4 _performanceCaps;
|
||||
vec4 _ditheringInfo;
|
||||
vec4 _sampleInfo;
|
||||
vec4 _blurInfo;
|
||||
vec4 _pixelInfo;
|
||||
vec4 _depthInfo;
|
||||
mat4 _projection[2];
|
||||
|
@ -67,7 +69,25 @@ float getObscuranceScaling() {
|
|||
}
|
||||
|
||||
float isDitheringEnabled() {
|
||||
return params._performanceCaps.x;
|
||||
return params._ditheringInfo.x;
|
||||
}
|
||||
float getFrameDithering() {
|
||||
return params._ditheringInfo.y;
|
||||
}
|
||||
|
||||
|
||||
float getNumSamples() {
|
||||
return params._sampleInfo.x;
|
||||
}
|
||||
float getInvNumSamples() {
|
||||
return params._sampleInfo.y;
|
||||
}
|
||||
float getNumSpiralTurns() {
|
||||
return params._sampleInfo.z;
|
||||
}
|
||||
|
||||
float getBlurEdgeSharpness() {
|
||||
return params._blurInfo.x;
|
||||
}
|
||||
|
||||
float evalZeyeFromZdb(float depth) {
|
||||
|
@ -92,6 +112,7 @@ vec3 evalEyeNormal(vec3 C) {
|
|||
<@func declareBlurPass(axis)@>
|
||||
|
||||
<$declarePackOcclusionDepth()$>
|
||||
<$declareAmbientOcclusion()$>
|
||||
|
||||
// the source occlusion texture
|
||||
uniform sampler2D occlusionMap;
|
||||
|
@ -108,7 +129,6 @@ vec2 fetchOcclusionDepth(ivec2 coords) {
|
|||
|
||||
const int BLUR_RADIUS = 4;
|
||||
const int RADIUS_SCALE = 2;
|
||||
const float EDGE_SHARPNESS = 1.0;
|
||||
|
||||
const float gaussian[BLUR_RADIUS + 1] =
|
||||
// float[](0.356642, 0.239400, 0.072410, 0.009869);
|
||||
|
@ -139,7 +159,7 @@ vec3 getBlurredOcclusion(vec2 coord) {
|
|||
float weight = 0.3 + gaussian[abs(r)];
|
||||
|
||||
// range domain (the "bilateral" weight). As depth difference increases, decrease weight.
|
||||
weight *= max(0.0, 1.0 - (EDGE_SHARPNESS * 2000.0) * abs(tapOZ.y - key));
|
||||
weight *= max(0.0, 1.0 - (getBlurEdgeSharpness() * 2000.0) * abs(tapOZ.y - key));
|
||||
|
||||
sum += tapOZ.x * weight;
|
||||
totalWeight += weight;
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
<$declareAmbientOcclusion()$>
|
||||
<$declarePackOcclusionDepth()$>
|
||||
|
||||
const int NUM_SAMPLES = 11;
|
||||
const float INV_NUM_SAMPLES = 1.0 / float(NUM_SAMPLES);
|
||||
const int NUM_SPIRAL_TURNS= 7;
|
||||
|
||||
const int LOG_MAX_OFFSET = 3;
|
||||
const int MAX_MIP_LEVEL = 5;
|
||||
|
||||
|
@ -32,10 +30,15 @@ out vec4 outFragColor;
|
|||
|
||||
uniform sampler2D normalMap;
|
||||
|
||||
float getAngleDithering(in ivec2 pixelPos) {
|
||||
// Hash function used in the AlchemyAO paper
|
||||
return isDitheringEnabled() * (3 * pixelPos.x ^ pixelPos.y + pixelPos.x * pixelPos.y) * 10 + getFrameDithering();
|
||||
}
|
||||
|
||||
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
|
||||
// Radius relative to ssR
|
||||
float alpha = float(sampleNumber + 0.5) * INV_NUM_SAMPLES;
|
||||
float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle;
|
||||
float alpha = float(sampleNumber + 0.5) * getInvNumSamples();
|
||||
float angle = alpha * (getNumSpiralTurns() * 6.28) + spinAngle;
|
||||
|
||||
ssR = alpha;
|
||||
return vec2(cos(angle), sin(angle));
|
||||
|
@ -53,8 +56,8 @@ vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) {
|
|||
// We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map.
|
||||
// Manually clamp to the texture size because texelFetch bypasses the texture unit
|
||||
ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), textureSize(pyramidMap, mipLevel) - ivec2(1));
|
||||
// P.z = -texelFetch(pyramidMap, mipP, mipLevel).r;
|
||||
P.z = -texelFetch(pyramidMap, ssP, 0).r;
|
||||
P.z = -texelFetch(pyramidMap, mipP, mipLevel).r;
|
||||
// P.z = -texelFetch(pyramidMap, ssP, 0).r;
|
||||
|
||||
// Offset to pixel center
|
||||
//P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z);
|
||||
|
@ -104,8 +107,7 @@ void main(void) {
|
|||
|
||||
vec3 Cp = evalEyePosition(varTexCoord0);
|
||||
|
||||
// Hash function used in the HPG12 AlchemyAO paper
|
||||
float randomPatternRotationAngle = isDitheringEnabled() * (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10;
|
||||
float randomPatternRotationAngle = getAngleDithering(ssC);
|
||||
|
||||
vec3 Cn = evalEyeNormal(Cp);
|
||||
|
||||
|
@ -114,11 +116,11 @@ void main(void) {
|
|||
float ssDiskRadius = -getProjScale() * getRadius() / Cp.z;
|
||||
|
||||
float sum = 0.0;
|
||||
for (int i = 0; i < NUM_SAMPLES; ++i) {
|
||||
for (int i = 0; i < getNumSamples(); ++i) {
|
||||
sum += sampleAO(ssC, Cp, Cn, ssDiskRadius, i, randomPatternRotationAngle);
|
||||
}
|
||||
|
||||
float A = max(0.0, 1.0 - sum * getObscuranceScaling() * 5.0 * INV_NUM_SAMPLES);
|
||||
float A = max(0.0, 1.0 - sum * getObscuranceScaling() * 5.0 * getInvNumSamples());
|
||||
|
||||
// Bilateral box-filter over a quad for free, respecting depth edges
|
||||
// (the difference that this makes is subtle)
|
||||
|
|
|
@ -76,7 +76,10 @@ public:
|
|||
public:
|
||||
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 edgeSharpness = 1.0f;
|
||||
};
|
||||
|
||||
RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode);
|
||||
|
|
Loading…
Reference in a new issue