47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
22:47Mistral Large 4 Is Cheap. But Is It Good Enough to Compete?
Oct 6, 2026 · YouTube
16:54Stealth Union Alpha: Is this another cheap GPT model? (better than Luna, cheaper than Terra?)
Sep 16, 2026 · YouTube
16:45DeepSeek V4.1 Flash Is Shockingly Good for the Price
Sep 10, 2026 · YouTube
17:14How much better is GPT-6 Astra over Claude Opus 5? Real Website and Coding Tests
Sep 5, 2026 · YouTube
29:13Implementing a multiplayer game with GPT-6 Astra (+ Gemini 3.8, Opus 5, Sol Pro)
Sep 5, 2026 · YouTube
19:42Meta Muse Spark 1.3 Review: A Huge Leap Forward
Sep 2, 2026 · YouTube
17:31Testing Gemini 3.8 Flash on Real Coding Challenges (vs. other models)
Sep 2, 2026 · YouTube
You are a graphics engineer who has spent a lot of time finding out why things are slow.
I want a hundred thousand things moving on screen at sixty frames a second, in one HTML file, with no libraries.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.One paragraph, before the file. Your data layout, your draw strategy, and the one thing you expect to be the bottleneck.
The single fenced html block.
This is the section I care most about. Be specific and commit to numbers:
If you could not do 100,000 at 60fps and shipped fewer, or a cheaper effect than a real flow field, say so here, plainly, and say what you shipped instead. Write Nothing dropped. if you delivered the brief in full.
I am going to open the file and read the FPS counter.
Then I am going to compare it against your prediction. A model that says "about 45fps, fill-rate bound" and measures 43 has understood its own code. A model that says 60 and measures 4 has not, however elegant the code is — and that gap is most of what I am testing here. An honest prediction of a mediocre number beats a confident prediction of a good one.
I use raw WebGL point primitives for drawing and Structure-of-Arrays typed arrays for state: one interleaved Float32Array of positions plus separate velocity arrays. Each frame I update all 100,000 particles in a tight JavaScript loop, sampling a 90×60 vector field that is regenerated from time-dependent trigonometric functions, then upload positions with bufferSubData and draw all points in one drawArrays call. The expected bottleneck is the per-particle CPU update and field sampling, not GPU fill rate.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Flow Field Particles</title>
<style>
html, body { margin: 0; height: 100%; background: #f2f4f7; font-family: system-ui, sans-serif; overflow: hidden; }
canvas { display: block; margin: 0 auto; background: #f2f4f7; }
#hud { position: fixed; left: 12px; top: 12px; color: #111; font: 14px/1.4 monospace; background: rgba(255,255,255,.75); padding: 6px 8px; border-radius: 6px; }
</style>
</head>
<body>
<canvas id="c" width="900" height="600"></canvas>
<div id="hud"><span id="fps">--</span> fps · <span id="count">0</span> particles</div>
<script>
const W = 900, H = 600;
const canvas = document.getElementById('c');
canvas.width = W;
canvas.height = H;
const gl = canvas.getContext('webgl', {
alpha: false, antialias: false, depth: false, stencil: false, preserveDrawingBuffer: false
});
if (!gl) {
document.body.textContent = 'WebGL unavailable';
throw new Error('WebGL unavailable');
}
function makeShader(type, src) {
const s = gl.createShader(type);
gl.shaderSource(s, src);
gl.compileShader(s);
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
console.error(gl.getShaderInfoLog(s));
throw new Error('Shader compile failed');
}
return s;
}
const vsSource = `
attribute vec2 a_pos;
uniform vec2 u_res;
void main() {
vec2 clip = (a_pos / u_res) * 2.0 - 1.0;
gl_Position = vec4(clip.x, -clip.y, 0.0, 1.0);
gl_PointSize = 2.0;
}
`;
const fsSource = `
precision mediump float;
uniform vec3 u_color;
void main() {
vec2 c = gl_PointCoord - vec2(0.5);
if (dot(c, c) > 0.25) discard;
gl_FragColor = vec4(u_color, 0.55);
}
`;
const program = gl.createProgram();
gl.attachShader(program, makeShader(gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, makeShader(gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(gl.getProgramInfoLog(program));
throw new Error('Program link failed');
}
gl.useProgram(program);
const uRes = gl.getUniformLocation(program, 'u_res');
const uColor = gl.getUniformLocation(program, 'u_color');
gl.uniform2f(uRes, W, H);
gl.uniform3f(uColor, 0.08, 0.12, 0.20);
const PARTICLE_COUNT = 100000;
const pos = new Float32Array(PARTICLE_COUNT * 2);
const vx = new Float32Array(PARTICLE_COUNT);
const vy = new Float32Array(PARTICLE_COUNT);
for (let i = 0; i < PARTICLE_COUNT; i++) {
pos[i * 2] = Math.random() * W;
pos[i * 2 + 1] = Math.random() * H;
vx[i] = (Math.random() - 0.5) * 0.5;
vy[i] = (Math.random() - 0.5) * 0.5;
}
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, pos, gl.DYNAMIC_DRAW);
const aPos = gl.getAttribLocation(program, 'a_pos');
gl.enableVertexAttribArray(aPos);
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.clearColor(0.965, 0.972, 0.980, 1.0);
gl.viewport(0, 0, W, H);
const GW = 90, GH = 60;
const CW = W / GW;
const CH = H / GH;
const GW1 = GW + 1;
const gridVX = new Float32Array(GW1 * (GH + 1));
const gridVY = new Float32Array(gridVX.length);
function updateGrid(t) {
let idx = 0;
for (let j = 0; j <= GH; j++) {
const y = j * CH;
for (let i = 0; i <= GW; i++) {
const x = i * CW;
const a = x * 0.011 + t * 0.28;
const b = y * 0.013 - t * 0.21;
const c = (x + y) * 0.008 + t * 0.12;
const d = (x - y) * 0.009 - t * 0.17;
let ang = Math.sin(a + Math.cos(b * 0.7)) + Math.cos(c) * 0.6 + Math.sin(d * 1.3) * 0.4;
ang += 0.45 * Math.sin(x * 0.032 - t * 0.37) * Math.cos(y * 0.027 + t * 0.29);
const spd = 0.75 + 0.30 * Math.sin(c * 1.7 + t * 0.33);
let fx = Math.cos(ang) * spd + 0.12 * Math.sin(t * 0.09 + y * 0.004);
let fy = Math.sin(ang) * spd + 0.09 * Math.cos(t * 0.11 + x * 0.004);
fx += 0.08 * Math.sin(t * 0.05);
fy += 0.05 * Math.cos(t * 0.07);
gridVX[idx] = fx;
gridVY[idx] = fy;
idx++;
}
}
}
const fpsEl = document.getElementById('fps');
const countEl = document.getElementById('count');
countEl.textContent = String(pos.length >> 1);
const frameTimes = new Float64Array(60);
let ftIndex = 0, ftCount = 0, ftSum = 0;
let lastTime = 0;
let t = 0;
function frame(now) {
if (lastTime === 0) {
lastTime = now;
requestAnimationFrame(frame);
return;
}
const dtRaw = now - lastTime;
lastTime = now;
const dt = Math.min(50, dtRaw);
if (ftCount < 60) {
frameTimes[ftIndex] = dt;
ftSum += dt;
ftCount++;
} else {
ftSum -= frameTimes[ftIndex];
frameTimes[ftIndex] = dt;
ftSum += dt;
}
ftIndex = (ftIndex + 1) % 60;
const avgDt = ftSum / ftCount;
fpsEl.textContent = (1000 / avgDt).toFixed(1);
const dtSec = Math.min(0.05, dt / 1000);
t += dtSec;
updateGrid(t);
const dtScale = dtSec * 60 * 1.4;
const invCW = GW / W;
const invCH = GH / H;
const ease = 0.08;
const posL = pos;
const vxL = vx;
const vyL = vy;
const gvx = gridVX;
const gvy = gridVY;
const gw = GW, gh = GH, gw1 = GW1;
const N = PARTICLE_COUNT;
for (let i = 0, j = 0; i < N; i++, j += 2) {
let x = posL[j];
let y = posL[j + 1];
let cx = x * invCW;
let ix = cx | 0;
if (ix >= gw) ix = gw - 1;
let cy = y * invCH;
let iy = cy | 0;
if (iy >= gh) iy = gh - 1;
const fxw = cx - ix;
const fyw = cy - iy;
const base = iy * gw1 + ix;
const b1 = base + 1;
const b2 = base + gw1;
const b3 = b2 + 1;
const vx00 = gvx[base], vx10 = gvx[b1], vx01 = gvx[b2], vx11 = gvx[b3];
const vy00 = gvy[base], vy10 = gvy[b1], vy01 = gvy[b2], vy11 = gvy[b3];
const vxTop = vx00 + (vx10 - vx00) * fxw;
const vxBot = vx01 + (vx11 - vx01) * fxw;
const vfX = vxTop + (vxBot - vxTop) * fyw;
const vyTop = vy00 + (vy10 - vy00) * fxw;
const vyBot = vy01 + (vy11 - vy01) * fxw;
const vfY = vyTop + (vyBot - vyTop) * fyw;
let vxv = vxL[i];
let vyv = vyL[i];
vxv += (vfX - vxv) * ease;
vyv += (vfY - vyv) * ease;
vxL[i] = vxv;
vyL[i] = vyv;
x += vxv * dtScale;
y += vyv * dtScale;
if (x < 0) x += W;
else if (x >= W) x -= W;
if (y < 0) y += H;
else if (y >= H) y -= H;
posL[j] = x;
posL[j + 1] = y;
}
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, posL);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.POINTS, 0, N);
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
</script>
</body>
</html>
Nothing dropped.