From b4e8ae9731eca175cd4e6e75a20da87ff86eb91f Mon Sep 17 00:00:00 2001 From: Matt Kosarek Date: Tue, 3 Feb 2026 08:13:30 -0500 Subject: feature: improve snowflake renderer --- themes/src/_shaders/snowflake.frag | 73 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 themes/src/_shaders/snowflake.frag (limited to 'themes/src/_shaders/snowflake.frag') diff --git a/themes/src/_shaders/snowflake.frag b/themes/src/_shaders/snowflake.frag new file mode 100644 index 0000000..d887cf5 --- /dev/null +++ b/themes/src/_shaders/snowflake.frag @@ -0,0 +1,73 @@ +// Procedural star fragment shader +varying lowp vec2 vUV; +varying lowp float vSeed; +varying lowp float vScale; + +const lowp float PI = 3.14159265359; + +// Simple hash function for deterministic randomness +lowp float hash(lowp float n) { + return fract(sin(n) * 43758.5453123); +} + +// Generate star pattern procedurally +lowp float starPattern(lowp vec2 uv) { + lowp float dist = length(uv); + lowp float angle = atan(uv.y, uv.x); + + // Number of star points (4 or 5) + lowp float numPoints = 4.0 + floor(hash(vSeed) * 2.0); + + // Create sharp star with triangular points + lowp float angleStep = 2.0 * PI / numPoints; + lowp float currentAngle = mod(angle + PI / numPoints, angleStep) - angleStep * 0.5; + + // Create triangular points - distance from center to edge varies linearly with angle + lowp float normalizedAngle = abs(currentAngle) / (angleStep * 0.5); + + // Outer tip radius and inner valley radius + lowp float tipRadius = 0.5; + lowp float valleyRadius = 0.15; + + // Linear interpolation creates sharp triangular points + lowp float rayEdge = mix(tipRadius, valleyRadius, normalizedAngle); + + // Hard cutoff for sharp edges + lowp float star = step(dist, rayEdge); + + return star; +} + +void main() { + lowp float pattern = starPattern(vUV); + + // Color variation based on seed - white and blue tints + lowp float colorVar = hash(vSeed * 3.0); + lowp vec3 starColor; + + if (colorVar < 0.5) { + // Pure white + starColor = vec3(1.0, 1.0, 1.0); + } else if (colorVar < 0.75) { + // Light blue tint + starColor = vec3(0.9, 0.95, 1.0); + } else { + // Stronger blue tint + starColor = vec3(0.85, 0.92, 1.0); + } + + // Scale alpha based on size - smaller stars are more transparent + // Normalize scale from range [16, 48] to [0, 1] + lowp float sizeRatio = (vScale - 16.0) / (48.0 - 16.0); + // Map to alpha range [0.3, 1.0] - smaller stars at 30% opacity, larger at 100% + lowp float alpha = mix(0.3, 1.0, sizeRatio); + + lowp vec4 color = vec4(starColor, pattern * alpha); + + // Discard fully transparent pixels for performance + if (color.a < 0.01) { + discard; + } + + gl_FragColor = color; +} -- cgit v1.2.1