Pages

marți, 19 mai 2026

News : Neverwinter | New Module "Biting Cold" Trailer

News : Sid Meier's Civilization VII | Test of Time Trailer

News : Dune: Awakening - The Water Wars DLC Launch Trailer

News : Farming Simulator 26 Now Available | Launch Trailer

Shadertoy: buttons with effect - 001.

A simple effect on buttons with a little help of artificial intelligence.
// with a little help with artificial inteligence
// ============================================================================
// HELPER FUNCTIONS
// ============================================================================

// Matrix for 2D rotation (useful if you want to rotate internal effects)
mat2 rotate2d(float angle){
    return mat2(
        cos(angle), -sin(angle),
        sin(angle), cos(angle)
    );
}

// Signed Distance Field (SDF) for a rectangle with independent corner radii
// r.x = Top-Right, r.y = Bottom-Right, r.z = Top-Left, r.w = Bottom-Left
float sdRoundedBox( in vec2 p, in vec2 b, in vec4 r )
{
    r.xy = (p.x > 0.0) ? r.xy : r.zw;
    r.x  = (p.y > 0.0) ? r.x  : r.y;
    vec2 q = abs(p) - b + r.x;
    return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
}

// ============================================================================
// MAIN SHADERTOY ENTRY POINT
// ============================================================================
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // 1. Normalize coordinates (from 0.0 to 1.0)
    vec2 uv = fragCoord / iResolution.xy;
    float ratio = iResolution.x / iResolution.y;
    
    // 2. Define the Color Palette (Sci-Fi / Neon Theme)
    vec3 backgroundColor = vec3(0.06, 0.06, 0.09); // Dark background
    vec3 buttonBaseColor = vec3(0.05, 0.18, 0.35); // Base body fill color
    vec3 neonBlue        = vec3(0.27, 0.67, 1.0);  // Sharp border stroke
    vec3 aquaGlow        = vec3(0.0, 0.95, 1.0);   // Outer aura glow
    
    vec3 finalColor = backgroundColor;

    // 3. Split the screen into a 2x3 grid (2 columns, 3 rows) to show 6 variations
    vec2 gridSize = vec2(2.0, 3.0);
    vec2 gridId = floor(uv * gridSize); 
    
    // Localize UV coordinates inside each grid cell, and center the origin (0,0)
    vec2 localUV = fract(uv * gridSize) - 0.5;
    
    // Adjust aspect ratio locally for the 2x3 grid mapping
    float localRatio = (iResolution.x / gridSize.x) / (iResolution.y / gridSize.y);
    localUV.x *= localRatio;

    // 4. Define Button Size (scaled for the 2x3 grid layout)
    vec2 buttonSize = vec2(0.38, 0.13); 
    
    // 5. Initialize the corner radii vector
    // Format: vec4(Top-Right, Bottom-Right, Top-Left, Bottom-Left)
    vec4 cornerRadii = vec4(0.0);

    // 6. Assign a different combination to each grid area (Rows from bottom=0 to top=2)
    if (gridId.y == 2.0) // === TOP ROW ===
    {
        if (gridId.x == 0.0) {
            // [TOP-LEFT]: All corners rounded equally (Standard Pill Button)
            cornerRadii = vec4(0.07, 0.07, 0.07, 0.07);
        } else {
            // [TOP-RIGHT]: Sharp rectangular button (No rounding)
            cornerRadii = vec4(0.00, 0.00, 0.00, 0.00);
        }
    }
    else if (gridId.y == 1.0) // === MIDDLE ROW (THE LEAF DIAGONALS) ===
    {
        if (gridId.x == 0.0) {
            // [MIDDLE-LEFT]: Leaf Style 1 (Top-Right and Bottom-Left rounded)
            cornerRadii = vec4(0.15, 0.00, 0.00, 0.15);
        } else {
            // [MIDDLE-RIGHT]: Leaf Style 2 (Top-Left and Bottom-Right rounded)
            cornerRadii = vec4(0.00, 0.15, 0.15, 0.00);
        }
    }
    else if (gridId.y == 0.0) // === BOTTOM ROW ===
    {
        if (gridId.x == 0.0) {
            // [BOTTOM-LEFT]: Tab Style (Top corners rounded only)
            cornerRadii = vec4(0.08, 0.00, 0.08, 0.00);
        } else {
            // [BOTTOM-RIGHT]: Asymmetric single corner rounded
            cornerRadii = vec4(0.00, 0.00, 0.16, 0.00);
        }
    }

    // 7. Calculate the distance field for the current button shape
    float d = sdRoundedBox(localUV, buttonSize, cornerRadii);

    // 8. Render Button Body (Fill with a clean vertical light-to-dark gradient)
    float fillMask = smoothstep(0.003, 0.0, d); 
    vec3 buttonBody = buttonBaseColor * (1.1 - (localUV.y + 0.5) * 0.4); 
    finalColor = mix(finalColor, buttonBody, fillMask);

    // 9. Render Sharp Neon Border (Stroke)
    float borderThickness = 0.004;
    float borderMask = smoothstep(borderThickness, 0.0, abs(d)) * smoothstep(d, d + 0.004, 0.0);
    finalColor += borderMask * neonBlue * 1.8;

    // 10. Render Dynamic External Glow Effect (Pulses over time using iTime)
    float pulse = sin(iTime * 3.5) * 0.12 + 0.88; 
    float glowIntensity = exp(-max(d, 0.0) * 28.0) * pulse;
    finalColor += glowIntensity * aquaGlow * 0.5 * (1.0 - fillMask); 

    // 11. Render Internal Scanline Laser Effect
    if (d < 0.0) 
    {
        // Laser position sweeps horizontally across the local cell width
        float scanSpeed = 0.5;
        float scanX = fract(iTime * scanSpeed) * 2.2 - 1.1; 
        
        // Render the vertical beam profile
        float scanlineWidth = 0.07;
        float scanline = smoothstep(scanlineWidth, 0.0, abs((localUV.x / localRatio) - scanX));
        
        // Add reflection overlay inside the button
        finalColor += scanline * neonBlue * 0.45;
        
        // Add inner vignette shadow
        float innerShadow = smoothstep(-0.06, 0.0, d);
        finalColor -= vec3(0.15) * innerShadow;
    }

    // 12. Draw grid lines to separate the 6 showcase zones clean
    float gridLines = smoothstep(0.004, 0.0, abs(uv.x - 0.5)) + 
                      smoothstep(0.004, 0.0, abs(uv.y - 0.3333)) + 
                      smoothstep(0.004, 0.0, abs(uv.y - 0.6666));
    finalColor = mix(finalColor, vec3(0.15, 0.15, 0.2), gridLines * 0.4);

    // 13. Output processed pixels to screen
    fragColor = vec4(finalColor, 1.0);
}
Let's see the result: