From 9c3b0b8e4f03395efe6550bbf7030427be4cbb40 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Wed, 10 Apr 2024 21:57:37 -0700 Subject: [PATCH] fix effects, patch checksum issue --- .../artery-font-format/disable-checksum.patch | 38 +++++++++++++++++ cmake/ports/artery-font-format/portfile.cmake | 1 + libraries/render-utils/src/sdf_text3D.slf | 8 +--- libraries/render-utils/src/sdf_text3D.slh | 40 ++++++++++-------- libraries/render-utils/src/sdf_text3D.slv | 4 +- libraries/render-utils/src/text/Font.cpp | 41 +++++++++++-------- libraries/render-utils/src/text/Font.h | 13 +++--- 7 files changed, 95 insertions(+), 50 deletions(-) create mode 100644 cmake/ports/artery-font-format/disable-checksum.patch diff --git a/cmake/ports/artery-font-format/disable-checksum.patch b/cmake/ports/artery-font-format/disable-checksum.patch new file mode 100644 index 0000000000..cd5133ea9e --- /dev/null +++ b/cmake/ports/artery-font-format/disable-checksum.patch @@ -0,0 +1,38 @@ +diff --git a/artery-font/serialization.hpp b/artery-font/serialization.hpp +index 69263a8..6075eda 100644 +--- a/artery-font/serialization.hpp ++++ b/artery-font/serialization.hpp +@@ -109,15 +109,16 @@ template class LIST, clas + bool decode(ArteryFont &font, void *userData) { + uint32 totalLength = 0; + uint32 prevLength = 0; +- uint32 checksum = crc32Init(); ++ //uint32 checksum = crc32Init(); + byte dump[4]; + #define ARTERY_FONT_DECODE_READ(target, len) { \ + if (READ((target), (len), userData) != int(len)) \ + return false; \ + totalLength += (len); \ +- for (int _i = 0; _i < int(len); ++_i) \ +- checksum = crc32Update(checksum, reinterpret_cast(target)[_i]); \ + } ++ // for (int _i = 0; _i < int(len); ++_i) \ ++ // checksum = crc32update(checksum, reinterpret_cast(target)[_i]); \ ++ //} + #define ARTERY_FONT_DECODE_REALIGN() { \ + if (totalLength&0x03u) { \ + uint32 len = 0x04u-(totalLength&0x03u); \ +@@ -228,10 +229,10 @@ bool decode(ArteryFont &font, void *userData) { + ARTERY_FONT_DECODE_READ(&footer, sizeof(footer)-sizeof(footer.checksum)); + if (footer.magicNo != ARTERY_FONT_FOOTER_MAGIC_NO) + return false; +- uint32 finalChecksum = checksum; ++ //uint32 finalChecksum = checksum; + ARTERY_FONT_DECODE_READ(&footer.checksum, sizeof(footer.checksum)); +- if (footer.checksum != finalChecksum) +- return false; ++ //if (footer.checksum != finalChecksum) ++ // return false; + if (totalLength != footer.totalLength) + return false; + } diff --git a/cmake/ports/artery-font-format/portfile.cmake b/cmake/ports/artery-font-format/portfile.cmake index bc49711438..4b2491ab67 100644 --- a/cmake/ports/artery-font-format/portfile.cmake +++ b/cmake/ports/artery-font-format/portfile.cmake @@ -6,6 +6,7 @@ vcpkg_from_github( REF 34134bde3cea35a93c2ae5703fa8d3d463793400 SHA512 6b2fc0de9ca7b367c9b98f829ce6cee858f1252b12a49b6f1e89a5a2fdb109e20ef812f0b30495195ca0b177adae32d5e238fdc305724857ced098be2d29a6af HEAD_REF master + PATCHES "disable-checksum.patch" ) file(COPY "${SOURCE_PATH}/artery-font" DESTINATION "${CURRENT_PACKAGES_DIR}/include") diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index 2d644b1120..27debc521e 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -43,13 +43,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) in vec4 _texCoord01; layout(location=RENDER_UTILS_ATTR_FADE1) flat in vec4 _glyphBounds; // we're reusing the fade texcoord locations here void main() { - vec4 color = evalSDFSuperSampled(_texCoord0, _glyphBounds); - - // Clip to edges - vec2 absPos = abs(_positionMS); - if (max(absPos.x, absPos.y) >= 1.0 || _positionMS.x <= 0.0) { - color.a = 0.0; - } + vec4 color = evalSDFSuperSampled(_texCoord0, _positionMS, _glyphBounds); <@if HIFI_USE_TRANSLUCENT or HIFI_USE_FORWARD@> color.a *= params.color.a; diff --git a/libraries/render-utils/src/sdf_text3D.slh b/libraries/render-utils/src/sdf_text3D.slh index 0bd8cae2a4..c927070a4d 100644 --- a/libraries/render-utils/src/sdf_text3D.slh +++ b/libraries/render-utils/src/sdf_text3D.slh @@ -17,13 +17,15 @@ LAYOUT(binding=0) uniform sampler2D fontTexture; struct TextParams { + vec4 bounds; vec4 color; - vec3 effectColor; - float effectThickness; + vec2 unitRange; int effect; - vec2 unitRange; + float effectThickness; + + vec3 effectColor; float spare; }; @@ -48,50 +50,56 @@ float screenPxRange(vec2 texCoord) { return max(0.5 * dot(params.unitRange, screenTexSize), 1.0); } -float evalSDF(vec2 texCoord) { - vec3 msdf = textureLod(fontTexture, texCoord, TAA_TEXTURE_LOD_BIAS).rgb; +vec2 evalSDF(vec2 texCoord) { + vec4 msdf = textureLod(fontTexture, texCoord, TAA_TEXTURE_LOD_BIAS); float sdf = median(msdf.r, msdf.g, msdf.b); float screenPxDistance = screenPxRange(texCoord) * (sdf - 0.5); float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); - return opacity; + return vec2(opacity, msdf.a); } vec4 evalSDFColor(vec2 texCoord, vec4 glyphBounds) { vec3 color = params.color.rgb; - float sdf = evalSDF(texCoord); + vec2 sdf = evalSDF(texCoord); // Outline if (params.effect == 1 || params.effect == 2) { - float outline = float(sdf < interiorCutoff); + float outline = float(sdf.x < interiorCutoff); color = mix(color, params.effectColor, outline); // with or without fill - sdf = mix(sdf, 0.0, float(params.effect == 1) * (1.0 - outline)); + sdf.x = mix(sdf.y, 0.0, float(params.effect == 1) * (1.0 - outline)); const float EPSILON = 0.00001; - sdf += mix(0.0, params.effectThickness - EPSILON, outline); + sdf.x += mix(0.0, params.effectThickness - EPSILON, outline); } else if (params.effect == 3) { // Shadow // don't sample from outside of our glyph bounds - sdf *= mix(1.0, 0.0, float(clamp(texCoord, glyphBounds.xy, glyphBounds.xy + glyphBounds.zw) != texCoord)); + sdf.x *= mix(1.0, 0.0, float(clamp(texCoord, glyphBounds.xy, glyphBounds.xy + glyphBounds.zw) != texCoord)); - if (sdf < interiorCutoff) { + if (sdf.x < interiorCutoff) { color = params.effectColor; const float DOUBLE_MAX_OFFSET_PIXELS = 20.0; // must match value in Font.cpp // FIXME: TAA_TEXTURE_LOD_BIAS doesn't have any effect because we're only generating one mip, so here we need to use 0, but it should // really match the LOD that we use in the textureLod call below vec2 textureOffset = vec2(params.effectThickness * DOUBLE_MAX_OFFSET_PIXELS) / vec2(textureSize(fontTexture, 0/*int(TAA_TEXTURE_LOD_BIAS)*/)); vec2 shadowTexCoords = texCoord - textureOffset; - sdf = evalSDF(shadowTexCoords); + sdf.x = evalSDF(shadowTexCoords).x; // don't sample from outside of our glyph bounds - sdf *= mix(1.0, 0.0, float(clamp(shadowTexCoords, glyphBounds.xy, glyphBounds.xy + glyphBounds.zw) != shadowTexCoords)); + sdf.x *= mix(1.0, 0.0, float(clamp(shadowTexCoords, glyphBounds.xy, glyphBounds.xy + glyphBounds.zw) != shadowTexCoords)); } } - return vec4(color, sdf); + return vec4(color, sdf.x); } -vec4 evalSDFSuperSampled(vec2 texCoord, vec4 glyphBounds) { +vec4 evalSDFSuperSampled(vec2 texCoord, vec2 positionMS, vec4 glyphBounds) { + // Clip to edges. Note: We don't need to check the top edge. + if (positionMS.x < params.bounds.x || positionMS.x > (params.bounds.x + params.bounds.z) || + positionMS.y < params.bounds.y - params.bounds.w) { + return vec4(0.0); + } + vec2 dxTexCoord = dFdx(texCoord) * 0.5 * taaBias; vec2 dyTexCoord = dFdy(texCoord) * 0.5 * taaBias; diff --git a/libraries/render-utils/src/sdf_text3D.slv b/libraries/render-utils/src/sdf_text3D.slv index d88ee78f89..db13e170e9 100644 --- a/libraries/render-utils/src/sdf_text3D.slv +++ b/libraries/render-utils/src/sdf_text3D.slv @@ -28,6 +28,7 @@ layout(location=RENDER_UTILS_ATTR_TEXCOORD01) out vec4 _texCoord01; layout(location=RENDER_UTILS_ATTR_FADE1) flat out vec4 _glyphBounds; // we're reusing the fade texcoord locations here void main() { + _positionMS = inPosition.xy; _texCoord01 = vec4(inTexCoord0.st, 0.0, 0.0); _glyphBounds = inTexCoord1; @@ -48,9 +49,6 @@ void main() { <$transformModelToClipPos(cam, obj, position, gl_Position)$> <@endif@> - // Our position has scale baked in, but we need the normalized values in the fragment shader - _positionMS = inPosition.xy * vec2(length(obj._model[0]), length(obj._model[1])); - const vec3 normal = vec3(0, 0, 1); <$transformModelToWorldDir(cam, obj, normal, _normalWS)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/text/Font.cpp b/libraries/render-utils/src/text/Font.cpp index c79203374c..f77037b523 100644 --- a/libraries/render-utils/src/text/Font.cpp +++ b/libraries/render-utils/src/text/Font.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "artery-font/artery-font.h" #include "artery-font/std-artery-font.h" @@ -97,20 +98,25 @@ void Font::handleFontNetworkReply() { } } -size_t _readOffset = 0; +QThreadStorage _readOffset; +QThreadStorage _readMax; int readHelper(void* dst, int length, void* data) { - memcpy(dst, (char *)data + _readOffset, length); - _readOffset += length; + if (_readOffset.localData() + length > _readMax.localData()) { + return -1; + } + memcpy(dst, (char *)data + _readOffset.localData(), length); + _readOffset.setLocalData(_readOffset.localData() + length); return length; }; void Font::read(QIODevice& in) { - _readOffset = 0; _loaded = false; - void* data = (void *)in.readAll().data(); + QByteArray data = in.readAll(); + _readOffset.setLocalData(0); + _readMax.setLocalData(data.length()); artery_font::StdArteryFont arteryFont; - bool success = artery_font::decode<&readHelper, float, artery_font::StdList, artery_font::StdByteArray, artery_font::StdString>(arteryFont, data); + bool success = artery_font::decode<&readHelper, float, artery_font::StdList, artery_font::StdByteArray, artery_font::StdString>(arteryFont, (void *)data.data()); if (!success) { qDebug() << "Font" << _family << "failed to decode."; @@ -152,8 +158,7 @@ void Font::read(QIODevice& in) { return; } - // TODO: change back to MTSDF - if (arteryFont.images[0].imageType != artery_font::ImageType::IMAGE_MSDF) { + if (arteryFont.images[0].imageType != artery_font::ImageType::IMAGE_MTSDF) { qDebug() << "Font" << _family << "has the wrong image type. Expected MTSDF (7), got" << arteryFont.images[0].imageType; return; } @@ -201,9 +206,7 @@ void Font::read(QIODevice& in) { g.texOffset /= imageSize; // Y flip g.texOffset.y = 1.0f - (g.texOffset.y + g.texSize.y); - if (g.offset.y > 0.0f) { - g.offset.y = -g.offset.y; - } + g.offset.y = -(1.0f - (g.offset.y + g.size.y)); // store in the character to glyph hash _glyphs[g.c] = g; }; @@ -390,8 +393,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm drawInfo.bounds = bounds; drawInfo.origin = origin; - float enlargedBoundsX = bounds.x - 0.5f * DOUBLE_MAX_OFFSET_PIXELS * float(enlargeForShadows); - float rightEdge = origin.x + enlargedBoundsX; + float rightEdge = origin.x + bounds.x; // Top left of text bool firstTokenOfLine = true; @@ -526,8 +528,10 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString int textEffect = (int)effect; const int SHADOW_EFFECT = (int)TextEffect::SHADOW_EFFECT; + const bool boundsChanged = bounds != drawInfo.bounds || origin != drawInfo.origin; + // If we're switching to or from shadow effect mode, we need to rebuild the vertices - if (str != drawInfo.string || bounds != drawInfo.bounds || origin != drawInfo.origin || alignment != _alignment || + if (str != drawInfo.string || boundsChanged || alignment != _alignment || (drawInfo.params.effect != textEffect && (textEffect == SHADOW_EFFECT || drawInfo.params.effect == SHADOW_EFFECT)) || (textEffect == SHADOW_EFFECT && scale != _scale)) { _scale = scale; @@ -537,7 +541,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString setupGPU(); - if (!drawInfo.paramsBuffer || drawInfo.params.color != color || drawInfo.params.effectColor != effectColor || + if (!drawInfo.paramsBuffer || boundsChanged || drawInfo.params.color != color || drawInfo.params.effectColor != effectColor || drawInfo.params.effectThickness != effectThickness || drawInfo.params.effect != textEffect) { drawInfo.params.color = color; drawInfo.params.effectColor = effectColor; @@ -546,11 +550,12 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString // need the gamma corrected color here DrawParams gpuDrawParams; + gpuDrawParams.bounds = glm::vec4(origin, bounds); gpuDrawParams.color = ColorUtils::sRGBToLinearVec4(drawInfo.params.color); - gpuDrawParams.effectColor = ColorUtils::sRGBToLinearVec3(drawInfo.params.effectColor); - gpuDrawParams.effectThickness = drawInfo.params.effectThickness; - gpuDrawParams.effect = drawInfo.params.effect; gpuDrawParams.unitRange = _distanceRange; + gpuDrawParams.effect = drawInfo.params.effect; + gpuDrawParams.effectThickness = drawInfo.params.effectThickness; + gpuDrawParams.effectColor = ColorUtils::sRGBToLinearVec3(drawInfo.params.effectColor); if (!drawInfo.paramsBuffer) { drawInfo.paramsBuffer = std::make_shared(sizeof(DrawParams), nullptr); } diff --git a/libraries/render-utils/src/text/Font.h b/libraries/render-utils/src/text/Font.h index 447bf216fb..b91de95a5f 100644 --- a/libraries/render-utils/src/text/Font.h +++ b/libraries/render-utils/src/text/Font.h @@ -29,15 +29,16 @@ public: void read(QIODevice& path); struct DrawParams { - vec4 color { 0 }; - - vec3 effectColor { 0 }; - float effectThickness { 0 }; - - int effect { 0 }; + vec4 bounds { 0.0f }; + vec4 color { 0.0f }; vec2 unitRange { 1.0f }; + int effect { 0 }; + float effectThickness { 0.0f }; + + vec3 effectColor { 0.0f }; + #if defined(__clang__) __attribute__((unused)) #endif