更新MaterialStyle::decoded

main
wuyize 2023-03-29 12:31:21 +08:00
parent 5013538e16
commit 38336aa944
3 changed files with 61 additions and 12 deletions

View File

@ -625,7 +625,7 @@ int solve_quartic(vec4 coeffs, inout vec4 s)
return num; 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 // 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.); roots[i] = clamp(roots[i], 0., 1.);
vec2 to_curve = uv - parametric_cub_bezier(roots[i], p0, p1, p2, p3); 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 else
{ {
@ -959,6 +965,37 @@ bool angleLargeThanPi(vec2 a, vec2 b)
return a.x * b.y - b.x * a.y < 0; 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) void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 metallicRoughness)
{ {
elementColor = vec4(1); elementColor = vec4(1);
@ -1156,11 +1193,11 @@ vec2 getLineTangentEnd(uint contourIterator, uint linesOffset, uint pointsOffset
return normalize(p[3] - p[1]); 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 lineIndex = elementIndexs[contourIterator];
uint pLocation = linesOffset + 3 * lineIndex; uint pLocation = linesOffset + 3 * lineIndex;
vec2 percent = unpackUnorm2x16(elementIndexs[pLocation + 2]); lengthRate = unpackUnorm2x16(elementIndexs[pLocation + 2]);
uvec4 pxIndex = uvec4 pxIndex =
uvec4(pointsOffset) + 2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF, uvec4(pointsOffset) + 2 * uvec4(elementIndexs[pLocation] >> 16, elementIndexs[pLocation] & 0xFFFF,
elementIndexs[pLocation + 1] >> 16, elementIndexs[pLocation + 1] & 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; float minDistance = 1e38;
uint lineCount = elementIndexs[contourIndex]; uint lineCount = elementIndexs[contourIndex];
uint widthMapSize = floatBitsToUint(elementData[styleIndex + 1]); uint widthMapSize = floatBitsToUint(elementData[styleIndex + 1]);
uint widthMapIndex = styleIndex + 2;
styleIndex += widthMapSize + 2; styleIndex += widthMapSize + 2;
vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex])); vec4 styleHead = unpackUnorm4x8(floatBitsToUint(elementData[styleIndex]));
float lineType = floor(styleHead.b * 10); 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_++) for (uint contourIterator_ = contourIndex + 1; contourIterator_ < contourIndex + 1 + lineCount; contourIterator_++)
{ {
uint contourIterator = contourIterator_; uint contourIterator = contourIterator_;
mat4x2 p = getPointsByContourIterator(contourIterator, linesOffset, pointsOffset); vec2 lengthRate;
mat4x2 p = getPointsByContourIterator(contourIterator, linesOffset, pointsOffset, lengthRate);
if ((contourIterator == contourIndex + 1)) if ((contourIterator == contourIndex + 1))
{ {
@ -1235,7 +1274,8 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
vec2 tangentBeginNext = vec2(0); vec2 tangentBeginNext = vec2(0);
if (contourIterator + 1 < contourIndex + 1 + lineCount) 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]) if (pNext[0] == p[3])
{ {
@ -1267,13 +1307,15 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
onVeryEnd = true; onVeryEnd = true;
} }
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true); float t;
if (d <= strokeWidth) 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; bool hit = d < minDistance;
hit = hit && hit = hit &&
shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast, strokeWidth); shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast, localWidth);
hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext, strokeWidth); hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext, localWidth);
if (hit) if (hit)
{ {
bool reverse = p[3].y - p[0].y < 0.; 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); minDistance = min(minDistance, d);
hitElement = true; hitElement = true;
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness); drawLine(minDistance / localWidth, styleIndex, elementColor, metallicRoughness);
} }
} }
} }

View File

@ -64,7 +64,13 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vecto
else /// MaterialStyleStroke else /// MaterialStyleStroke
{ {
std::unique_ptr<MaterialStroke> materialStroke; std::unique_ptr<MaterialStroke> materialStroke;
std::map<float, float> widthMap;
uint widthMapSize = floatBitsToUint(encoded[1]); 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; uint headIndex = widthMapSize + 2;
if (encoded[1] < 0) if (encoded[1] < 0)
headIndex = 1; /// 쇗휭앉경긍쯤 headIndex = 1; /// 쇗휭앉경긍쯤
@ -96,6 +102,6 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vecto
break; break;
} }
} }
return std::make_unique<MaterialStyleStroke>(encoded[0], strokeType, endType, std::move(materialStroke)); return std::make_unique<MaterialStyleStroke>(encoded[0], strokeType, endType, std::move(materialStroke), widthMap);
} }
} }

View File

@ -70,6 +70,7 @@ std::vector<glm::vec2> generatePathBuffer(const QPainterPath& path)
pathBuffer.emplace_back(element.x, element.y); pathBuffer.emplace_back(element.x, element.y);
lastPoint = glm::vec2(element.x, element.y); lastPoint = glm::vec2(element.x, element.y);
j++; j++;
k = 0;
break; break;
case QPainterPath::LineToElement: case QPainterPath::LineToElement:
{ {