From 59a758b5ecdb9c71841b6de34585c89d2bee5dde Mon Sep 17 00:00:00 2001 From: Raffi Bedikian Date: Sun, 30 Aug 2015 20:38:05 -0700 Subject: [PATCH 1/6] Add AA state to RenderContext and Menu --- interface/src/Application.cpp | 1 + interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + libraries/render/src/render/Engine.h | 1 + 4 files changed, 4 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c227e5e1c9..88ebf25da8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3542,6 +3542,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect(); renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion); + renderContext._fxaaStatus = Menu::getInstance()->isOptionChecked(MenuOption::Antialiasing); renderArgs->_shouldRender = LODManager::shouldRender; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 4696463181..a93f5e0425 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -317,6 +317,7 @@ Menu::Menu() { 0, // QML Qt::SHIFT | Qt::Key_A, true); addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::DebugAmbientOcclusion); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Antialiasing); MenuWrapper* ambientLightMenu = renderOptionsMenu->addMenu(MenuOption::RenderAmbientLight); QActionGroup* ambientLightGroup = new QActionGroup(ambientLightMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 94e49abcc7..12aee08994 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -134,6 +134,7 @@ namespace MenuOption { const QString AlignForearmsWithWrists = "Align Forearms with Wrists"; const QString AlternateIK = "Alternate IK"; const QString Animations = "Animations..."; + const QString Antialiasing = "Antialiasing"; const QString Atmosphere = "Atmosphere"; const QString Attachments = "Attachments..."; const QString AudioNoiseReduction = "Audio Noise Reduction"; diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 8d096c5e15..5da7956b22 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -53,6 +53,7 @@ public: bool _drawHitEffect = false; bool _occlusionStatus = false; + bool _fxaaStatus = false; RenderContext() {} }; From 1001cf9000178e2117bf5372db47054c002f0f7b Mon Sep 17 00:00:00 2001 From: Raffi Bedikian Date: Sun, 30 Aug 2015 20:48:06 -0700 Subject: [PATCH 2/6] Add shader files for FXAA --- libraries/render-utils/src/fxaa.slf | 77 +++++++++++++++++++++++ libraries/render-utils/src/fxaa.slv | 26 ++++++++ libraries/render-utils/src/fxaa_blend.slf | 24 +++++++ 3 files changed, 127 insertions(+) create mode 100644 libraries/render-utils/src/fxaa.slf create mode 100644 libraries/render-utils/src/fxaa.slv create mode 100644 libraries/render-utils/src/fxaa_blend.slf diff --git a/libraries/render-utils/src/fxaa.slf b/libraries/render-utils/src/fxaa.slf new file mode 100644 index 0000000000..1f10756ce6 --- /dev/null +++ b/libraries/render-utils/src/fxaa.slf @@ -0,0 +1,77 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// fxaa.frag +// fragment shader +// +// Created by Raffi Bedikian on 8/30/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// FXAA shader, GLSL code adapted from: +// http://horde3d.org/wiki/index.php5?title=Shading_Technique_-_FXAA +// Whitepaper describing the technique: +// http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf + +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +uniform sampler2D colorTexture; +uniform vec2 texcoordOffset; + +in vec2 varTexcoord; +out vec4 outFragColor; + +void main() { + float FXAA_SPAN_MAX = 8.0; + float FXAA_REDUCE_MUL = 1.0/8.0; + float FXAA_REDUCE_MIN = (1.0/128.0); + + vec3 rgbNW = texture2D(colorTexture, varTexcoord + (vec2(-1.0, -1.0) * texcoordOffset)).xyz; + vec3 rgbNE = texture2D(colorTexture, varTexcoord + (vec2(+1.0, -1.0) * texcoordOffset)).xyz; + vec3 rgbSW = texture2D(colorTexture, varTexcoord + (vec2(-1.0, +1.0) * texcoordOffset)).xyz; + vec3 rgbSE = texture2D(colorTexture, varTexcoord + (vec2(+1.0, +1.0) * texcoordOffset)).xyz; + vec3 rgbM = texture2D(colorTexture, varTexcoord).xyz; + + vec3 luma = vec3(0.299, 0.587, 0.114); + float lumaNW = dot(rgbNW, luma); + float lumaNE = dot(rgbNE, luma); + float lumaSW = dot(rgbSW, luma); + float lumaSE = dot(rgbSE, luma); + float lumaM = dot( rgbM, luma); + + float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); + float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + + vec2 dir; + dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); + dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); + + float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); + + float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + + dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), + max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texcoordOffset; + + vec3 rgbA = (1.0/2.0) * ( + texture2D(colorTexture, varTexcoord + dir * (1.0/3.0 - 0.5)).xyz + + texture2D(colorTexture, varTexcoord + dir * (2.0/3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( + texture2D(colorTexture, varTexcoord + dir * (0.0/3.0 - 0.5)).xyz + + texture2D(colorTexture, varTexcoord + dir * (3.0/3.0 - 0.5)).xyz); + float lumaB = dot(rgbB, luma); + + if (lumaB < lumaMin || lumaB > lumaMax) { + outFragColor.xyz=rgbA; + } else { + outFragColor.xyz=rgbB; + } + outFragColor.a = 1.0; +} diff --git a/libraries/render-utils/src/fxaa.slv b/libraries/render-utils/src/fxaa.slv new file mode 100644 index 0000000000..35a96ceb24 --- /dev/null +++ b/libraries/render-utils/src/fxaa.slv @@ -0,0 +1,26 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// fxaa.vert +// vertex shader +// +// Created by Raffi Bedikian on 8/30/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include gpu/Inputs.slh@> + +<@include gpu/Transform.slh@> + +<$declareStandardTransform()$> + +out vec2 varTexcoord; + +void main(void) { + varTexcoord = inTexCoord0.xy; + gl_Position = inPosition; +} diff --git a/libraries/render-utils/src/fxaa_blend.slf b/libraries/render-utils/src/fxaa_blend.slf new file mode 100644 index 0000000000..d5819cc9a6 --- /dev/null +++ b/libraries/render-utils/src/fxaa_blend.slf @@ -0,0 +1,24 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// fxaa_blend.frag +// fragment shader +// +// Created by Raffi Bedikian on 8/30/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include DeferredBufferWrite.slh@> + +in vec2 varTexcoord; +out vec4 outFragColor; + +uniform sampler2D colorTexture; + +void main(void) { + outFragColor = texture(colorTexture, varTexcoord); +} From ff2a58b3eb622e3b6d84c4e1513b87e1e696dade Mon Sep 17 00:00:00 2001 From: Raffi Bedikian Date: Sun, 30 Aug 2015 20:49:03 -0700 Subject: [PATCH 3/6] Add FXAA effect class, modeled after AO effect --- .../render-utils/src/AntialiasingEffect.cpp | 151 ++++++++++++++++++ .../render-utils/src/AntialiasingEffect.h | 44 +++++ .../render-utils/src/RenderDeferredTask.cpp | 8 + .../render-utils/src/RenderDeferredTask.h | 5 + 4 files changed, 208 insertions(+) create mode 100644 libraries/render-utils/src/AntialiasingEffect.cpp create mode 100644 libraries/render-utils/src/AntialiasingEffect.h diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp new file mode 100644 index 0000000000..4e1b6f451c --- /dev/null +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -0,0 +1,151 @@ +// +// AntialiasingEffect.cpp +// libraries/render-utils/src/ +// +// Created by Raffi Bedikian on 8/30/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + + +#include + +#include +#include +#include + +#include "gpu/StandardShaderLib.h" +#include "AntialiasingEffect.h" +#include "TextureCache.h" +#include "FramebufferCache.h" +#include "DependencyManager.h" +#include "ViewFrustum.h" +#include "GeometryCache.h" + +#include "fxaa_vert.h" +#include "fxaa_frag.h" +#include "fxaa_blend_frag.h" + + +Antialiasing::Antialiasing() { +} + +const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { + if (!_antialiasingPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(fxaa_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fxaa_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 0)); + + gpu::Shader::makeProgram(*program, slotBindings); + + _texcoordOffsetLoc = program->getUniforms().findLocation("texcoordOffset"); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Link the antialiasing FBO to texture + _antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _antialiasingBuffer->getWidth(); + auto height = _antialiasingBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _antialiasingTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + + // Good to go add the brand new pipeline + _antialiasingPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _antialiasingPipeline; +} + +const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { + if (!_blendPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(fxaa_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fxaa_blend_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 0)); + + gpu::Shader::makeProgram(*program, slotBindings); + + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + state->setDepthTest(false, false, gpu::LESS_EQUAL); + + // Good to go add the brand new pipeline + _blendPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _blendPipeline; +} + +void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + gpu::Batch batch; + RenderArgs* args = renderContext->args; + + auto framebufferCache = DependencyManager::get(); + QSize framebufferSize = framebufferCache->getFrameBufferSize(); + float fbWidth = framebufferSize.width(); + float fbHeight = framebufferSize.height(); + float sMin = args->_viewport.x / fbWidth; + float sWidth = args->_viewport.z / fbWidth; + float tMin = args->_viewport.y / fbHeight; + float tHeight = args->_viewport.w / fbHeight; + + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); + + // FXAA step + getAntialiasingPipeline(); + batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); + _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); + batch.setFramebuffer(_antialiasingBuffer); + batch.setPipeline(getAntialiasingPipeline()); + + // initialize the view-space unpacking uniforms using frustum data + float left, right, bottom, top, nearVal, farVal; + glm::vec4 nearClipPlane, farClipPlane; + + args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + + float depthScale = (farVal - nearVal) / farVal; + float nearScale = -1.0f / nearVal; + float depthTexCoordScaleS = (right - left) * nearScale / sWidth; + float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight; + float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS; + float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT; + + batch._glUniform2f(_texcoordOffsetLoc, 1.0 / fbWidth, 1.0 / fbHeight); + + glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); + glm::vec2 bottomLeft(-1.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); + glm::vec2 texCoordTopLeft(0.0f, 0.0f); + glm::vec2 texCoordBottomRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // Blend step + getBlendPipeline(); + batch.setResourceTexture(0, _antialiasingTexture); + batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); + batch.setPipeline(getBlendPipeline()); + + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + + // Ready to render + args->_context->render((batch)); +} diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h new file mode 100644 index 0000000000..96cf3aaf3e --- /dev/null +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -0,0 +1,44 @@ +// +// AntialiasingEffect.h +// libraries/render-utils/src/ +// +// Created by Raffi Bedikian on 8/30/15 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AntialiasingEffect_h +#define hifi_AntialiasingEffect_h + +#include + +#include "render/DrawTask.h" + +class Antialiasing { +public: + + Antialiasing(); + + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + typedef render::Job::Model JobModel; + + const gpu::PipelinePointer& getAntialiasingPipeline(); + const gpu::PipelinePointer& getBlendPipeline(); + +private: + + // Uniforms for AA + gpu::int32 _texcoordOffsetLoc; + + gpu::FramebufferPointer _antialiasingBuffer; + + gpu::TexturePointer _antialiasingTexture; + + gpu::PipelinePointer _antialiasingPipeline; + gpu::PipelinePointer _blendPipeline; + +}; + +#endif // hifi_AntialiasingEffect_h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index ca3f87f53f..137294c5b6 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -23,6 +23,7 @@ #include "render/DrawStatus.h" #include "AmbientOcclusionEffect.h" +#include "AntialiasingEffect.h" #include "overlay3D_vert.h" #include "overlay3D_frag.h" @@ -88,6 +89,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() { _jobs.back().setEnabled(false); _occlusionJobIndex = _jobs.size() - 1; + _jobs.push_back(Job(new Antialiasing::JobModel("Antialiasing"))); + + _jobs.back().setEnabled(false); + _antialiasingJobIndex = _jobs.size() - 1; + _jobs.push_back(Job(new FetchItems::JobModel("FetchTransparent", FetchItems( ItemFilter::Builder::transparentShape().withoutLayered(), @@ -146,6 +152,8 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend // TODO: turn on/off AO through menu item setOcclusionStatus(renderContext->_occlusionStatus); + setAntialiasingStatus(renderContext->_fxaaStatus); + renderContext->args->_context->syncCache(); for (auto job : _jobs) { diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 0041f5d9aa..8366a2665d 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -91,6 +91,11 @@ public: void setOcclusionStatus(bool draw) { if (_occlusionJobIndex >= 0) { _jobs[_occlusionJobIndex].setEnabled(draw); } } bool doOcclusionStatus() const { if (_occlusionJobIndex >= 0) { return _jobs[_occlusionJobIndex].isEnabled(); } else { return false; } } + int _antialiasingJobIndex = -1; + + void setAntialiasingStatus(bool draw) { if (_antialiasingJobIndex >= 0) { _jobs[_antialiasingJobIndex].setEnabled(draw); } } + bool doAntialiasingStatus() const { if (_antialiasingJobIndex >= 0) { return _jobs[_antialiasingJobIndex].isEnabled(); } else { return false; } } + virtual void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); From 9318661bc38ac18cf6c8d76d411a2c25cf302d5c Mon Sep 17 00:00:00 2001 From: Raffi Bedikian Date: Tue, 1 Sep 2015 23:54:48 -0700 Subject: [PATCH 4/6] Add algorithm comments to FXAA shader --- libraries/render-utils/src/fxaa.slf | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/fxaa.slf b/libraries/render-utils/src/fxaa.slf index 1f10756ce6..69596e13ce 100644 --- a/libraries/render-utils/src/fxaa.slf +++ b/libraries/render-utils/src/fxaa.slf @@ -29,16 +29,28 @@ in vec2 varTexcoord; out vec4 outFragColor; void main() { + // filter width limit for dependent "two-tap" texture samples float FXAA_SPAN_MAX = 8.0; - float FXAA_REDUCE_MUL = 1.0/8.0; - float FXAA_REDUCE_MIN = (1.0/128.0); + // local contrast multiplier for performing AA + // higher = sharper, but setting this value too high will cause near-vertical and near-horizontal edges to fail + // see "fxaaQualityEdgeThreshold" + float FXAA_REDUCE_MUL = 1.0/8.0; + + // luminance threshold for processing dark colors + // see "fxaaQualityEdgeThresholdMin" + float FXAA_REDUCE_MIN = (1.0/128.0); + + // fetch raw RGB values for nearby locations + // sampling pattern is "five on a die" (each diagonal direction and the center) + // computing the coordinates for these texture reads could be moved to the vertex shader for speed if needed vec3 rgbNW = texture2D(colorTexture, varTexcoord + (vec2(-1.0, -1.0) * texcoordOffset)).xyz; vec3 rgbNE = texture2D(colorTexture, varTexcoord + (vec2(+1.0, -1.0) * texcoordOffset)).xyz; vec3 rgbSW = texture2D(colorTexture, varTexcoord + (vec2(-1.0, +1.0) * texcoordOffset)).xyz; vec3 rgbSE = texture2D(colorTexture, varTexcoord + (vec2(+1.0, +1.0) * texcoordOffset)).xyz; vec3 rgbM = texture2D(colorTexture, varTexcoord).xyz; + // convert RGB values to luminance vec3 luma = vec3(0.299, 0.587, 0.114); float lumaNW = dot(rgbNW, luma); float lumaNE = dot(rgbNE, luma); @@ -46,20 +58,23 @@ void main() { float lumaSE = dot(rgbSE, luma); float lumaM = dot( rgbM, luma); + // luma range of local neighborhood float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); + // direction perpendicular to local luma gradient vec2 dir; dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); - + + // compute clamped direction offset for additional "two-tap" samples + // longer vector = blurry, shorter vector = sharp float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); - dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texcoordOffset; + // perform additional texture sampling perpendicular to gradient vec3 rgbA = (1.0/2.0) * ( texture2D(colorTexture, varTexcoord + dir * (1.0/3.0 - 0.5)).xyz + texture2D(colorTexture, varTexcoord + dir * (2.0/3.0 - 0.5)).xyz); @@ -68,6 +83,8 @@ void main() { texture2D(colorTexture, varTexcoord + dir * (3.0/3.0 - 0.5)).xyz); float lumaB = dot(rgbB, luma); + // compare luma of new samples to the luma range of the original neighborhood + // if the new samples exceed this range, just use the first two samples instead of all four if (lumaB < lumaMin || lumaB > lumaMax) { outFragColor.xyz=rgbA; } else { From 2d95d1c236f5d2dc00a2811ccc2b052ba6b67e76 Mon Sep 17 00:00:00 2001 From: Raffi Bedikian Date: Wed, 2 Sep 2015 13:49:21 -0700 Subject: [PATCH 5/6] Fix various whitespace issues --- .../render-utils/src/AntialiasingEffect.cpp | 170 +++++++++--------- .../render-utils/src/AntialiasingEffect.h | 22 +-- libraries/render-utils/src/fxaa.slf | 18 +- 3 files changed, 105 insertions(+), 105 deletions(-) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 4e1b6f451c..283561fc57 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -33,119 +33,119 @@ Antialiasing::Antialiasing() { } const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { - if (!_antialiasingPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(fxaa_vert))); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fxaa_frag))); - gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + if (!_antialiasingPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(fxaa_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fxaa_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 0)); + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 0)); - gpu::Shader::makeProgram(*program, slotBindings); + gpu::Shader::makeProgram(*program, slotBindings); - _texcoordOffsetLoc = program->getUniforms().findLocation("texcoordOffset"); + _texcoordOffsetLoc = program->getUniforms().findLocation("texcoordOffset"); - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(false, false, gpu::LESS_EQUAL); + state->setDepthTest(false, false, gpu::LESS_EQUAL); - // Link the antialiasing FBO to texture - _antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, - DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); - auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); - auto width = _antialiasingBuffer->getWidth(); - auto height = _antialiasingBuffer->getHeight(); - auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); - _antialiasingTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); + // Link the antialiasing FBO to texture + _antialiasingBuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_RGBA_32, + DependencyManager::get()->getFrameBufferSize().width(), DependencyManager::get()->getFrameBufferSize().height())); + auto format = gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA); + auto width = _antialiasingBuffer->getWidth(); + auto height = _antialiasingBuffer->getHeight(); + auto defaultSampler = gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT); + _antialiasingTexture = gpu::TexturePointer(gpu::Texture::create2D(format, width, height, defaultSampler)); - // Good to go add the brand new pipeline - _antialiasingPipeline.reset(gpu::Pipeline::create(program, state)); - } - return _antialiasingPipeline; + // Good to go add the brand new pipeline + _antialiasingPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _antialiasingPipeline; } const gpu::PipelinePointer& Antialiasing::getBlendPipeline() { - if (!_blendPipeline) { - auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(fxaa_vert))); - auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fxaa_blend_frag))); - gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); + if (!_blendPipeline) { + auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(fxaa_vert))); + auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(fxaa_blend_frag))); + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 0)); + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("colorTexture"), 0)); - gpu::Shader::makeProgram(*program, slotBindings); + gpu::Shader::makeProgram(*program, slotBindings); - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(false, false, gpu::LESS_EQUAL); + state->setDepthTest(false, false, gpu::LESS_EQUAL); - // Good to go add the brand new pipeline - _blendPipeline.reset(gpu::Pipeline::create(program, state)); - } - return _blendPipeline; + // Good to go add the brand new pipeline + _blendPipeline.reset(gpu::Pipeline::create(program, state)); + } + return _blendPipeline; } void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); - gpu::Batch batch; - RenderArgs* args = renderContext->args; + gpu::Batch batch; + RenderArgs* args = renderContext->args; - auto framebufferCache = DependencyManager::get(); - QSize framebufferSize = framebufferCache->getFrameBufferSize(); - float fbWidth = framebufferSize.width(); - float fbHeight = framebufferSize.height(); - float sMin = args->_viewport.x / fbWidth; - float sWidth = args->_viewport.z / fbWidth; - float tMin = args->_viewport.y / fbHeight; - float tHeight = args->_viewport.w / fbHeight; + auto framebufferCache = DependencyManager::get(); + QSize framebufferSize = framebufferCache->getFrameBufferSize(); + float fbWidth = framebufferSize.width(); + float fbHeight = framebufferSize.height(); + float sMin = args->_viewport.x / fbWidth; + float sWidth = args->_viewport.z / fbWidth; + float tMin = args->_viewport.y / fbHeight; + float tHeight = args->_viewport.w / fbHeight; - glm::mat4 projMat; - Transform viewMat; - args->_viewFrustum->evalProjectionMatrix(projMat); - args->_viewFrustum->evalViewTransform(viewMat); - batch.setProjectionTransform(projMat); - batch.setViewTransform(viewMat); - batch.setModelTransform(Transform()); + glm::mat4 projMat; + Transform viewMat; + args->_viewFrustum->evalProjectionMatrix(projMat); + args->_viewFrustum->evalViewTransform(viewMat); + batch.setProjectionTransform(projMat); + batch.setViewTransform(viewMat); + batch.setModelTransform(Transform()); - // FXAA step - getAntialiasingPipeline(); - batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); - _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); - batch.setFramebuffer(_antialiasingBuffer); - batch.setPipeline(getAntialiasingPipeline()); + // FXAA step + getAntialiasingPipeline(); + batch.setResourceTexture(0, framebufferCache->getPrimaryColorTexture()); + _antialiasingBuffer->setRenderBuffer(0, _antialiasingTexture); + batch.setFramebuffer(_antialiasingBuffer); + batch.setPipeline(getAntialiasingPipeline()); - // initialize the view-space unpacking uniforms using frustum data - float left, right, bottom, top, nearVal, farVal; - glm::vec4 nearClipPlane, farClipPlane; + // initialize the view-space unpacking uniforms using frustum data + float left, right, bottom, top, nearVal, farVal; + glm::vec4 nearClipPlane, farClipPlane; - args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - float depthScale = (farVal - nearVal) / farVal; - float nearScale = -1.0f / nearVal; - float depthTexCoordScaleS = (right - left) * nearScale / sWidth; - float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight; - float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS; - float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT; + float depthScale = (farVal - nearVal) / farVal; + float nearScale = -1.0f / nearVal; + float depthTexCoordScaleS = (right - left) * nearScale / sWidth; + float depthTexCoordScaleT = (top - bottom) * nearScale / tHeight; + float depthTexCoordOffsetS = left * nearScale - sMin * depthTexCoordScaleS; + float depthTexCoordOffsetT = bottom * nearScale - tMin * depthTexCoordScaleT; - batch._glUniform2f(_texcoordOffsetLoc, 1.0 / fbWidth, 1.0 / fbHeight); + batch._glUniform2f(_texcoordOffsetLoc, 1.0 / fbWidth, 1.0 / fbHeight); - glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); - glm::vec2 bottomLeft(-1.0f, -1.0f); - glm::vec2 topRight(1.0f, 1.0f); - glm::vec2 texCoordTopLeft(0.0f, 0.0f); - glm::vec2 texCoordBottomRight(1.0f, 1.0f); - DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f); + glm::vec2 bottomLeft(-1.0f, -1.0f); + glm::vec2 topRight(1.0f, 1.0f); + glm::vec2 texCoordTopLeft(0.0f, 0.0f); + glm::vec2 texCoordBottomRight(1.0f, 1.0f); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); - // Blend step - getBlendPipeline(); - batch.setResourceTexture(0, _antialiasingTexture); - batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); - batch.setPipeline(getBlendPipeline()); + // Blend step + getBlendPipeline(); + batch.setResourceTexture(0, _antialiasingTexture); + batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer()); + batch.setPipeline(getBlendPipeline()); - DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); + DependencyManager::get()->renderQuad(batch, bottomLeft, topRight, texCoordTopLeft, texCoordBottomRight, color); - // Ready to render - args->_context->render((batch)); + // Ready to render + args->_context->render((batch)); } diff --git a/libraries/render-utils/src/AntialiasingEffect.h b/libraries/render-utils/src/AntialiasingEffect.h index 96cf3aaf3e..c7cce4cb15 100644 --- a/libraries/render-utils/src/AntialiasingEffect.h +++ b/libraries/render-utils/src/AntialiasingEffect.h @@ -19,25 +19,25 @@ class Antialiasing { public: - Antialiasing(); + Antialiasing(); - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); - typedef render::Job::Model JobModel; + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + typedef render::Job::Model JobModel; - const gpu::PipelinePointer& getAntialiasingPipeline(); - const gpu::PipelinePointer& getBlendPipeline(); + const gpu::PipelinePointer& getAntialiasingPipeline(); + const gpu::PipelinePointer& getBlendPipeline(); private: - // Uniforms for AA - gpu::int32 _texcoordOffsetLoc; + // Uniforms for AA + gpu::int32 _texcoordOffsetLoc; - gpu::FramebufferPointer _antialiasingBuffer; + gpu::FramebufferPointer _antialiasingBuffer; - gpu::TexturePointer _antialiasingTexture; + gpu::TexturePointer _antialiasingTexture; - gpu::PipelinePointer _antialiasingPipeline; - gpu::PipelinePointer _blendPipeline; + gpu::PipelinePointer _antialiasingPipeline; + gpu::PipelinePointer _blendPipeline; }; diff --git a/libraries/render-utils/src/fxaa.slf b/libraries/render-utils/src/fxaa.slf index 69596e13ce..d1c50b2c58 100644 --- a/libraries/render-utils/src/fxaa.slf +++ b/libraries/render-utils/src/fxaa.slf @@ -35,11 +35,11 @@ void main() { // local contrast multiplier for performing AA // higher = sharper, but setting this value too high will cause near-vertical and near-horizontal edges to fail // see "fxaaQualityEdgeThreshold" - float FXAA_REDUCE_MUL = 1.0/8.0; + float FXAA_REDUCE_MUL = 1.0 / 8.0; // luminance threshold for processing dark colors // see "fxaaQualityEdgeThresholdMin" - float FXAA_REDUCE_MIN = (1.0/128.0); + float FXAA_REDUCE_MIN = 1.0 / 128.0; // fetch raw RGB values for nearby locations // sampling pattern is "five on a die" (each diagonal direction and the center) @@ -70,17 +70,17 @@ void main() { // compute clamped direction offset for additional "two-tap" samples // longer vector = blurry, shorter vector = sharp float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); - float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce); + float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * texcoordOffset; // perform additional texture sampling perpendicular to gradient - vec3 rgbA = (1.0/2.0) * ( - texture2D(colorTexture, varTexcoord + dir * (1.0/3.0 - 0.5)).xyz + - texture2D(colorTexture, varTexcoord + dir * (2.0/3.0 - 0.5)).xyz); - vec3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * ( - texture2D(colorTexture, varTexcoord + dir * (0.0/3.0 - 0.5)).xyz + - texture2D(colorTexture, varTexcoord + dir * (3.0/3.0 - 0.5)).xyz); + vec3 rgbA = (1.0 / 2.0) * ( + texture2D(colorTexture, varTexcoord + dir * (1.0 / 3.0 - 0.5)).xyz + + texture2D(colorTexture, varTexcoord + dir * (2.0 / 3.0 - 0.5)).xyz); + vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * ( + texture2D(colorTexture, varTexcoord + dir * (0.0 / 3.0 - 0.5)).xyz + + texture2D(colorTexture, varTexcoord + dir * (3.0 / 3.0 - 0.5)).xyz); float lumaB = dot(rgbB, luma); // compare luma of new samples to the luma range of the original neighborhood From 6b2897ca8fe233b8c725f24105d9c2eba5e34801 Mon Sep 17 00:00:00 2001 From: Raffi Bedikian Date: Thu, 3 Sep 2015 23:11:53 -0700 Subject: [PATCH 6/6] Fix AA bugs with display plugins and mini-mirror --- libraries/render-utils/src/AntialiasingEffect.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libraries/render-utils/src/AntialiasingEffect.cpp b/libraries/render-utils/src/AntialiasingEffect.cpp index 283561fc57..0e362bfb49 100644 --- a/libraries/render-utils/src/AntialiasingEffect.cpp +++ b/libraries/render-utils/src/AntialiasingEffect.cpp @@ -61,6 +61,13 @@ const gpu::PipelinePointer& Antialiasing::getAntialiasingPipeline() { // Good to go add the brand new pipeline _antialiasingPipeline.reset(gpu::Pipeline::create(program, state)); } + + int w = DependencyManager::get()->getFrameBufferSize().width(); + int h = DependencyManager::get()->getFrameBufferSize().height(); + if (w != _antialiasingBuffer->getWidth() || h != _antialiasingBuffer->getHeight()) { + _antialiasingBuffer->resize(w, h); + } + return _antialiasingPipeline; } @@ -89,7 +96,14 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re assert(renderContext->args); assert(renderContext->args->_viewFrustum); + if (renderContext->args->_renderMode == RenderArgs::MIRROR_RENDER_MODE) { + return; + } + gpu::Batch batch; + + batch.enableStereo(false); + RenderArgs* args = renderContext->args; auto framebufferCache = DependencyManager::get();