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.
This commit is contained in:
Anthony J. Thibault 2017-01-30 11:15:40 -08:00
parent a9b478888c
commit 39d68828ab
12 changed files with 138 additions and 57 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -249,9 +249,9 @@ void Web3DOverlay::render(RenderArgs* args) {
batch.setModelTransform(transform);
auto geometryCache = DependencyManager::get<GeometryCache>();
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

View file

@ -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;

View file

@ -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<GeometryCache>()->bindTransparentWebBrowserProgram(batch);
DependencyManager::get<GeometryCache>()->bindTransparentWebBrowserProgram(batch, IS_AA);
} else {
DependencyManager::get<GeometryCache>()->bindOpaqueWebBrowserProgram(batch);
DependencyManager::get<GeometryCache>()->bindOpaqueWebBrowserProgram(batch, IS_AA);
}
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId);
}

View file

@ -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<gpu::State>();
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<TextureCache>()->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<gpu::State>();
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<TextureCache>()->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<gpu::State>();
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) {

View file

@ -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<SimpleProgramKey, gpu::PipelinePointer> _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

View file

@ -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.

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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 () {