Fix:曲线锐角连接时渲染错误

main
wuyize 2023-03-24 13:42:16 +08:00
parent 7667525287
commit 2345cd6758
4 changed files with 68 additions and 52 deletions

View File

@ -1002,7 +1002,8 @@ void nextStyleIndex(inout uint styleIndex)
}
}
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, vec2 tangentBegin, vec2 tangentEndLast)
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, vec2 tangentBegin, vec2 tangentEndLast,
float width)
{
vec2 normal;
if (onVeryBegin)
@ -1018,10 +1019,16 @@ bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, ve
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
normal = normalLast + normalNow;
}
return angleLargeThanPi(normal, localUV - p0);
normal = normalize(normal);
float cosine = dot(normal, -tangentBegin);
vec2 toBegin = localUV - p0;
if (/*cosine > 0 ||*/ dot(toBegin, toBegin) > (width * width / (1 - cosine * cosine)))
return true;
return angleLargeThanPi(normal, toBegin);
}
bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 tangentEnd, vec2 tangentBeginNext)
bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 tangentEnd, vec2 tangentBeginNext,
float width)
{
vec2 normal;
if (onVeryEnd)
@ -1037,7 +1044,12 @@ bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 t
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBeginNext));
normal = normalLast + normalNow;
}
return angleLargeThanPi(localUV - p3, normal);
normal = normalize(normal);
float cosine = dot(normal, tangentEnd);
vec2 toEnd = localUV - p3;
if (/*cosine < 0 ||*/ dot(toEnd, toEnd) > (width * width / (1 - cosine * cosine)))
return true;
return angleLargeThanPi(toEnd, normal);
}
void main()
@ -1097,7 +1109,7 @@ void main()
bool onVeryBegin = false;
bool onVeryEnd = false;
vec2 tangentEndLast = vec2(0);
vec2 tangentFirstBegin;
vec2 tangentFirstBegin = vec2(0);
uint lastHitIndex = 0;
bool lastHitElement = false;
hitElement = false;
@ -1154,7 +1166,11 @@ void main()
else
onVeryEnd = true;
}
vec2 tangentBegin;
if (p[0] != p[1])
tangentBegin = normalize(p[0] - p[1]);
else
tangentBegin = normalize(p[0] - p[2]);
vec2 tangentEnd;
if (p[3] != p[2])
tangentEnd = normalize(p[3] - p[2]);
@ -1166,22 +1182,14 @@ void main()
float localWidth = strokeWidth; // * mix(lengthRate.x, lengthRate.y, t);
if (d <= localWidth)
{
bool onBegin = t<1e-5;
bool onEnd = t>1-1e-5;
//bool onBegin = true;
//bool onEnd = true;
vec2 tangentBegin;
if (p[0] != p[1])
tangentBegin = normalize(p[0] - p[1]);
else
tangentBegin = normalize(p[0] - p[2]);
// bool onBegin = true;
// bool onEnd = true;
bool hit = d < minDistance;
if (onBegin)
hit = hit &&
shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast);
if (onEnd)
hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext);
hit = hit && 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.;
@ -1205,11 +1213,10 @@ void main()
drawLine(minDistance / localWidth, styleIndex, elementColor, metallicRoughness);
}
}
if (pathIndex == 5)
tangentFirstBegin = tangentBegin;
}
tangentEndLast = tangentEnd;
if (pathIndex == 5)
tangentFirstBegin = tangentBegin;
p3Last = p[3];
p2Last = p[2];
onVeryBegin = false;

View File

@ -1035,7 +1035,8 @@ void drawLine(in float d, uint styleHeadIndex, out vec4 elementColor, out vec2 m
}
}
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, vec2 tangentBegin, vec2 tangentEndLast)
bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, vec2 tangentBegin, vec2 tangentEndLast,
float width)
{
vec2 normal;
if (onVeryBegin)
@ -1051,10 +1052,16 @@ bool shouldFillBeginCap(vec2 localUV, bool onVeryBegin, int endType, vec2 p0, ve
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBegin));
normal = normalLast + normalNow;
}
return angleLargeThanPi(normal, localUV - p0);
normal = normalize(normal);
float cosine = dot(normal, -tangentBegin);
vec2 toBegin = localUV - p0;
if (/*cosine > 0 ||*/ dot(toBegin, toBegin) > (width * width / (1 - cosine * cosine)))
return true;
return angleLargeThanPi(normal, toBegin);
}
bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 tangentEnd, vec2 tangentBeginNext)
bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 tangentEnd, vec2 tangentBeginNext,
float width)
{
vec2 normal;
if (onVeryEnd)
@ -1070,7 +1077,12 @@ bool shouldFillEndCap(vec2 localUV, bool onVeryEnd, int endType, vec2 p3, vec2 t
vec2 normalNow = normalize(mat2(0, 1, -1, 0) * (-tangentBeginNext));
normal = normalLast + normalNow;
}
return angleLargeThanPi(localUV - p3, normal);
normal = normalize(normal);
float cosine = dot(normal, tangentEnd);
vec2 toEnd = localUV - p3;
if (/*cosine < 0 ||*/ dot(toEnd, toEnd) > (width * width / (1 - cosine * cosine)))
return true;
return angleLargeThanPi(toEnd, normal);
}
bool fillElement(vec2 localUV, uint contourIndex, uint linesOffset, uint pointsOffset, uint styleIndex,
@ -1231,29 +1243,24 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
debugBegin = 1;
}
vec2 tangentBegin;
if (p[0] != p[1])
tangentBegin = normalize(p[0] - p[1]);
else
tangentBegin = normalize(p[0] - p[2]);
vec2 tangentEnd;
if (p[3] != p[2])
tangentEnd = normalize(p[3] - p[2]);
else
tangentEnd = normalize(p[3] - p[1]);
float d = cubic_bezier_dis(localUV, p[0], p[1], p[2], p[3], true);
if (d <= strokeWidth)
{
bool onBegin =
distance(localUV, p[0]) <= strokeWidth; //&& (p3Last == p[0] || contourIterator == contourIndex + 1);
bool onEnd = distance(localUV, p[3]) <= strokeWidth;
vec2 tangentBegin;
vec2 tangentEnd;
if (p[0] != p[1])
tangentBegin = normalize(p[0] - p[1]);
else
tangentBegin = normalize(p[0] - p[2]);
if (p[3] != p[2])
tangentEnd = normalize(p[3] - p[2]);
else
tangentEnd = normalize(p[3] - p[1]);
bool hit = d < minDistance;
if (onBegin)
hit = hit && shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast);
if (onEnd)
hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext);
hit = hit &&
shouldFillBeginCap(localUV, onVeryBegin, endType, p[0], tangentBegin, tangentEndLast, strokeWidth);
hit = hit && shouldFillEndCap(localUV, onVeryEnd, endType, p[3], tangentEnd, tangentBeginNext, strokeWidth);
if (hit)
{
@ -1269,10 +1276,10 @@ bool strokeElement(vec2 localUV, uint contourIndex, uint linesOffset, uint point
drawLine(minDistance / strokeWidth, styleIndex, elementColor, metallicRoughness);
}
}
tangentEndLast = tangentEnd;
if (contourIterator == contourIndex + 1)
tangentFirstBegin = tangentBegin;
}
tangentEndLast = tangentEnd;
if (contourIterator == contourIndex + 1)
tangentFirstBegin = tangentBegin;
p3Last = p[3];
p2Last = p[2];
onVeryBegin = false;

View File

@ -46,7 +46,7 @@ bool Renderer::Material::operator==(const Material& m) const
std::pair<glm::vec4, glm::vec2> Renderer::Material::toVec() const
{
return { glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF()), glm::vec2(metallicF(), roughnessF())};
return { glm::vec4(color.redF(), color.greenF(), color.blueF(), color.alphaF()), glm::vec2(metallicF(), roughnessF()) };
}
std::unique_ptr<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vector<GLfloat>& encoded)
@ -66,6 +66,8 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vecto
std::unique_ptr<MaterialStroke> materialStroke;
uint widthMapSize = floatBitsToUint(encoded[1]);
uint headIndex = widthMapSize + 2;
if (encoded[1] < 0)
headIndex = 1; /// 쇗휭앉경긍쯤
uint headUint = floatBitsToUint(encoded[headIndex]);
vec4 head = unpackUnorm4x8(headUint);
StrokeType strokeType = (StrokeType)floor(head.b * 10);
@ -74,7 +76,7 @@ std::unique_ptr<MaterialStyle> Renderer::MaterialStyle::decoded(const std::vecto
{
/// Plain
case 0: {
materialStroke = std::make_unique<StrokePlain>(Material(glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[headIndex+1])), glm::vec2(head.r, head.g)));
materialStroke = std::make_unique<StrokePlain>(Material(glm::unpackUnorm4x8(glm::floatBitsToUint(encoded[headIndex + 1])), glm::vec2(head.r, head.g)));
break;
}
/// RadialGradient

View File

@ -220,7 +220,7 @@ namespace UnitTest
{1.00, Material{QColor(58,64,151)}}
};
return { BaseStyle(std::make_shared<TransformStyle>(),
std::make_shared<MaterialStyleStroke>(10, StrokeType::kBothSides, StrokeEndType::kClosed,
std::make_shared<MaterialStyleStroke>(10, StrokeType::kLeftSide, StrokeEndType::kClosed,
std::make_shared<StrokeRadialGradient>(materialMap, false))) };
}
} style;