Rectangular selection box

CC0

Shader code
shader_type canvas_item;

uniform float border_width = 0.02; // Border thickness in UV space
uniform float blur = 0.01; // Blur amount for all edges (0.0 = sharp, >0.0 = softer)
uniform float corner_radius = 0.05; // Corner radius in UV space (0.0 = sharp, >0.0 = rounded)
uniform float dash_length = 0.1; // Length of each dash in UV space
uniform float dash_gap = 0.05; // Gap between dashes in UV space
uniform float speed = 1.0; // Animation speed
uniform vec4 border_color : source_color = vec4(1.0, 1.0, 1.0, 1.0); // Border color

void fragment() {
    vec2 uv = UV;
    vec2 center = vec2(0.5, 0.5);
    vec2 size = vec2(0.5, 0.5); // Rectangle half-size (width, height) in UV space

    // Calculate signed distance to a rounded rectangle
    vec2 d = abs(uv - center) - size + vec2(corner_radius);
    float dist = min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - corner_radius;

    // Calculate perimeter position for continuous dashing
    vec2 pos = uv - center;
    float t = 0.0;
    float perimeter = 2.0 * (size.x + size.y); // Approximate perimeter (adjusted for rounding)

    // Determine the segment and compute normalized perimeter position
    vec2 abs_pos = abs(pos);
    float u = 0.0;
    if (abs_pos.x > abs_pos.y) {
        if (pos.x > 0.0) {
            // Right edge
            u = (pos.y + size.y) + size.x;
        } else {
            // Left edge
            u = (size.y - pos.y) + 3.0 * size.x;
        }
    } else {
        if (pos.y > 0.0) {
            // Top edge
            u = (size.x - pos.x);
        } else {
            // Bottom edge
            u = (pos.x + size.x) + 2.0 * size.x;
        }
    }

    // Adjust perimeter for rounded corners (approximation)
    perimeter += 2.0 * 3.141592 * corner_radius * 0.5; // Add corner arc lengths
    u = fract(u / perimeter + TIME * speed);

    // Dash pattern
    float dash_cycle = dash_length + dash_gap;
    float pattern_pos = mod(u * perimeter, dash_cycle);

    // Apply blur to all edges of the border
    float edge_alpha = smoothstep(border_width + blur, border_width - blur, abs(dist));

    // Ensure the border is fully blurred across its width
    float border_mask = step(abs(dist), border_width + blur);

    // Combine dash pattern and blurred border
    if (pattern_pos < dash_length && border_mask > 0.0) {
        COLOR.rgb = border_color.rgb;
        COLOR.a = border_color.a * edge_alpha;
    } else {
        COLOR.a = 0.0; // Transparent for gaps and outside border
    }
}
Tags
rect, selection
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

Selection Box

Animated selection rectangle (Marching ants)

Selection Blur

guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments