From 992247617a9947bceb365f7b056fed6ebed3793d Mon Sep 17 00:00:00 2001 From: deanlee Date: Wed, 28 May 2025 05:05:29 +0800 Subject: [PATCH] improve shader --- system/ui/lib/shader_polygon.py | 137 ++++++++++++++------------------ 1 file changed, 60 insertions(+), 77 deletions(-) diff --git a/system/ui/lib/shader_polygon.py b/system/ui/lib/shader_polygon.py index 6f379ea40e..45ce54afef 100644 --- a/system/ui/lib/shader_polygon.py +++ b/system/ui/lib/shader_polygon.py @@ -23,110 +23,93 @@ uniform float gradientStops[8]; uniform int gradientColorCount; vec4 getGradientColor(vec2 pos) { - vec2 gradientDir = gradientEnd - gradientStart; - float gradientLength = length(gradientDir); + vec2 dir = gradientEnd - gradientStart; + float len = length(dir); + if (len < 0.001) return gradientColors[0]; - if (gradientLength < 0.001) return gradientColors[0]; + float t = clamp(dot(pos - gradientStart, dir) / (len * len), 0.0, 1.0); - vec2 normalizedDir = gradientDir / gradientLength; - vec2 pointVec = pos - gradientStart; - float projection = dot(pointVec, normalizedDir); - float t = clamp(projection / gradientLength, 0.0, 1.0); + if (gradientColorCount == 2) { + return mix(gradientColors[0], gradientColors[1], t); + } - for (int i = 0; i < gradientColorCount - 1; i++) { - if (t >= gradientStops[i] && t <= gradientStops[i+1]) { - float segmentT = (t - gradientStops[i]) / (gradientStops[i+1] - gradientStops[i]); - return mix(gradientColors[i], gradientColors[i+1], segmentT); + int low = 0; + int high = gradientColorCount - 1; + while (low < high) { + int mid = (low + high) / 2; + if (t > gradientStops[mid]) low = mid + 1; + else high = mid; } - } - return gradientColors[gradientColorCount-1]; + if (low == 0) return gradientColors[0]; + if (low == gradientColorCount) return gradientColors[gradientColorCount - 1]; + + float segmentT = (t - gradientStops[low - 1]) / (gradientStops[low] - gradientStops[low - 1]); + return mix(gradientColors[low - 1], gradientColors[low], segmentT); } float distanceToEdge(vec2 p) { - float minDist = 1000.0; - - for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { - vec2 edge0 = points[j]; - vec2 edge1 = points[i]; + float minDist = resolution.x; - if (edge0 == edge1) continue; + for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { + vec2 edge0 = points[j]; + vec2 edge1 = points[i]; - vec2 v1 = p - edge0; - vec2 v2 = edge1 - edge0; - float l2 = dot(v2, v2); + vec2 v2 = edge1 - edge0; + float l2 = dot(v2, v2); + if (l2 < 0.0001) continue; - if (l2 < 0.0001) { - float dist = length(v1); - minDist = min(minDist, dist); - continue; + vec2 v1 = p - edge0; + float t = clamp(dot(v1, v2) / l2, 0.0, 1.0); + minDist = min(minDist, length(v1 - t * v2)); } - float t = max(0.0, min(1.0, dot(v1, v2) / l2)); - vec2 projection = edge0 + t * v2; - float dist = length(p - projection); - minDist = min(minDist, dist); - } - - return minDist; + return minDist; } bool isPointInsidePolygon(vec2 p) { - if (pointCount < 3) return false; - - if (pointCount == 3) { - vec2 v0 = points[0]; - vec2 v1 = points[1]; - vec2 v2 = points[2]; + if (pointCount < 3) return false; - float d = (v1.y - v2.y) * (v0.x - v2.x) + (v2.x - v1.x) * (v0.y - v2.y); - if (abs(d) < 0.0001) return false; + if (pointCount == 3) { + vec2 v0 = points[0], v1 = points[1], v2 = points[2]; + float d = (v1.y - v2.y) * (v0.x - v2.x) + (v2.x - v1.x) * (v0.y - v2.y); + if (abs(d) < 0.0001) return false; - float a = ((v1.y - v2.y) * (p.x - v2.x) + (v2.x - v1.x) * (p.y - v2.y)) / d; - float b = ((v2.y - v0.y) * (p.x - v2.x) + (v0.x - v2.x) * (p.y - v2.y)) / d; - float c = 1.0 - a - b; - - return (a >= 0.0 && b >= 0.0 && c >= 0.0); - } - - bool inside = false; - for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { - if (points[i] == points[j]) continue; + float a = ((v1.y - v2.y) * (p.x - v2.x) + (v2.x - v1.x) * (p.y - v2.y)) / d; + float b = ((v2.y - v0.y) * (p.x - v2.x) + (v0.x - v2.x) * (p.y - v2.y)) / d; + float c = 1.0 - a - b; + return a >= 0.0 && b >= 0.0 && c >= 0.0; + } - float dy = points[j].y - points[i].y; - if (abs(dy) < 0.0001) continue; + bool inside = false; + for (int i = 0, j = pointCount - 1; i < pointCount; j = i++) { + vec2 pi = points[i], pj = points[j]; + float dy = pj.y - pi.y; + if (abs(dy) < 1e-4 || pi == pj) continue; - if (((points[i].y > p.y) != (points[j].y > p.y))) { - float x_intersect = points[i].x + (points[j].x - points[i].x) * (p.y - points[i].y) / dy; - if (p.x < x_intersect) { - inside = !inside; - } + if ((pi.y > p.y) != (pj.y > p.y)) { + float x_intersect = pi.x + (pj.x - pi.x) * (p.y - pi.y) / dy; + if (p.x < x_intersect) inside = !inside; + } } - } - return inside; + return inside; } void main() { - vec2 pixel = fragTexCoord * resolution; - bool inside = isPointInsidePolygon(pixel); - float dist = distanceToEdge(pixel); - float aaWidth = 1.0; - float alpha = inside ? - min(1.0, dist / aaWidth) : - max(0.0, 1.0 - dist / aaWidth); - - if (alpha > 0.0) { - vec4 color; - if (useGradient) { - color = getGradientColor(fragTexCoord); - } else { - color = fillColor; + vec2 pixel = fragTexCoord * resolution; + bool inside = isPointInsidePolygon(pixel); + float dist = distanceToEdge(pixel); + float aaWidth = 2.0 / min(resolution.x, resolution.y); + float alpha = inside ? min(1.0, dist / aaWidth) : max(0.0, 1.0 - dist / aaWidth); + + if (alpha == 0.0) { + discard; } + + vec4 color = useGradient ? getGradientColor(pixel) : fillColor; finalColor = vec4(color.rgb, color.a * alpha); - } else { - finalColor = vec4(0.0, 0.0, 0.0, 0.0); - } } + """ # Default vertex shader