Files
video-shader-toys/shaders/dvd-bounce/shader.slang
2026-05-02 19:29:18 +10:00

117 lines
4.2 KiB
Plaintext

float sdBox(float2 p, float2 b)
{
float2 d = abs(p) - b;
return length(max(d, float2(0.0, 0.0))) + min(max(d.x, d.y), 0.0);
}
float sdRoundedBox(float2 p, float2 b, float r)
{
return sdBox(p, b - r) - r;
}
float sdSegment(float2 p, float2 a, float2 b)
{
float2 pa = p - a;
float2 ba = b - a;
float h = saturate(dot(pa, ba) / max(dot(ba, ba), 0.0001));
return length(pa - ba * h);
}
float pingPong(float x, float lengthValue)
{
float safeLength = max(lengthValue, 0.0001);
float period = safeLength * 2.0;
float wrapped = x - floor(x / period) * period;
return wrapped <= safeLength ? wrapped : (period - wrapped);
}
float3 hsvToRgb(float3 hsv)
{
float3 p = abs(frac(hsv.x + float3(0.0, 0.6666667, 0.3333333)) * 6.0 - 3.0);
float3 rgb = saturate(p - 1.0);
return hsv.z * lerp(float3(1.0, 1.0, 1.0), rgb, hsv.y);
}
float letterD(float2 p, float scale)
{
float2 offset = p;
float stem = sdBox(offset + float2(scale * 0.18, 0.0), float2(scale * 0.065, scale * 0.47));
float outer = sdRoundedBox(offset + float2(scale * 0.03, 0.0), float2(scale * 0.30, scale * 0.47), scale * 0.23);
float inner = sdRoundedBox(offset + float2(scale * 0.11, 0.0), float2(scale * 0.15, scale * 0.24), scale * 0.12);
float bowl = max(outer, -inner);
return min(stem, bowl);
}
float letterV(float2 p, float scale)
{
float leftStroke = sdSegment(p, float2(-scale * 0.30, -scale * 0.48), float2(0.0, scale * 0.48)) - scale * 0.085;
float rightStroke = sdSegment(p, float2(scale * 0.30, -scale * 0.48), float2(0.0, scale * 0.48)) - scale * 0.085;
return min(leftStroke, rightStroke);
}
float logoLetters(float2 p, float scale)
{
float left = letterD(p + float2(scale * 0.92, 0.0), scale);
float middle = letterV(p, scale);
float right = letterD(p - float2(scale * 0.92, 0.0), scale);
return min(left, min(middle, right));
}
float4 shadeVideo(ShaderContext context)
{
float2 resolution = max(context.outputResolution, float2(1.0, 1.0));
float minDimension = min(resolution.x, resolution.y);
float safeScale = max(logoScale, 0.05);
float2 logoHalfSize = float2(minDimension * safeScale * 0.82, minDimension * safeScale * 0.28);
float2 paddingPx = float2(minDimension * max(edgePadding, 0.0), minDimension * max(edgePadding, 0.0));
float2 minCenterPx = logoHalfSize + paddingPx;
float2 maxCenterPx = resolution - logoHalfSize - paddingPx;
float2 travelPx = max(maxCenterPx - minCenterPx, float2(1.0, 1.0));
float2 velocityPx = float2(
max(20.0, bounceSpeed * minDimension * 1.00),
max(24.0, bounceSpeed * minDimension * 0.77));
float2 motionPx = context.time * velocityPx;
float2 centerPx = minCenterPx + float2(
pingPong(motionPx.x, travelPx.x),
pingPong(motionPx.y, travelPx.y));
int xHits = int(floor(motionPx.x / max(travelPx.x, 1.0)));
int yHits = int(floor(motionPx.y / max(travelPx.y, 1.0)));
int totalHits = max(0, xHits + yHits);
float hue = frac(0.09 + float(totalHits) * 0.173);
float3 badgeColor = hsvToRgb(float3(hue, 0.86, 1.0));
float3 glowColor = hsvToRgb(float3(frac(hue + 0.06), 0.72, 1.0));
float2 fragPx = context.uv * resolution;
float2 p = fragPx - centerPx;
float badgeDist = sdRoundedBox(p, logoHalfSize, logoHalfSize.y * 0.42);
float innerBadgeDist = sdRoundedBox(p, logoHalfSize - float2(minDimension * 0.012, minDimension * 0.012), logoHalfSize.y * 0.34);
float letterScale = logoHalfSize.y * 0.88;
float letterDist = logoLetters(p, letterScale);
float aa = 1.5;
float badgeMask = 1.0 - smoothstep(0.0, aa, badgeDist);
float rimMask = 1.0 - smoothstep(0.0, aa, abs(badgeDist + minDimension * 0.01));
float innerShade = 1.0 - smoothstep(0.0, aa, innerBadgeDist);
float lettersMask = 1.0 - smoothstep(0.0, aa, letterDist);
float glowMask = (1.0 - smoothstep(0.0, minDimension * 0.04, badgeDist)) * glowAmount;
float3 color = float3(0.0, 0.0, 0.0);
color += glowColor * glowMask * 0.55;
color = lerp(color, badgeColor * 0.95, badgeMask);
color = lerp(color, badgeColor * 0.55 + float3(0.08, 0.08, 0.1), innerShade * 0.35);
color = lerp(color, float3(1.0, 1.0, 1.0), rimMask * 0.8);
color = lerp(color, float3(0.98, 0.99, 1.0), lettersMask);
float alpha = max(badgeMask, glowMask * 0.45);
alpha = max(alpha, lettersMask);
alpha *= saturate(baseAlpha);
return float4(saturate(color), saturate(alpha));
}