2D, 3D, game, games, online game, game development, game engine, programming, OpenGL, Open AI, math, graphics, design, graphic, graphics, game development, game engine, programming, web development, web art, web graphic, arts, tutorial, tutorials,
marți, 19 mai 2026
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:
Posted by
Cătălin George Feștilă
Labels:
2026,
online,
online tool,
shader,
shadertoy,
web,
web development,
website
Abonați-vă la:
Postări (Atom)