shader/rectangle_frag.glsl

changeset 158
f650994ec543
parent 157
d6c2f028d8c9
--- a/shader/rectangle_frag.glsl	Tue Jun 17 19:00:20 2025 +0200
+++ b/shader/rectangle_frag.glsl	Tue Jun 17 20:11:53 2025 +0200
@@ -6,15 +6,91 @@
 #ifndef FILL
 uniform float thickness;
 #endif
+#ifdef ROUNDED_CORNERS
+uniform float radius;
+#endif
 
 void main(void) {
-#ifdef FILL
+#ifdef ROUNDED_CORNERS
+    // Calculate distances from each corner
+    vec2 corner_distances[4];
+    corner_distances[0] = uvcoord - vec2(radius, radius);                         // top-left
+    corner_distances[1] = uvcoord - vec2(size.x - radius, radius);                // top-right
+    corner_distances[2] = uvcoord - vec2(radius, size.y - radius);                // bottom-left
+    corner_distances[3] = uvcoord - vec2(size.x - radius, size.y - radius);       // bottom-right
+
+    // Check if we're in a corner region
+    bool in_corner_region = false;
+    int corner_idx = -1;
+
+    for (int i = 0; i < 4; i++) {
+        vec2 test_point = corner_distances[i];
+        vec2 corner_test = vec2(0.0);
+
+        if (i == 0 && test_point.x < 0.0 && test_point.y < 0.0) { // top-left
+            corner_test = test_point;
+            corner_idx = i;
+            in_corner_region = true;
+            break;
+        } else if (i == 1 && test_point.x > 0.0 && test_point.y < 0.0) { // top-right
+            corner_test = test_point;
+            corner_idx = i;
+            in_corner_region = true;
+            break;
+        } else if (i == 2 && test_point.x < 0.0 && test_point.y > 0.0) { // bottom-left
+            corner_test = test_point;
+            corner_idx = i;
+            in_corner_region = true;
+            break;
+        } else if (i == 3 && test_point.x > 0.0 && test_point.y > 0.0) { // bottom-right
+            corner_test = test_point;
+            corner_idx = i;
+            in_corner_region = true;
+            break;
+        }
+    }
+
+    #ifdef FILL
+    // For filled rectangle with rounded corners
+    if (in_corner_region) {
+        float dist = length(corner_distances[corner_idx]);
+        if (dist > radius) {
+            discard; // Outside the rounded corner
+        }
+    } else if (uvcoord.x < 0.0 || uvcoord.y < 0.0 || uvcoord.x > size.x || uvcoord.y > size.y) {
+        discard; // Outside the rectangle
+    }
     diffuse = color;
-#else
+    #else  // no FILL
+    // For outlined rectangle with rounded corners
+    if (in_corner_region) {
+        float dist = length(corner_distances[corner_idx]);
+        if (dist > radius) {
+            discard; // Outside the rounded corner
+        } else if (dist < radius - thickness) {
+            discard; // Inside the outline
+        }
+        diffuse = color;
+    } else if (any(lessThan(uvcoord, vec2(thickness))) || any(greaterThan(uvcoord, size - thickness))) {
+        // On a straight edge
+        if (uvcoord.x >= 0.0 && uvcoord.y >= 0.0 && uvcoord.x <= size.x && uvcoord.y <= size.y) {
+            diffuse = color;
+        } else {
+            discard;
+        }
+    } else {
+        discard; // Inside the outline
+    }
+    #endif // FILL
+#else // no ROUNDED_CORNERS
+    #ifdef FILL
+    diffuse = color;
+    #else // no FILL
     if (any(notEqual(1.0-step(thickness, uvcoord)+step(size-thickness, uvcoord), vec2(0.0)))) {
         diffuse = color;
     } else {
         discard;
     }
-#endif
+    #endif // FILL
+#endif // ROUNDED_CORNERS
 }

mercurial