From 39d68828abe178640deb5f7c95534bd86a89ae7b Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Mon, 30 Jan 2017 11:15:40 -0800 Subject: [PATCH] Disable FXAA on tablet overlay in desktop mode. This introduces the "isAA" property to 3d overlays. When false, the overlay is rendered after the "Antialiasing" render pass. Ironically, disabling FXAA makes the text more readable, which is essential in 2D desktop mode. Two new shaders were introduced. simple_opaque_web_browser_overlay.slf simple_transparent_web_browser_overlay.slf These are tailored to write into the main framebuffer instead of the g-buffer. --- interface/src/ui/overlays/Base3DOverlay.cpp | 16 +++- interface/src/ui/overlays/Base3DOverlay.h | 4 +- interface/src/ui/overlays/Web3DOverlay.cpp | 4 +- interface/src/ui/overlays/Web3DOverlay.h | 2 - .../src/RenderableWebEntityItem.cpp | 5 +- libraries/render-utils/src/GeometryCache.cpp | 75 +++++++++---------- libraries/render-utils/src/GeometryCache.h | 16 ++-- .../src/simple_opaque_web_browser.slf | 2 +- .../src/simple_opaque_web_browser_overlay.slf | 30 ++++++++ .../src/simple_transparent_web_browser.slf | 3 +- ...simple_transparent_web_browser_overlay.slf | 31 ++++++++ scripts/system/libraries/WebTablet.js | 7 +- 12 files changed, 138 insertions(+), 57 deletions(-) create mode 100644 libraries/render-utils/src/simple_opaque_web_browser_overlay.slf create mode 100644 libraries/render-utils/src/simple_transparent_web_browser_overlay.slf diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 8f2149f02d..ff5177ed3a 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -26,7 +26,8 @@ Base3DOverlay::Base3DOverlay() : _isSolid(DEFAULT_IS_SOLID), _isDashedLine(DEFAULT_IS_DASHED_LINE), _ignoreRayIntersection(false), - _drawInFront(false) + _drawInFront(false), + _isAA(true) { } @@ -37,7 +38,8 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : _isSolid(base3DOverlay->_isSolid), _isDashedLine(base3DOverlay->_isDashedLine), _ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection), - _drawInFront(base3DOverlay->_drawInFront) + _drawInFront(base3DOverlay->_drawInFront), + _isAA(base3DOverlay->_isAA) { setTransform(base3DOverlay->getTransform()); } @@ -175,6 +177,13 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { needRenderItemUpdate = true; } + auto isAA = properties["isAA"]; + if (isAA.isValid()) { + bool value = isAA.toBool(); + setIsAA(value); + needRenderItemUpdate = true; + } + // Communicate changes to the renderItem if needed if (needRenderItemUpdate) { auto itemID = getRenderItemID(); @@ -224,6 +233,9 @@ QVariant Base3DOverlay::getProperty(const QString& property) { if (property == "parentJointIndex") { return getParentJointIndex(); } + if (property == "isAA") { + return _isAA; + } return Overlay::getProperty(property); } diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index 487d4eff70..18936df504 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -36,13 +36,14 @@ public: bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; } bool getDrawInFront() const { return _drawInFront; } - virtual bool isAA() const { return true; } + virtual bool isAA() const { return _isAA; } void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } void setIsSolid(bool isSolid) { _isSolid = isSolid; } void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } void setDrawInFront(bool value) { _drawInFront = value; } + void setIsAA(bool value) { _isAA = value; } virtual AABox getBounds() const override = 0; @@ -66,6 +67,7 @@ protected: bool _isDashedLine; bool _ignoreRayIntersection; bool _drawInFront; + bool _isAA; }; #endif // hifi_Base3DOverlay_h diff --git a/interface/src/ui/overlays/Web3DOverlay.cpp b/interface/src/ui/overlays/Web3DOverlay.cpp index bf708c738d..f33ef24c0d 100644 --- a/interface/src/ui/overlays/Web3DOverlay.cpp +++ b/interface/src/ui/overlays/Web3DOverlay.cpp @@ -249,9 +249,9 @@ void Web3DOverlay::render(RenderArgs* args) { batch.setModelTransform(transform); auto geometryCache = DependencyManager::get(); if (color.a < OPAQUE_ALPHA_THRESHOLD) { - geometryCache->bindTransparentWebBrowserProgram(batch); + geometryCache->bindTransparentWebBrowserProgram(batch, _isAA); } else { - geometryCache->bindOpaqueWebBrowserProgram(batch); + geometryCache->bindOpaqueWebBrowserProgram(batch, _isAA); } geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId); batch.setResourceTexture(0, args->_whiteTexture); // restore default white color after me diff --git a/interface/src/ui/overlays/Web3DOverlay.h b/interface/src/ui/overlays/Web3DOverlay.h index 72b923496c..2b9686919d 100644 --- a/interface/src/ui/overlays/Web3DOverlay.h +++ b/interface/src/ui/overlays/Web3DOverlay.h @@ -29,8 +29,6 @@ public: Web3DOverlay(const Web3DOverlay* Web3DOverlay); virtual ~Web3DOverlay(); - virtual bool isAA() const { return false; } - QString pickURL(); void loadSourceURL(); virtual void render(RenderArgs* args) override; diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index e8353a1595..972c23d534 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -241,10 +241,11 @@ void RenderableWebEntityItem::render(RenderArgs* args) { batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); + const bool IS_AA = true; if (fadeRatio < OPAQUE_ALPHA_THRESHOLD) { - DependencyManager::get()->bindTransparentWebBrowserProgram(batch); + DependencyManager::get()->bindTransparentWebBrowserProgram(batch, IS_AA); } else { - DependencyManager::get()->bindOpaqueWebBrowserProgram(batch); + DependencyManager::get()->bindOpaqueWebBrowserProgram(batch, IS_AA); } DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId); } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index a19f1844f0..c277b9be64 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -36,7 +36,9 @@ #include "simple_textured_frag.h" #include "simple_textured_unlit_frag.h" #include "simple_opaque_web_browser_frag.h" +#include "simple_opaque_web_browser_overlay_frag.h" #include "simple_transparent_web_browser_frag.h" +#include "simple_transparent_web_browser_overlay_frag.h" #include "glowLine_vert.h" #include "glowLine_frag.h" @@ -1760,66 +1762,61 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { return a.getRaw() == b.getRaw(); } -void GeometryCache::bindOpaqueWebBrowserProgram(gpu::Batch& batch) { - batch.setPipeline(getOpaqueWebBrowserProgram()); +static void buildWebShader(const std::string& vertShaderText, const std::string& fragShaderText, bool blendEnable, + gpu::ShaderPointer& shaderPointerOut, gpu::PipelinePointer& pipelinePointerOut) { + auto VS = gpu::Shader::createVertex(vertShaderText); + auto PS = gpu::Shader::createPixel(fragShaderText); + + shaderPointerOut = gpu::Shader::createProgram(VS, PS); + + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); + gpu::Shader::makeProgram(*shaderPointerOut, slotBindings); + auto state = std::make_shared(); + state->setCullMode(gpu::State::CULL_NONE); + state->setDepthTest(true, true, gpu::LESS_EQUAL); + state->setBlendFunction(blendEnable, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + + pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state); +} + +void GeometryCache::bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA) { + batch.setPipeline(getOpaqueWebBrowserProgram(isAA)); // Set a default normal map batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, DependencyManager::get()->getNormalFittingTexture()); } -gpu::PipelinePointer GeometryCache::getOpaqueWebBrowserProgram() { +gpu::PipelinePointer GeometryCache::getOpaqueWebBrowserProgram(bool isAA) { static std::once_flag once; std::call_once(once, [&]() { - auto VS = gpu::Shader::createVertex(std::string(simple_vert)); - auto PS = gpu::Shader::createPixel(std::string(simple_opaque_web_browser_frag)); - - _simpleOpaqueWebBrowserShader = gpu::Shader::createProgram(VS, PS); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); - gpu::Shader::makeProgram(*_simpleOpaqueWebBrowserShader, slotBindings); - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_NONE); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(false, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - _simpleOpaqueWebBrowserPipeline = gpu::Pipeline::create(_simpleOpaqueWebBrowserShader, state); + const bool BLEND_ENABLE = false; + buildWebShader(simple_vert, simple_opaque_web_browser_frag, BLEND_ENABLE, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline); + buildWebShader(simple_vert, simple_opaque_web_browser_overlay_frag, BLEND_ENABLE, _simpleOpaqueWebBrowserOverlayShader, _simpleOpaqueWebBrowserOverlayPipeline); }); - return _simpleOpaqueWebBrowserPipeline; + return isAA ? _simpleOpaqueWebBrowserPipeline : _simpleOpaqueWebBrowserOverlayPipeline; } -void GeometryCache::bindTransparentWebBrowserProgram(gpu::Batch& batch) { - batch.setPipeline(getTransparentWebBrowserProgram()); +void GeometryCache::bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA) { + batch.setPipeline(getTransparentWebBrowserProgram(isAA)); // Set a default normal map batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING, DependencyManager::get()->getNormalFittingTexture()); } -gpu::PipelinePointer GeometryCache::getTransparentWebBrowserProgram() { +gpu::PipelinePointer GeometryCache::getTransparentWebBrowserProgram(bool isAA) { static std::once_flag once; std::call_once(once, [&]() { - auto VS = gpu::Shader::createVertex(std::string(simple_vert)); - auto PS = gpu::Shader::createPixel(std::string(simple_transparent_web_browser_frag)); - _simpleTransparentWebBrowserShader = gpu::Shader::createProgram(VS, PS); - - gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); - gpu::Shader::makeProgram(*_simpleTransparentWebBrowserShader, slotBindings); - auto state = std::make_shared(); - state->setCullMode(gpu::State::CULL_NONE); - state->setDepthTest(true, true, gpu::LESS_EQUAL); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - _simpleTransparentWebBrowserPipeline = gpu::Pipeline::create(_simpleTransparentWebBrowserShader, state); + const bool BLEND_ENABLE = true; + buildWebShader(simple_vert, simple_transparent_web_browser_frag, BLEND_ENABLE, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline); + buildWebShader(simple_vert, simple_transparent_web_browser_overlay_frag, BLEND_ENABLE, _simpleTransparentWebBrowserOverlayShader, _simpleTransparentWebBrowserOverlayPipeline); }); - return _simpleTransparentWebBrowserPipeline; + return isAA ? _simpleTransparentWebBrowserPipeline : _simpleTransparentWebBrowserOverlayPipeline; } void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased) { diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 84dfd8ccc3..e0a610a095 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -158,11 +158,11 @@ public: gpu::PipelinePointer getSimplePipeline(bool textured = false, bool transparent = false, bool culled = true, bool unlit = false, bool depthBias = false); - void bindOpaqueWebBrowserProgram(gpu::Batch& batch); - gpu::PipelinePointer getOpaqueWebBrowserProgram(); + void bindOpaqueWebBrowserProgram(gpu::Batch& batch, bool isAA); + gpu::PipelinePointer getOpaqueWebBrowserProgram(bool isAA); - void bindTransparentWebBrowserProgram(gpu::Batch& batch); - gpu::PipelinePointer getTransparentWebBrowserProgram(); + void bindTransparentWebBrowserProgram(gpu::Batch& batch, bool isAA); + gpu::PipelinePointer getTransparentWebBrowserProgram(bool isAA); render::ShapePipelinePointer getOpaqueShapePipeline() { return GeometryCache::_simpleOpaquePipeline; } render::ShapePipelinePointer getTransparentShapePipeline() { return GeometryCache::_simpleTransparentPipeline; } @@ -420,15 +420,21 @@ private: gpu::ShaderPointer _unlitShader; static render::ShapePipelinePointer _simpleOpaquePipeline; static render::ShapePipelinePointer _simpleTransparentPipeline; + static render::ShapePipelinePointer _simpleOpaqueOverlayPipeline; + static render::ShapePipelinePointer _simpleTransparentOverlayPipeline; static render::ShapePipelinePointer _simpleWirePipeline; gpu::PipelinePointer _glowLinePipeline; QHash _simplePrograms; gpu::ShaderPointer _simpleOpaqueWebBrowserShader; gpu::PipelinePointer _simpleOpaqueWebBrowserPipeline; - gpu::ShaderPointer _simpleTransparentWebBrowserShader; gpu::PipelinePointer _simpleTransparentWebBrowserPipeline; + + gpu::ShaderPointer _simpleOpaqueWebBrowserOverlayShader; + gpu::PipelinePointer _simpleOpaqueWebBrowserOverlayPipeline; + gpu::ShaderPointer _simpleTransparentWebBrowserOverlayShader; + gpu::PipelinePointer _simpleTransparentWebBrowserOverlayPipeline; }; #endif // hifi_GeometryCache_h diff --git a/libraries/render-utils/src/simple_opaque_web_browser.slf b/libraries/render-utils/src/simple_opaque_web_browser.slf index 2921d6aea0..3acf104b55 100644 --- a/libraries/render-utils/src/simple_opaque_web_browser.slf +++ b/libraries/render-utils/src/simple_opaque_web_browser.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple_opaque_web_browser.frag +// simple_opaque_web_browser.slf // fragment shader // // Created by Anthony Thibault on 7/25/16. diff --git a/libraries/render-utils/src/simple_opaque_web_browser_overlay.slf b/libraries/render-utils/src/simple_opaque_web_browser_overlay.slf new file mode 100644 index 0000000000..6d4d35591f --- /dev/null +++ b/libraries/render-utils/src/simple_opaque_web_browser_overlay.slf @@ -0,0 +1,30 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_opaque_web_browser_overlay.slf +// fragment shader +// +// Created by Anthony Thibault on 1/30/17. +// Copyright 2017 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 +// +// Same as simple_opaque_web_browser.slf except frame buffer is sRGB, so colorToLinearRGBA is not necessary. + +<@include gpu/Color.slh@> +<@include DeferredBufferWrite.slh@> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + _fragColor0 = vec4(_color.rgb * texel.rgb, 1.0); +} diff --git a/libraries/render-utils/src/simple_transparent_web_browser.slf b/libraries/render-utils/src/simple_transparent_web_browser.slf index b7606985e6..19079f5d92 100644 --- a/libraries/render-utils/src/simple_transparent_web_browser.slf +++ b/libraries/render-utils/src/simple_transparent_web_browser.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple_transparent_web_browser.frag +// simple_transparent_web_browser.slf // fragment shader // // Created by Anthony Thibault on 7/25/16. @@ -33,4 +33,3 @@ void main(void) { DEFAULT_FRESNEL, DEFAULT_ROUGHNESS); } - diff --git a/libraries/render-utils/src/simple_transparent_web_browser_overlay.slf b/libraries/render-utils/src/simple_transparent_web_browser_overlay.slf new file mode 100644 index 0000000000..af52389d5b --- /dev/null +++ b/libraries/render-utils/src/simple_transparent_web_browser_overlay.slf @@ -0,0 +1,31 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent_web_browser_overlay.slf +// fragment shader +// +// Created by Anthony Thibault on 1/30/17. +// Copyright 2017 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 +// +// Same as simple_transparent_web_browser.slf except frame buffer is sRGB, So colorToLinearRGBA is not necessary. +// + +<@include gpu/Color.slh@> +<@include DeferredBufferWrite.slh@> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + _fragColor0 = vec4(_color.rgb * texel.rgb, _color.a); +} diff --git a/scripts/system/libraries/WebTablet.js b/scripts/system/libraries/WebTablet.js index a342597c2d..6a0f159582 100644 --- a/scripts/system/libraries/WebTablet.js +++ b/scripts/system/libraries/WebTablet.js @@ -128,7 +128,8 @@ WebTablet = function (url, width, dpi, hand, clientOnly) { alpha: 1.0, parentID: this.tabletEntityID, parentJointIndex: -1, - showKeyboardFocusHighlight: false + showKeyboardFocusHighlight: false, + isAA: HMD.active }); var HOME_BUTTON_Y_OFFSET = (this.height / 2) - 0.035; @@ -293,6 +294,10 @@ WebTablet.prototype.onHmdChanged = function () { // compute position, rotation & parentJointIndex of the tablet this.calculateTabletAttachmentProperties(NO_HANDS, tabletProperties); Entities.editEntity(this.tabletEntityID, tabletProperties); + + // Full scene FXAA should be disabled on the overlay when the tablet in desktop mode. + // This should make the text more readable. + Overlays.editOverlay(this.webOverlayID, { isAA: HMD.active }); }; WebTablet.prototype.pickle = function () {