shader/rectangle_frag.glsl

Tue, 17 Jun 2025 20:11:53 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 17 Jun 2025 20:11:53 +0200
changeset 158
f650994ec543
parent 157
d6c2f028d8c9
permissions
-rw-r--r--

implement rounded corners

for the time being this should be enough to close issue #384
later we add anti-aliasing, glow effects, etc.

layout(location = 0) out vec4 diffuse;
in vec2 uvcoord;

uniform vec4 color;
uniform vec2 size;
#ifndef FILL
uniform float thickness;
#endif
#ifdef ROUNDED_CORNERS
uniform float radius;
#endif

void main(void) {
#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  // 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 // FILL
#endif // ROUNDED_CORNERS
}

mercurial