← back to Star Burstcompare with ground truth →
model output
Gemini 3 Flash Preview
Star Burst
A 0.37T 0.17
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Light Rays Animation</title>
7 <style>
8 body, html {
9 margin: 0;
10 padding: 0;
11 width: 100%;
12 height: 100%;
13 overflow: hidden;
14 background-color: #050a10;
15 }
16
17 canvas {
18 display: block;
19 }
20
21 /* Subtle vignette to match the video background */
22 .vignette {
23 position: fixed;
24 top: 0;
25 left: 0;
26 width: 100%;
27 height: 100%;
28 background: radial-gradient(circle, transparent 20%, rgba(0, 0, 0, 0.4) 100%);
29 pointer-events: none;
30 z-index: 10;
31 }
32 </style>
33</head>
34<body>
35 <div class="vignette"></div>
36 <canvas id="canvas"></canvas>
37
38 <script>
39 const canvas = document.getElementById('canvas');
40 const ctx = canvas.getContext('2d');
41
42 let width, height, centerX, centerY;
43 const particleCount = 150;
44 const particles = [];
45 const colors = [
46 '#ffffff', // White
47 '#00f2ff', // Bright Cyan
48 '#00d2ff', // Light Blue
49 '#3a7bd5', // Blue
50 '#ffffff'
51 ];
52
53 // Particle configuration
54 const speed = 15;
55 const focalLength = 400;
56
57 function init() {
58 resize();
59 for (let i = 0; i < particleCount; i++) {
60 particles.push(new Particle());
61 }
62 animate();
63 }
64
65 function resize() {
66 width = canvas.width = window.innerWidth;
67 height = canvas.height = window.innerHeight;
68 centerX = width / 2;
69 centerY = height / 2;
70 }
71
72 window.addEventListener('resize', resize);
73
74 class Particle {
75 constructor() {
76 this.reset();
77 // Randomize start Z so they don't all appear at once
78 this.z = Math.random() * focalLength * 2;
79 }
80
81 reset() {
82 // Spread particles in a 3D sphere/cone space
83 this.x = (Math.random() - 0.5) * 2000;
84 this.y = (Math.random() - 0.5) * 2000;
85 this.z = focalLength * 2;
86
87 this.color = colors[Math.floor(Math.random() * colors.length)];
88 this.lineWidth = Math.random() * 2 + 1;
89
90 // Track previous Z for the "streak" effect
91 this.prevZ = this.z;
92 }
93
94 update() {
95 this.prevZ = this.z;
96 this.z -= speed;
97
98 // Reset when particle passes "behind" the camera or gets too close
99 if (this.z <= 1) {
100 this.reset();
101 }
102 }
103
104 draw() {
105 // Project 3D coordinates to 2D
106 const scale = focalLength / this.z;
107 const x2d = centerX + this.x * scale;
108 const y2d = centerY + this.y * scale;
109
110 const prevScale = focalLength / this.prevZ;
111 const prevX2d = centerX + this.x * prevScale;
112 const prevY2d = centerY + this.y * prevScale;
113
114 // Fade in as they move closer to prevent sudden pops
115 const opacity = Math.min(1, (focalLength * 2 - this.z) / 200);
116
117 ctx.beginPath();
118 ctx.strokeStyle = this.color;
119 ctx.globalAlpha = opacity;
120 ctx.lineWidth = this.lineWidth * scale * 0.5;
121 ctx.lineCap = 'round';
122
123 ctx.moveTo(prevX2d, prevY2d);
124 ctx.lineTo(x2d, y2d);
125 ctx.stroke();
126 }
127 }
128
129 function drawCentralGlow() {
130 ctx.save();
131 ctx.globalCompositeOperation = 'lighter';
132
133 // Core white glow
134 const grad1 = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, 15);
135 grad1.addColorStop(0, 'rgba(255, 255, 255, 0.8)');
136 grad1.addColorStop(1, 'rgba(0, 242, 255, 0)');
137 ctx.fillStyle = grad1;
138 ctx.beginPath();
139 ctx.arc(centerX, centerY, 15, 0, Math.PI * 2);
140 ctx.fill();
141
142 // Large cyan soft glow
143 const grad2 = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, 60);
144 grad2.addColorStop(0, 'rgba(0, 242, 255, 0.3)');
145 grad2.addColorStop(1, 'rgba(0, 242, 255, 0)');
146 ctx.fillStyle = grad2;
147 ctx.beginPath();
148 ctx.arc(centerX, centerY, 60, 0, Math.PI * 2);
149 ctx.fill();
150
151 ctx.restore();
152 }
153
154 function animate() {
155 // Clear screen with a slight fade to create motion blur trails
156 ctx.fillStyle = 'rgba(5, 10, 16, 0.4)';
157 ctx.fillRect(0, 0, width, height);
158
159 // Additive blending for the "glow" look of the streaks
160 ctx.globalCompositeOperation = 'lighter';
161
162 particles.forEach(p => {
163 p.update();
164 p.draw();
165 });
166
167 // Reset blending and draw the core center glow
168 ctx.globalAlpha = 1;
169 drawCentralGlow();
170
171 requestAnimationFrame(animate);
172 }
173
174 init();
175 </script>
176</body>
177</html>