Merge pull request #15197 from SamGondelman/onion

Case 21746: Fix color grading/lighting of renderLayer front entities
This commit is contained in:
Sam Gondelman 2019-03-15 17:17:09 -07:00 committed by GitHub
commit e7f2df4fac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 268 additions and 331 deletions

View file

@ -43,7 +43,6 @@
using namespace std;
const int NUM_BODY_CONE_SIDES = 9;
const float CHAT_MESSAGE_SCALE = 0.0015f;
const float CHAT_MESSAGE_HEIGHT = 0.1f;
const float DISPLAYNAME_FADE_TIME = 0.5f;
@ -1661,60 +1660,6 @@ int Avatar::parseDataFromBuffer(const QByteArray& buffer) {
return bytesRead;
}
int Avatar::_jointConesID = GeometryCache::UNKNOWN_ID;
// render a makeshift cone section that serves as a body part connecting joint spheres
void Avatar::renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2,
float radius1, float radius2, const glm::vec4& color) {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (_jointConesID == GeometryCache::UNKNOWN_ID) {
_jointConesID = geometryCache->allocateID();
}
glm::vec3 axis = position2 - position1;
float length = glm::length(axis);
if (length > 0.0f) {
axis /= length;
glm::vec3 perpSin = glm::vec3(1.0f, 0.0f, 0.0f);
glm::vec3 perpCos = glm::normalize(glm::cross(axis, perpSin));
perpSin = glm::cross(perpCos, axis);
float angleb = 0.0f;
QVector<glm::vec3> points;
for (int i = 0; i < NUM_BODY_CONE_SIDES; i ++) {
// the rectangles that comprise the sides of the cone section are
// referenced by "a" and "b" in one dimension, and "1", and "2" in the other dimension.
int anglea = angleb;
angleb = ((float)(i+1) / (float)NUM_BODY_CONE_SIDES) * TWO_PI;
float sa = sinf(anglea);
float sb = sinf(angleb);
float ca = cosf(anglea);
float cb = cosf(angleb);
glm::vec3 p1a = position1 + perpSin * sa * radius1 + perpCos * ca * radius1;
glm::vec3 p1b = position1 + perpSin * sb * radius1 + perpCos * cb * radius1;
glm::vec3 p2a = position2 + perpSin * sa * radius2 + perpCos * ca * radius2;
glm::vec3 p2b = position2 + perpSin * sb * radius2 + perpCos * cb * radius2;
points << p1a << p1b << p2a << p1b << p2a << p2b;
}
PROFILE_RANGE_BATCH(batch, __FUNCTION__);
// TODO: this is really inefficient constantly recreating these vertices buffers. It would be
// better if the avatars cached these buffers for each of the joints they are rendering
geometryCache->updateVertices(_jointConesID, points, color);
geometryCache->renderVertices(batch, gpu::TRIANGLES, _jointConesID);
}
}
float Avatar::getSkeletonHeight() const {
Extents extents = _skeletonModel->getBindExtents();
return extents.maximum.y - extents.minimum.y;

View file

@ -296,9 +296,6 @@ public:
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
static void renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2,
float radius1, float radius2, const glm::vec4& color);
/**jsdoc
* Set the offset applied to the current avatar. The offset adjusts the position that the avatar is rendered. For example,
* with an offset of <code>{ x: 0, y: 0.1, z: 0 }</code>, your avatar will appear to be raised off the ground slightly.
@ -665,8 +662,6 @@ protected:
AvatarTransit _transit;
std::mutex _transitLock;
static int _jointConesID;
int _voiceSphereID;
float _displayNameTargetAlpha { 1.0f };

View file

@ -338,24 +338,20 @@ void SkeletonModel::computeBoundingShape() {
void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch& batch, float scale, float alpha) {
auto geometryCache = DependencyManager::get<GeometryCache>();
// draw a blue sphere at the capsule top point
glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
glm::vec3 topPoint = _translation + _rotation * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y));
batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius));
geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha));
// draw a yellow sphere at the capsule bottom point
glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
glm::vec3 axis = topPoint - bottomPoint;
glm::vec3 bottomPoint = topPoint - _rotation * glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f);
batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius));
geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha));
// draw a green cylinder between the two points
glm::vec3 origin(0.0f);
batch.setModelTransform(Transform().setTranslation(bottomPoint));
geometryCache->bindSimpleProgram(batch);
Avatar::renderJointConnectingCone(batch, origin, axis, scale * _boundingCapsuleRadius, scale * _boundingCapsuleRadius,
glm::vec4(0.6f, 0.8f, 0.6f, alpha));
float capsuleDiameter = 2.0f * _boundingCapsuleRadius;
glm::vec3 cylinderDimensions = glm::vec3(capsuleDiameter, _boundingCapsuleHeight, capsuleDiameter);
batch.setModelTransform(Transform().setScale(scale * cylinderDimensions).setRotation(_rotation).setTranslation(0.5f * (topPoint + bottomPoint)));
geometryCache->renderSolidShapeInstance(args, batch, GeometryCache::Shape::Cylinder, glm::vec4(0.6f, 0.8f, 0.6f, alpha));
}
bool SkeletonModel::hasSkeleton() {

View file

@ -46,12 +46,7 @@ PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity)
void PolyLineEntityRenderer::buildPipeline() {
// FIXME: opaque pipeline
gpu::ShaderPointer program;
if (DISABLE_DEFERRED) {
program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke_forward);
} else {
program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
}
gpu::ShaderPointer program = gpu::Shader::createProgram(DISABLE_DEFERRED ? shader::entities_renderer::program::paintStroke_forward : shader::entities_renderer::program::paintStroke);
{
gpu::StatePointer state = gpu::StatePointer(new gpu::State());

View file

@ -19,8 +19,6 @@
#include "RenderPipelines.h"
#include <DisableDeferred.h>
//#define SHAPE_ENTITY_USE_FADE_EFFECT
#ifdef SHAPE_ENTITY_USE_FADE_EFFECT
#include <FadeEffect.h>
@ -277,16 +275,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) {
} else if (!useMaterialPipeline(materials)) {
// FIXME, support instanced multi-shape rendering using multidraw indirect
outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
render::ShapePipelinePointer pipeline;
if (_renderLayer == RenderLayer::WORLD && !DISABLE_DEFERRED) {
pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline();
} else {
pipeline = outColor.a < 1.0f ? geometryCache->getForwardTransparentShapePipeline() : geometryCache->getForwardOpaqueShapePipeline();
}
if (render::ShapeKey(args->_globalShapeKey).isWireframe() || _primitiveMode == PrimitiveMode::LINES) {
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, pipeline);
geometryCache->renderWireShapeInstance(args, batch, geometryShape, outColor, args->_shapePipeline);
} else {
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline);
geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, args->_shapePipeline);
}
} else {
if (args->_renderMode != render::Args::RenderMode::SHADOW_RENDER_MODE) {

View file

@ -19,7 +19,7 @@
#include "GLMHelpers.h"
#include <DisableDeferred.h>
#include "DeferredLightingEffect.h"
using namespace render;
using namespace render::entities;
@ -162,7 +162,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
glm::vec4 backgroundColor;
Transform modelTransform;
glm::vec3 dimensions;
bool forwardRendered;
bool layered;
withReadLock([&] {
modelTransform = _renderTransform;
dimensions = _dimensions;
@ -172,7 +172,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
textColor = EntityRenderer::calculatePulseColor(textColor, _pulseProperties, _created);
backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
backgroundColor = EntityRenderer::calculatePulseColor(backgroundColor, _pulseProperties, _created);
forwardRendered = _renderLayer != RenderLayer::WORLD || DISABLE_DEFERRED;
layered = _renderLayer != RenderLayer::WORLD;
});
// Render background
@ -184,6 +184,11 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
Q_ASSERT(args->_batch);
gpu::Batch& batch = *args->_batch;
// FIXME: we need to find a better way of rendering text so we don't have to do this
if (layered) {
DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch);
}
auto transformToTopLeft = modelTransform;
transformToTopLeft.setRotation(EntityItem::getBillboardRotation(transformToTopLeft.getTranslation(), transformToTopLeft.getRotation(), _billboardMode, args->getViewFrustum().getPosition()));
transformToTopLeft.postTranslate(dimensions * glm::vec3(-0.5f, 0.5f, 0.0f)); // Go to the top left
@ -192,7 +197,7 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
if (backgroundColor.a > 0.0f) {
batch.setModelTransform(transformToTopLeft);
auto geometryCache = DependencyManager::get<GeometryCache>();
geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, forwardRendered);
geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false, true, layered);
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
}
@ -203,7 +208,11 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
batch.setModelTransform(transformToTopLeft);
glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin), dimensions.y - (_topMargin + _bottomMargin));
_textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, forwardRendered);
_textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale, layered);
}
if (layered) {
DependencyManager::get<DeferredLightingEffect>()->unsetKeyLightBatch(batch);
}
}

View file

@ -235,7 +235,7 @@ vec3 fetchLightmapMap(vec2 uv) {
<@endfunc@>
<@func discardInvisible(opacity)@>
{
if (<$opacity$> < 1.e-6) {
if (<$opacity$> <= 0.0) {
discard;
}
}

View file

@ -29,7 +29,7 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) {
<@include LightingModel.slh@>
void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) {
if (alpha != 1.0) {
if (alpha < 1.0) {
discard;
}
@ -42,7 +42,7 @@ void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness
}
void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 lightmap) {
if (alpha != 1.0) {
if (alpha < 1.0) {
discard;
}
@ -54,7 +54,7 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r
}
void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) {
if (alpha != 1.0) {
if (alpha < 1.0) {
discard;
}
_fragColor0 = vec4(color, packUnlit());

View file

@ -722,8 +722,6 @@ gpu::ShaderPointer GeometryCache::_unlitFadeShader;
render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;
render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;
render::ShapePipelinePointer GeometryCache::_forwardSimpleOpaquePipeline;
render::ShapePipelinePointer GeometryCache::_forwardSimpleTransparentPipeline;
render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline;
render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline;
render::ShapePipelinePointer GeometryCache::_simpleWirePipeline;
@ -803,8 +801,6 @@ void GeometryCache::initializeShapePipelines() {
if (!_simpleOpaquePipeline) {
_simpleOpaquePipeline = getShapePipeline(false, false, true, false);
_simpleTransparentPipeline = getShapePipeline(false, true, true, false);
_forwardSimpleOpaquePipeline = getShapePipeline(false, false, true, false, false, true);
_forwardSimpleTransparentPipeline = getShapePipeline(false, true, true, false, false, true);
_simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false);
_simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false);
_simpleWirePipeline = getShapePipeline(false, false, true, true);
@ -836,14 +832,6 @@ render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured
);
}
render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) {
return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline;
}
render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) {
return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline;
}
void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
batch.setInputFormat(getSolidStreamFormat());
_shapes[shape].draw(batch);
@ -1029,7 +1017,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, con
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
const glm::vec3 NORMAL(0.0f, 1.0f, 0.0f);
auto pointCount = points.size();
auto colorCount = colors.size();
int compactColor = 0;
@ -1107,7 +1095,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
const glm::vec3 NORMAL(0.0f, 1.0f, 0.0f);
auto pointCount = points.size();
auto colorCount = colors.size();
for (auto i = 0; i < pointCount; i++) {
@ -1195,7 +1183,7 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
int* colorData = new int[details.vertices];
int* colorDataAt = colorData;
const glm::vec3 NORMAL(0.0f, 0.0f, 1.0f);
const glm::vec3 NORMAL(0.0f, 1.0f, 0.0f);
for (int i = 0; i < points.size(); i++) {
glm::vec3 point = points[i];
glm::vec2 texCoord = texCoords[i];
@ -2018,77 +2006,6 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm
batch.draw(gpu::LINES, 2, 0);
}
void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color, float glowIntensity, float glowWidth, int id) {
// Disable glow lines on OSX
#ifndef Q_OS_WIN
glowIntensity = 0.0f;
#endif
if (glowIntensity <= 0.0f) {
if (color.a >= 1.0f) {
bindSimpleProgram(batch, false, false, false, true, true);
} else {
bindSimpleProgram(batch, false, true, false, true, true);
}
renderLine(batch, p1, p2, color, id);
return;
}
// Compile the shaders
static std::once_flag once;
std::call_once(once, [&] {
auto state = std::make_shared<gpu::State>();
auto program = gpu::Shader::createProgram(shader::render_utils::program::glowLine);
state->setCullMode(gpu::State::CULL_NONE);
state->setDepthTest(true, false, 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);
PrepareStencil::testMask(*state);
_glowLinePipeline = gpu::Pipeline::create(program, state);
});
batch.setPipeline(_glowLinePipeline);
Vec3Pair key(p1, p2);
bool registered = (id != UNKNOWN_ID);
BatchItemDetails& details = _registeredLine3DVBOs[id];
// if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed
if (registered && details.isCreated) {
Vec3Pair& lastKey = _lastRegisteredLine3D[id];
if (lastKey != key) {
details.clear();
_lastRegisteredLine3D[id] = key;
}
}
const int NUM_VERTICES = 4;
if (!details.isCreated) {
details.isCreated = true;
details.uniformBuffer = std::make_shared<gpu::Buffer>();
struct LineData {
vec4 p1;
vec4 p2;
vec4 color;
float width;
};
LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color, glowWidth };
details.uniformBuffer->resize(sizeof(LineData));
details.uniformBuffer->setSubData(0, lineData);
}
// The shader requires no vertices, only uniforms.
batch.setUniformBuffer(0, details.uniformBuffer);
batch.draw(gpu::TRIANGLE_STRIP, NUM_VERTICES, 0);
}
void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
static std::once_flag once;
std::call_once(once, [&]() {
@ -2282,8 +2199,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp
_unlitShader = _forwardUnlitShader;
} else {
_simpleShader = gpu::Shader::createProgram(simple_textured);
// Use the forward pipeline for both here, otherwise transparents will be unlit
_transparentShader = gpu::Shader::createProgram(forward_simple_textured_transparent);
_transparentShader = gpu::Shader::createProgram(simple_transparent_textured);
_unlitShader = gpu::Shader::createProgram(simple_textured_unlit);
}
});

View file

@ -181,17 +181,6 @@ public:
static void initializeShapePipelines();
render::ShapePipelinePointer getOpaqueShapePipeline() { assert(_simpleOpaquePipeline != nullptr); return _simpleOpaquePipeline; }
render::ShapePipelinePointer getTransparentShapePipeline() { assert(_simpleTransparentPipeline != nullptr); return _simpleTransparentPipeline; }
render::ShapePipelinePointer getForwardOpaqueShapePipeline() { assert(_forwardSimpleOpaquePipeline != nullptr); return _forwardSimpleOpaquePipeline; }
render::ShapePipelinePointer getForwardTransparentShapePipeline() { assert(_forwardSimpleTransparentPipeline != nullptr); return _forwardSimpleTransparentPipeline; }
render::ShapePipelinePointer getOpaqueFadeShapePipeline() { assert(_simpleOpaqueFadePipeline != nullptr); return _simpleOpaqueFadePipeline; }
render::ShapePipelinePointer getTransparentFadeShapePipeline() { assert(_simpleTransparentFadePipeline != nullptr); return _simpleTransparentFadePipeline; }
render::ShapePipelinePointer getOpaqueShapePipeline(bool isFading);
render::ShapePipelinePointer getTransparentShapePipeline(bool isFading);
render::ShapePipelinePointer getWireShapePipeline() { assert(_simpleWirePipeline != nullptr); return GeometryCache::_simpleWirePipeline; }
// Static (instanced) geometry
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
@ -317,12 +306,6 @@ public:
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id);
void renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color, float glowIntensity, float glowWidth, int id);
void renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec4& color, int id)
{ renderGlowLine(batch, p1, p2, color, 1.0f, 0.05f, id); }
void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id)
{ renderDashedLine(batch, start, end, color, 0.05f, 0.025f, id); }
@ -478,12 +461,9 @@ private:
static gpu::ShaderPointer _unlitFadeShader;
static render::ShapePipelinePointer _simpleOpaquePipeline;
static render::ShapePipelinePointer _simpleTransparentPipeline;
static render::ShapePipelinePointer _forwardSimpleOpaquePipeline;
static render::ShapePipelinePointer _forwardSimpleTransparentPipeline;
static render::ShapePipelinePointer _simpleOpaqueFadePipeline;
static render::ShapePipelinePointer _simpleTransparentFadePipeline;
static render::ShapePipelinePointer _simpleWirePipeline;
gpu::PipelinePointer _glowLinePipeline;
static QHash<SimpleProgramKey, gpu::PipelinePointer> _simplePrograms;

View file

@ -67,11 +67,11 @@ float TextRenderer3D::getFontSize() const {
}
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
const glm::vec2& bounds, bool forwardRendered) {
const glm::vec2& bounds, bool layered) {
// The font does all the OpenGL work
if (_font) {
_color = color;
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, forwardRendered);
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, layered);
}
}

View file

@ -39,7 +39,7 @@ public:
float getFontSize() const; // Pixel size
void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color = glm::vec4(1.0f),
const glm::vec2& bounds = glm::vec2(-1.0f), bool forwardRendered = false);
const glm::vec2& bounds = glm::vec2(-1.0f), bool layered = false);
private:
TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false,

View file

@ -0,0 +1,57 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// sdf_text3D_transparent.frag
// fragment shader
//
// Created by Bradley Austin Davis on 2015-02-04
// Based on fragment shader code from
// https://github.com/paulhoux/Cinder-Samples/blob/master/TextRendering/include/text/Text.cpp
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
<@include DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
<$declareEvalSkyboxGlobalColor()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
<@include render-utils/ShaderConstants.h@>
<@include sdf_text3D.slh@>
<$declareEvalSDFSuperSampled()$>
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
#define _texCoord0 _texCoord01.xy
#define _texCoord1 _texCoord01.zw
layout(location=0) out vec4 _fragColor0;
void main() {
float a = evalSDFSuperSampled(_texCoord0);
float alpha = a * _color.a;
if (alpha <= 0.0) {
discard;
}
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _positionES.xyz;
_fragColor0 = vec4(evalSkyboxGlobalColor(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normalWS),
_color.rgb,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_ROUGHNESS),
1.0);
}

View file

@ -11,6 +11,7 @@
// 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/Color.slh@>
<@include DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
@ -21,10 +22,8 @@
<@include render-utils/ShaderConstants.h@>
// the albedo texture
LAYOUT(binding=0) uniform sampler2D originalTexture;
// the interpolated normal
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
@ -36,7 +35,11 @@ layout(location=0) out vec4 _fragColor0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a * texel.a;
texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0));
vec3 albedo = _color.xyz * texel.xyz;
float metallic = DEFAULT_METALLIC;
vec3 fresnel = getFresnelF0(metallic, albedo);
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _positionES.xyz;
@ -47,9 +50,9 @@ void main(void) {
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normalWS),
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
albedo,
fresnel,
metallic,
DEFAULT_ROUGHNESS),
1.0);
}

View file

@ -11,6 +11,7 @@
// 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/Color.slh@>
<@include DefaultMaterials.slh@>
<@include ForwardGlobalLight.slh@>
@ -21,22 +22,25 @@
<@include render-utils/ShaderConstants.h@>
// the albedo texture
LAYOUT(binding=0) uniform sampler2D originalTexture;
// the interpolated normal
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
#define _texCoord0 _texCoord01.xy
#define _texCoord1 _texCoord01.zw
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
layout(location=0) out vec4 _fragColor0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
float colorAlpha = _color.a * texel.a;
texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0));
vec3 albedo = _color.xyz * texel.xyz;
float alpha = _color.a * texel.a;
float metallic = DEFAULT_METALLIC;
vec3 fresnel = getFresnelF0(metallic, albedo);
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _positionES.xyz;
@ -47,10 +51,10 @@ void main(void) {
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normalWS),
_color.rgb * texel.rgb,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
albedo,
fresnel,
metallic,
DEFAULT_EMISSIVE,
DEFAULT_ROUGHNESS, colorAlpha),
colorAlpha);
DEFAULT_ROUGHNESS, alpha),
alpha);
}

View file

@ -0,0 +1 @@
VERTEX sdf_text3D

View file

@ -13,54 +13,22 @@
<@include DeferredBufferWrite.slh@>
<@include render-utils/ShaderConstants.h@>
LAYOUT(binding=0) uniform sampler2D Font;
<@include sdf_text3D.slh@>
<$declareEvalSDFSuperSampled()$>
struct TextParams {
vec4 color;
vec4 outline;
};
LAYOUT(binding=0) uniform textParamsBuffer {
TextParams params;
};
// the interpolated normal
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
#define _texCoord0 _texCoord01.xy
#define _texCoord1 _texCoord01.zw
#define TAA_TEXTURE_LOD_BIAS -3.0
const float interiorCutoff = 0.8;
const float outlineExpansion = 0.2;
const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);
float evalSDF(vec2 texCoord) {
// retrieve signed distance
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
sdf = mix(sdf, mix(sdf + outlineExpansion, 1.0 - sdf, float(sdf > interiorCutoff)), float(params.outline.x > 0.0));
// Rely on TAA for anti-aliasing
return step(0.5, sdf);
}
void main() {
vec2 dxTexCoord = dFdx(_texCoord0) * 0.5 * taaBias;
vec2 dyTexCoord = dFdy(_texCoord0) * 0.5 * taaBias;
// Perform 4x supersampling for anisotropic filtering
float a;
a = evalSDF(_texCoord0);
a += evalSDF(_texCoord0 + dxTexCoord);
a += evalSDF(_texCoord0 + dyTexCoord);
a += evalSDF(_texCoord0 + dxTexCoord + dyTexCoord);
a *= 0.25;
float a = evalSDFSuperSampled(_texCoord0);
packDeferredFragment(
normalize(_normalWS),
a * params.color.a,
params.color.rgb,
a,
_color.rgb,
DEFAULT_ROUGHNESS,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,

View file

@ -0,0 +1,63 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
<!
// <$_SCRIBE_FILENAME$>
// Generated on <$_SCRIBE_DATE$>
//
// Created by Sam Gondelman on 3/15/19
// Copyright 2019 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
//
!>
<@if not SDF_TEXT3D_SLH@>
<@def SDF_TEXT3D_SLH@>
LAYOUT(binding=0) uniform sampler2D Font;
struct TextParams {
vec4 color;
vec4 outline;
};
LAYOUT(binding=0) uniform textParamsBuffer {
TextParams params;
};
<@func declareEvalSDFSuperSampled()@>
#define TAA_TEXTURE_LOD_BIAS -3.0
const float interiorCutoff = 0.8;
const float outlineExpansion = 0.2;
const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);
float evalSDF(vec2 texCoord) {
// retrieve signed distance
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
sdf = mix(sdf, mix(sdf + outlineExpansion, 1.0 - sdf, float(sdf > interiorCutoff)), float(params.outline.x > 0.0));
// Rely on TAA for anti-aliasing
return step(0.5, sdf);
}
float evalSDFSuperSampled(vec2 texCoord) {
vec2 dxTexCoord = dFdx(texCoord) * 0.5 * taaBias;
vec2 dyTexCoord = dFdy(texCoord) * 0.5 * taaBias;
// Perform 4x supersampling for anisotropic filtering
float a;
a = evalSDF(texCoord);
a += evalSDF(texCoord + dxTexCoord);
a += evalSDF(texCoord + dyTexCoord);
a += evalSDF(texCoord + dxTexCoord + dyTexCoord);
a *= 0.25;
return a;
}
<@endfunc@>
<@endif@>

View file

@ -11,18 +11,23 @@
//
<@include gpu/Inputs.slh@>
<@include gpu/Transform.slh@>
<@include gpu/Color.slh@>
<@include render-utils/ShaderConstants.h@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
<@include sdf_text3D.slh@>
// the interpolated normal
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
layout(location=RENDER_UTILS_ATTR_POSITION_ES) out vec4 _positionES;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01;
void main() {
_texCoord01.xy = inTexCoord0.xy;
_color = color_sRGBAToLinear(params.color);
// standard transform
TransformCamera cam = getTransformCamera();

View file

@ -20,53 +20,22 @@
<@include render-utils/ShaderConstants.h@>
LAYOUT(binding=0) uniform sampler2D Font;
struct TextParams {
vec4 color;
vec4 outline;
};
LAYOUT(binding=0) uniform textParamsBuffer {
TextParams params;
};
<@include sdf_text3D.slh@>
<$declareEvalSDFSuperSampled()$>
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
#define _texCoord0 _texCoord01.xy
#define _texCoord1 _texCoord01.zw
layout(location=0) out vec4 _fragColor0;
#define TAA_TEXTURE_LOD_BIAS -3.0
const float interiorCutoff = 0.8;
const float outlineExpansion = 0.2;
const float taaBias = pow(2.0, TAA_TEXTURE_LOD_BIAS);
float evalSDF(vec2 texCoord) {
// retrieve signed distance
float sdf = textureLod(Font, texCoord, TAA_TEXTURE_LOD_BIAS).g;
sdf = mix(sdf, mix(sdf + outlineExpansion, 1.0 - sdf, float(sdf > interiorCutoff)), float(params.outline.x > 0.0));
// Rely on TAA for anti-aliasing
return step(0.5, sdf);
}
void main() {
vec2 dxTexCoord = dFdx(_texCoord0) * 0.5 * taaBias;
vec2 dyTexCoord = dFdy(_texCoord0) * 0.5 * taaBias;
float a = evalSDFSuperSampled(_texCoord0);
// Perform 4x supersampling for anisotropic filtering
float a;
a = evalSDF(_texCoord0);
a += evalSDF(_texCoord0 + dxTexCoord);
a += evalSDF(_texCoord0 + dyTexCoord);
a += evalSDF(_texCoord0 + dxTexCoord + dyTexCoord);
a *= 0.25;
float alpha = a * params.color.a;
float alpha = a * _color.a;
if (alpha <= 0.0) {
discard;
}
@ -80,7 +49,7 @@ void main() {
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normalWS),
params.color.rgb,
_color.rgb,
DEFAULT_FRESNEL,
DEFAULT_METALLIC,
DEFAULT_EMISSIVE,

View file

@ -19,7 +19,6 @@
<@include render-utils/ShaderConstants.h@>
// the interpolated normal
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) out vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_NORMAL_MS) out vec3 _normalMS;
layout(location=RENDER_UTILS_ATTR_COLOR) out vec4 _color;

View file

@ -11,31 +11,50 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DefaultMaterials.slh@>
<@include gpu/Color.slh@>
<@include DeferredBufferWrite.slh@>
<@include render-utils/ShaderConstants.h@>
// the albedo texture
<@include ForwardGlobalLight.slh@>
<$declareEvalGlobalLightingAlphaBlended()$>
<@include gpu/Transform.slh@>
<$declareStandardCameraTransform()$>
LAYOUT(binding=0) uniform sampler2D originalTexture;
// the interpolated normal
layout(location=RENDER_UTILS_ATTR_POSITION_ES) in vec4 _positionES;
layout(location=RENDER_UTILS_ATTR_NORMAL_WS) in vec3 _normalWS;
layout(location=RENDER_UTILS_ATTR_COLOR) in vec4 _color;
layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01;
#define _texCoord0 _texCoord01.xy
#define _texCoord1 _texCoord01.zw
layout(location=0) out vec4 _fragColor0;
void main(void) {
vec4 texel = texture(originalTexture, _texCoord0);
texel = mix(texel, color_sRGBAToLinear(texel), float(_color.a <= 0.0));
texel.rgb *= _color.rgb;
texel.a *= abs(_color.a);
vec3 albedo = _color.xyz * texel.xyz;
float alpha = _color.a * texel.a;
float metallic = DEFAULT_METALLIC;
packDeferredFragmentTranslucent(
vec3 fresnel = getFresnelF0(metallic, albedo);
TransformCamera cam = getTransformCamera();
vec3 fragPosition = _positionES.xyz;
_fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze(
cam._viewInverse,
1.0,
DEFAULT_OCCLUSION,
fragPosition,
normalize(_normalWS),
texel.a,
texel.rgb,
DEFAULT_ROUGHNESS);
albedo,
fresnel,
metallic,
DEFAULT_EMISSIVE,
DEFAULT_ROUGHNESS, alpha),
alpha);
}

View file

@ -13,6 +13,8 @@
#include "FontFamilies.h"
#include "../StencilMaskPass.h"
#include "DisableDeferred.h"
static std::mutex fontMutex;
struct TextureVertex {
@ -221,25 +223,43 @@ void Font::setupGPU() {
// Setup render pipeline
{
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D);
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
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);
PrepareStencil::testMaskDrawShape(*state);
_pipeline = gpu::Pipeline::create(program, state);
{
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::forward_sdf_text3D);
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
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);
PrepareStencil::testMaskDrawShape(*state);
_layeredPipeline = gpu::Pipeline::create(program, state);
}
gpu::ShaderPointer programTransparent = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent);
auto transparentState = std::make_shared<gpu::State>();
transparentState->setCullMode(gpu::State::CULL_BACK);
transparentState->setDepthTest(true, true, gpu::LESS_EQUAL);
transparentState->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);
PrepareStencil::testMask(*transparentState);
_transparentPipeline = gpu::Pipeline::create(programTransparent, transparentState);
if (DISABLE_DEFERRED) {
_pipeline = _layeredPipeline;
} else {
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D);
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
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);
PrepareStencil::testMaskDrawShape(*state);
_pipeline = gpu::Pipeline::create(program, state);
}
{
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent);
auto state = std::make_shared<gpu::State>();
state->setCullMode(gpu::State::CULL_BACK);
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);
PrepareStencil::testMask(*state);
_transparentPipeline = gpu::Pipeline::create(program, state);
}
}
// Sanity checks
@ -343,7 +363,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
}
void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool forwardRendered) {
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool layered) {
if (str == "") {
return;
}
@ -370,7 +390,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString
}
// need the gamma corrected color here
batch.setPipeline(forwardRendered || (color.a < 1.0f) ? _transparentPipeline : _pipeline);
batch.setPipeline(color.a < 1.0f ? _transparentPipeline : (layered ? _layeredPipeline : _pipeline));
batch.setInputFormat(_format);
batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);

View file

@ -46,7 +46,7 @@ public:
// Render string to batch
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str,
const glm::vec4& color, EffectType effectType,
const glm::vec2& origin, const glm::vec2& bound, bool forwardRendered);
const glm::vec2& origin, const glm::vec2& bound, bool layered);
static Pointer load(const QString& family);
@ -81,6 +81,7 @@ private:
// gpu structures
gpu::PipelinePointer _pipeline;
gpu::PipelinePointer _layeredPipeline;
gpu::PipelinePointer _transparentPipeline;
gpu::TexturePointer _texture;
gpu::Stream::FormatPointer _format;