From 38336aa94486929ba3833b16499e2e5a787e1bba Mon Sep 17 00:00:00 2001 From: wuyize Date: Wed, 29 Mar 2023 12:31:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0MaterialStyle::decoded?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../res/Shaders/painting.comp | 64 +++++++++++++++---- .../src/Renderer/Painting/BaseStyle.cpp | 8 ++- .../src/Renderer/Preview/ElementRenderer.cpp | 1 + 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/ArchitectureColoredPainting/res/Shaders/painting.comp b/ArchitectureColoredPainting/res/Shaders/painting.comp index 6c79a8b..a5ea5e2 100644 --- a/ArchitectureColoredPainting/res/Shaders/painting.comp +++ b/ArchitectureColoredPainting/res/Shaders/painting.comp @@ -625,7 +625,7 @@ int solve_quartic(vec4 coeffs, inout vec4 s) return num; } -float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd) +float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEnd, out float t) { // switch points when near to end point to minimize numerical error @@ -862,7 +862,13 @@ float cubic_bezier_dis(vec2 uv, vec2 p0, vec2 p1, vec2 p2, vec2 p3, bool roundEn { roots[i] = clamp(roots[i], 0., 1.); vec2 to_curve = uv - parametric_cub_bezier(roots[i], p0, p1, p2, p3); - d0 = min(d0, dot(to_curve, to_curve)); + float d = dot(to_curve, to_curve); + if (d < d0) + { + d0 = d; + t = roots[i]; + } + // d0 = min(d0, dot(to_curve, to_curve)); } else { @@ -959,6 +965,37 @@ bool angleLargeThanPi(vec2 a, vec2 b) return a.x * b.y - b.x * a.y < 0; } +float getLocalWidth(float t, vec2 lengthRate, float originWidth, uint widthMapSize, uint widthMapIndex) +{ + if (widthMapSize == 0) + return originWidth; + float width; + vec2 lastData = unpackUnorm2x16(floatBitsToUint(elementData[widthMapIndex])); + float lastLevel = 0; + float lastWidth = lastData.y; + float currentLengthRate = mix(lengthRate.x, lengthRate.y, t); + bool found = false; + for (uint i = 0; i < widthMapSize; i++) + { + vec2 data = unpackUnorm2x16(floatBitsToUint(elementData[widthMapIndex + i])); + float level = data.x; + float currentWidth = data.y; + if (currentLengthRate <= level) + { + float a = (currentLengthRate - lastLevel) / (level - lastLevel); + a = smoothstep(0, 1, a); + width = mix(lastWidth, currentWidth, a); + found = true; + break; + } + lastWidth = currentWidth; + lastLevel = level; + } + if (!found) + width = lastWidth; + return width * originWidth; +} + void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 metallicRoughness) { elementColor = vec4(1); @@ -1156,11 +1193,11 @@ vec2 getLineTangentEnd(uint contourIterator, uint linesOffset, uint pointsOffset return normalize(p[3] - p[1]); } -mat4x2 getPointsByContourIterator(uint contourIterator, uint linesOffset, uint pointsOffset) +mat4x2 getPointsByContourIterator(uint contourIterator, uint linesOffset, uint pointsOffset, out vec2 lengthRate) { uint lineIndex = elementIndexs[contourIterator]; uint pLocation = linesOffset + 3 * lineIndex; - vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]); + lengthRate = unpackUnorm2x16(elementIndexs[pLocation + 2]); uvec4 pxIndex = uvec4(pointsOffset) + 2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF, elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 0xFFFF); @@ -1186,6 +1223,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point float minDistance = 1e38; uint lineCount = elementIndexs[contourIndex]; uint widthMapSize = floatBitsToUint(elementData[styleIndex + 1]); + uint widthMapIndex = styleIndex + 2; styleIndex += widthMapSize + 2; vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex])); float lineType = floor(styleHead.b * 10); @@ -1202,7 +1240,8 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point for (uint contourIterator_ = contourIndex + 1; contourIterator_ < contourIndex + 1 + lineCount; contourIterator_++) { uint contourIterator = contourIterator_; - mat4x2 p = getPointsByContourIterator(contourIterator, linesOffset, pointsOffset); + vec2 lengthRate; + mat4x2 p = getPointsByContourIterator(contourIterator, linesOffset, pointsOffset, lengthRate); if ((contourIterator == contourIndex + 1)) { @@ -1235,7 +1274,8 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point vec2 tangentBeginNext = vec2(0); if (contourIterator + 1 < contourIndex + 1 + lineCount) { - mat4x2 pNext = getPointsByContourIterator(contourIterator + 1, linesOffset, pointsOffset); + vec2 lengthRate; + mat4x2 pNext = getPointsByContourIterator(contourIterator + 1, linesOffset, pointsOffset, lengthRate); if (pNext[0] == p[3]) { @@ -1267,13 +1307,15 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point onVeryEnd = true; } - float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true); - if (d <= strokeWidth) + float t; + float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true, t); + float localWidth = getLocalWidth(t, lengthRate, strokeWidth, widthMapSize, widthMapIndex); + if (d <= localWidth) { bool hit = d < minDistance; hit = hit && - shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast, strokeWidth); - hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext, strokeWidth); + shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast, localWidth); + hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext, localWidth); if (hit) { bool reverse = p[3].y - p[0].y < 0.; @@ -1289,7 +1331,7 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point { minDistance = min(minDistance, d); hitElement = true; - drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness); + drawLine(minDistance / localWidth, styleIndex, elementColor, metallicRoughness); } } } diff --git a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp index f77a07a..a462dd3 100644 --- a/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Painting/BaseStyle.cpp @@ -64,7 +64,13 @@ std::unique_ptr Renderer::MaterialStyle::decoded(const std::vecto else /// MaterialStyleStroke { std::unique_ptr materialStroke; + std::map widthMap; uint widthMapSize = floatBitsToUint(encoded[1]); + for (int i = 0; i < widthMapSize; i++) + { + glm::vec2 v = glm::unpackUnorm2x16(glm::floatBitsToUint(encoded[2 + i])); + widthMap.emplace(v.x, v.y); + } uint headIndex = widthMapSize + 2; if (encoded[1] < 0) headIndex = 1; /// ¼æÈݾɰæ±àÂë @@ -96,6 +102,6 @@ std::unique_ptr Renderer::MaterialStyle::decoded(const std::vecto break; } } - return std::make_unique(encoded[0], strokeType, endType, std::move(materialStroke)); + return std::make_unique(encoded[0], strokeType, endType, std::move(materialStroke), widthMap); } } diff --git a/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp b/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp index 9c0c54f..c2e6341 100644 --- a/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp +++ b/ArchitectureColoredPainting/src/Renderer/Preview/ElementRenderer.cpp @@ -70,6 +70,7 @@ std::vector generatePathBuffer(const QPainterPath& path) pathBuffer.emplace_back(element.x, element.y); lastPoint = glm::vec2(element.x, element.y); j++; + k = 0; break; case QPainterPath::LineToElement: {