diff --git a/examples/utilities/tools/renderEngineDebug.js b/examples/utilities/tools/renderEngineDebug.js index a6a6d1252f..fe5ce1e668 100755 --- a/examples/utilities/tools/renderEngineDebug.js +++ b/examples/utilities/tools/renderEngineDebug.js @@ -52,7 +52,7 @@ var overlaysCounter = new CounterWidget(panel, "Overlays", Render.overlay3D); var resizing = false; var previousMode = Settings.getValue(SETTINGS_KEY, -1); -previousMode = 4; // FIXME: just for debug purpose +previousMode = 1; // FIXME: just for debug purpose Menu.addActionGroup(MENU, ACTIONS, ACTIONS[previousMode + 1]); Render.deferredDebugMode = previousMode; Render.deferredDebugSize = { x: 0.0, y: -1.0, z: 1.0, w: 1.0 }; // Reset to default size @@ -104,6 +104,11 @@ panel.newSlider("Ambient Occlusion Radius", 0.0, 2.0, function() { return Render.ambientOcclusion.radius; }, function (value) { return (value); }); +panel.newSlider("Ambient Occlusion Level", 0.0, 1.0, + function (value) { Render.ambientOcclusion.level = value; }, + function() { return Render.ambientOcclusion.level; }, + function (value) { return (value); }); + var tickTackPeriod = 500; function updateCounters() { diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index eb51fa68ea..732ec71228 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -154,14 +154,27 @@ const gpu::PipelinePointer& AmbientOcclusionEffect::getVBlurPipeline() { } -void AmbientOcclusionEffect::setClipInfo(float nearZ, float farZ) { - _parametersBuffer.edit()._clipInfo = glm::vec4(nearZ*farZ, farZ -nearZ, -farZ, 0.0f); +void AmbientOcclusionEffect::setDepthInfo(float nearZ, float farZ) { + _parametersBuffer.edit()._depthInfo = glm::vec4(nearZ*farZ, farZ -nearZ, -farZ, 0.0f); } void AmbientOcclusionEffect::setRadius(float radius) { radius = std::max(0.01f, radius); - _parametersBuffer.edit()._radius_radius2_InvRadius6_s2 = glm::vec4(radius, radius * radius, 1.0f / pow(radius, 6.0f), 0.0f); + if (radius != getRadius()) { + auto& current = _parametersBuffer.edit()._radiusInfo; + current.x = radius; + current.y = radius * radius; + current.z = 1.0f / pow(radius, 6.0f); + } +} + +void AmbientOcclusionEffect::setLevel(float level) { + level = std::max(0.01f, level); + if (level != getLevel()) { + auto& current = _parametersBuffer.edit()._radiusInfo; + current.w = level; + } } void AmbientOcclusionEffect::updateDeferredTransformBuffer(const render::RenderContextPointer& renderContext) { @@ -290,8 +303,8 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext mat4 monoProjMat; args->_viewFrustum->evalProjectionMatrix(monoProjMat); - setClipInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip()); - _parametersBuffer.edit()._projection = monoProjMat; + setDepthInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip()); + _parametersBuffer.edit()._projection[0] = monoProjMat; _parametersBuffer.edit()._pixelInfo = args->_viewport; auto pyramidPipeline = getPyramidPipeline(); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 4eecfc3fc7..5e03f74e8b 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -25,20 +25,28 @@ public: typedef render::Job::Model JobModel; void setRadius(float radius); - float getRadius() const { return _parametersBuffer.get()._radius_radius2_InvRadius6_s2.x; } + float getRadius() const { return _parametersBuffer.get()._radiusInfo.x; } + + // Obscurance level which intensify or dim down the obscurance effect + void setLevel(float level); + float getLevel() const { return _parametersBuffer.get()._radiusInfo.w; } private: - void setClipInfo(float nearZ, float farZ); + void setDepthInfo(float nearZ, float farZ); // Class describing the uniform buffer with all the parameters common to the AO shaders class Parameters { 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 }; + // Pixel info is { viemport width height and stereo on off} glm::vec4 _pixelInfo; - glm::vec4 _clipInfo; - glm::mat4 _projection; - glm::vec4 _radius_radius2_InvRadius6_s2{ 0.5, 0.5 * 0.5, 1.0 / (0.25 * 0.25 * 0.25), 0.0 }; - + // Depth info is { n.f, f - n, -f} + glm::vec4 _depthInfo; + // Mono proj matrix or Left and Right proj matrix going from Mono Eye space to side clip space + glm::mat4 _projection[2]; + Parameters() {} }; typedef gpu::BufferView UniformBufferView; diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 9614229122..2574f22a8c 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -160,6 +160,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend setOcclusionStatus(renderContext->getOcclusionStatus()); if (_occlusionJobIndex >= 0) { _jobs[_occlusionJobIndex].edit().setRadius(renderContext->getAmbientOcclusion().radius); + _jobs[_occlusionJobIndex].edit().setLevel(renderContext->getAmbientOcclusion().level); } setAntialiasingStatus(renderContext->getFxaaStatus()); diff --git a/libraries/render-utils/src/RenderScriptingInterface.h b/libraries/render-utils/src/RenderScriptingInterface.h index b330c23fc9..19d50ce1db 100644 --- a/libraries/render-utils/src/RenderScriptingInterface.h +++ b/libraries/render-utils/src/RenderScriptingInterface.h @@ -71,6 +71,7 @@ namespace RenderScripting { public: Q_PROPERTY(float radius MEMBER radius) + Q_PROPERTY(float level MEMBER level) }; using AmbientOcclusionPointer = std::unique_ptr; }; diff --git a/libraries/render-utils/src/ssao.slh b/libraries/render-utils/src/ssao.slh index 93b702b506..5bac9c6335 100644 --- a/libraries/render-utils/src/ssao.slh +++ b/libraries/render-utils/src/ssao.slh @@ -32,10 +32,10 @@ vec2 unpackOcclusionDepth(vec3 raw) { <@func declareAmbientOcclusion()@> struct AmbientOcclusionParams { + vec4 _radiusInfo; vec4 _pixelInfo; - vec4 _clipInfo; - mat4 _projection; - vec4 _radius_radius2_InvRadius6_s2; + vec4 _depthInfo; + mat4 _projection[2]; }; uniform ambientOcclusionParamsBuffer { @@ -46,28 +46,34 @@ vec2 getWidthHeight() { return params._pixelInfo.zw; } float getProjScale() { - return getWidthHeight().y * params._projection[1][1] * 0.5; + return getWidthHeight().y * params._projection[0][1][1] * 0.5; +} +mat4 getProjection(int side) { + return params._projection[side]; } float getRadius() { - return params._radius_radius2_InvRadius6_s2.x; + return params._radiusInfo.x; } float getRadius2() { - return params._radius_radius2_InvRadius6_s2.y; + return params._radiusInfo.y; } float getInvRadius6() { - return params._radius_radius2_InvRadius6_s2.z; + return params._radiusInfo.z; +} +float getObscuranceScaling() { + return params._radiusInfo.z * params._radiusInfo.w; } float evalZeyeFromZdb(float depth) { - return params._clipInfo.x / (depth * params._clipInfo.y + params._clipInfo.z); + return params._depthInfo.x / (depth * params._depthInfo.y + params._depthInfo.z); } vec3 evalEyePositionFromZeye(float Zeye, vec2 texcoord) { // compute the view space position using the depth // basically manually pick the proj matrix components to do the inverse - float Xe = (-Zeye * (texcoord.x * 2.0 - 1.0) - Zeye * params._projection[2][0] - params._projection[3][0]) / params._projection[0][0]; - float Ye = (-Zeye * (texcoord.y * 2.0 - 1.0) - Zeye * params._projection[2][1] - params._projection[3][1]) / params._projection[1][1]; + float Xe = (-Zeye * (texcoord.x * 2.0 - 1.0) - Zeye * params._projection[0][2][0] - params._projection[0][3][0]) / params._projection[0][0][0]; + float Ye = (-Zeye * (texcoord.y * 2.0 - 1.0) - Zeye * params._projection[0][2][1] - params._projection[0][3][1]) / params._projection[0][1][1]; return vec3(Xe, Ye, Zeye); } @@ -96,15 +102,14 @@ vec2 fetchOcclusionDepth(ivec2 coords) { const int BLUR_RADIUS = 4; -const int RADIUS_SCALE = 2; +const int RADIUS_SCALE = 3; const float EDGE_SHARPNESS = 1.0; const float gaussian[BLUR_RADIUS + 1] = -// float[](0.356642, 0.239400, 0.072410, 0.009869); // R = 2 -// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // R = 3 -float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // R = 4 -// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // R = 5.0 - +// float[](0.356642, 0.239400, 0.072410, 0.009869); +// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 +float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 vec3 getBlurredOcclusion(vec2 coord) { ivec2 ssC = ivec2(coord); diff --git a/libraries/render-utils/src/ssao_makeOcclusion.slf b/libraries/render-utils/src/ssao_makeOcclusion.slf index 3193bd05d4..6b5b768a28 100644 --- a/libraries/render-utils/src/ssao_makeOcclusion.slf +++ b/libraries/render-utils/src/ssao_makeOcclusion.slf @@ -85,15 +85,8 @@ float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in i // return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] - float f = max(radius2 - vv, 0.0); return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); - - // C: Medium contrast (which looks better at high radii), no division. Note that the - // contribution still falls off with radius^2, but we've adjusted the rate in a way that is - // more computationally efficient and happens to be aesthetically pleasing. - // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); - - // D: Low contrast, no division operation - // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); + float f = max(radius2 - vv, 0.0); + return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); } vec3 debugValue(float f, float scale) { @@ -125,16 +118,16 @@ void main(void) { sum += sampleAO(ssC, Cp, Cn, ssDiskRadius, i, randomPatternRotationAngle); } - float A = max(0.0, 1.0 - sum * getInvRadius6() * 5.0 * INV_NUM_SAMPLES); + float A = max(0.0, 1.0 - sum * getObscuranceScaling() * 5.0 * INV_NUM_SAMPLES); // Bilateral box-filter over a quad for free, respecting depth edges // (the difference that this makes is subtle) - /*if (abs(dFdx(Cp.z)) < 0.02) { + if (abs(dFdx(Cp.z)) < 0.02) { A -= dFdx(A) * ((ssC.x & 1) - 0.5); } if (abs(dFdy(Cp.z)) < 0.02) { A -= dFdy(A) * ((ssC.y & 1) - 0.5); - }*/ + } outFragColor = vec4(packOcclusionDepth(A, CSZToDephtKey(Cp.z)), 1.0); //outFragColor = vec4(0.5 * (Cn + vec3(1.0)), A); diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 277d66ce35..bf77081502 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -79,7 +79,8 @@ public: class AmbientOcclusion { public: - float radius = 0.5; // radius in meters of the AO effect + float radius = 0.5f; // radius in meters of the AO effect + float level = 0.5f; // Level of the obscrance value }; RenderContext(ItemsConfig items, Tone tone, AmbientOcclusion ao, int drawStatus, bool drawHitEffect, glm::vec4 deferredDebugSize, int deferredDebugMode);