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.
My data layout is three flat typed arrays: pos Float32Array(2*N) for x,y, vel Float32Array(2*N) for vx,vy, and spd Float32Array(N) for per-particle speed variation, plus a coarse 90x60 vector grid gX,gY Float32Array holding the flow field; each frame I re-evaluate the grid with a few sines/cosines of x,y,t to make curl/drift/eddies that evolve with time, then for each of the 100,000 particles I bilinearly sample the 4 surrounding grid vectors, steer velocity toward field*speed with exponential damping, integrate, and wrap at the borders to recycle, and my draw strategy is raw WebGL POINTS where I orphan-upload only the pos buffer once per frame with DYNAMIC_DRAW and let a tiny vertex shader position the points and color them coherently from position+time while the fragment shader draws round alpha sprites, so the GPU work is trivial point raster and the one thing I expect to be the bottleneck is CPU time in the per-particle JS loop plus PCIe buffer upload, not fill-rate.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>100k flow field - raw WebGL</title>
<style>
html,body{margin:0;background:#05070f;color:#cfe3ff;font:13px/1.4 system-ui,-apple-system,Segoe UI,Roboto,sans-serif}
#wrap{width:900px;margin:10px auto}
#hud{display:flex;gap:18px;align-items:baseline;padding:6px 2px}
#hud b{color:#fff;font-variant-numeric:tabular-nums}
#c{display:block;width:900px;height:600px;background:#04060d;border:1px solid #1a2742}
.small{opacity:.7}
</style>
</head>
<body>
<div id="wrap">
<div id="hud"><div>FPS <b id="fps">-</b></div><div>particles <b id="cnt">-</b></div><div class="small">900x600 raw WebGL POINTS + evolving grid flow field</div></div>
<canvas id="c" width="900" height="600"></canvas>
</div>
<script>
'use strict';
var W=900, H=600, N=100000;
var canvas=document.getElementById('c');
var fpsEl=document.getElementById('fps');
var cntEl=document.getElementById('cnt');
var gl=canvas.getContext('webgl',{antialias:false,alpha:false,depth:false,stencil:false,powerPreference:'high-performance'});
if(!gl){fpsEl.textContent='no-webgl';throw new Error('no webgl');}
var P=new Float32Array(N*2);
var V=new Float32Array(N*2);
var S=new Float32Array(N);
for(var i=0;i<N;i++){
P[i*2]=Math.random()*W;
P[i*2+1]=Math.random()*H;
V[i*2]=(Math.random()-0.5)*1.5;
V[i*2+1]=(Math.random()-0.5)*1.5;
S[i]=0.6+Math.random()*0.9;
}
var GW=90, GH=60;
var gX=new Float32Array(GW*GH);
var gY=new Float32Array(GW*GH);
var stepX=(GW-1)/W, stepY=(GH-1)/H;
var cellWX=W/(GW-1), cellHY=H/(GH-1);
function updateGrid(t){
var k=0;
for(var j=0;j<GH;j++){
var y=j*cellHY;
var y1=y*0.009-t*0.45;
var y2=y*0.005+t*0.22;
for(var ii=0;ii<GW;ii++){
var x=ii*cellWX;
var a=Math.sin(x*0.008+t*0.6)+Math.cos(y1)+Math.sin((x+y)*0.0042+t*0.23);
a*=1.1;
var m=1.6+0.7*Math.sin(x*0.005-t*0.3)*Math.cos(y2);
gX[k]=Math.cos(a)*m;
gY[k]=Math.sin(a)*m;
k++;
}
}
}
var vsrc='attribute vec2 a_p;uniform vec2 u_res;uniform float u_t;varying vec3 v_c;'+
'void main(){vec2 c=(a_p/u_res)*2.0-1.0;c.y=-c.y;gl_Position=vec4(c,0.0,1.0);gl_PointSize=2.0;'+
'float h=sin(a_p.x*0.012+u_t*0.7)+cos(a_p.y*0.014-u_t*0.5)+sin((a_p.x+a_p.y)*0.006+u_t*0.3);'+
'float f=clamp(0.5+h*0.166,0.0,1.0);'+
'vec3 c1=vec3(0.08,0.30,0.85);vec3 c2=vec3(0.15,0.85,0.85);vec3 c3=vec3(0.92,0.96,1.0);'+
'vec3 col=mix(c1,c2,f);col=mix(col,c3,clamp(abs(h)*0.12,0.0,0.45));v_c=col;}';
var fsrc='precision mediump float;varying vec3 v_c;'+
'void main(){vec2 d=gl_PointCoord-0.5;if(dot(d,d)>0.25) discard;gl_FragColor=vec4(v_c,0.85);}';
function sh(type,src){var s=gl.createShader(type);gl.shaderSource(s,src);gl.compileShader(s);return s;}
var vs=sh(gl.VERTEX_SHADER,vsrc);
var fs=sh(gl.FRAGMENT_SHADER,fsrc);
var prog=gl.createProgram();
gl.attachShader(prog,vs);gl.attachShader(prog,fs);gl.linkProgram(prog);gl.useProgram(prog);
var aLoc=gl.getAttribLocation(prog,'a_p');
var uRes=gl.getUniformLocation(prog,'u_res');
var uT=gl.getUniformLocation(prog,'u_t');
gl.uniform2f(uRes,W,H);
var buf=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,buf);
gl.bufferData(gl.ARRAY_BUFFER,P,gl.DYNAMIC_DRAW);
gl.vertexAttribPointer(aLoc,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(aLoc);
gl.disable(gl.DEPTH_TEST);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA);
gl.viewport(0,0,W,H);
gl.clearColor(0.015,0.025,0.07,1.0);
var t=0.0, last=performance.now(), ema=16.66, frames=0;
cntEl.textContent=(P.length/2).toString();
function frame(now){
requestAnimationFrame(frame);
var ms=now-last; last=now;
if(!(ms>0)) ms=16.66;
if(ms>100) ms=100;
ema=ema*0.94+ms*0.06;
t+=ms*0.001;
updateGrid(t);
var dtS=ms/16.666;
if(dtS>2) dtS=2; else if(dtS<0.25) dtS=0.25;
var GX=gX, GY=gY;
var K=0.12, SPD=2.1;
for(var n=0;n<N;n++){
var i2=n+n;
var px=P[i2], py=P[i2+1];
var vx=V[i2], vy=V[i2+1];
var gx=px*stepX, gy=py*stepY;
var ix=gx|0, iy=gy|0;
if(ix<0)ix=0; else if(ix>GW-2)ix=GW-2;
if(iy<0)iy=0; else if(iy>GH-2)iy=GH-2;
var fx=gx-ix, fy=gy-iy;
if(fx<0)fx=0; else if(fx>1)fx=1;
if(fy<0)fy=0; else if(fy>1)fy=1;
var b=iy*GW+ix;
var x00=GX[b], y00=GY[b];
var x10=GX[b+1], y10=GY[b+1];
var x01=GX[b+GW], y01=GY[b+GW];
var x11=GX[b+GW+1], y11=GY[b+GW+1];
var ax=x00+(x10-x00)*fx;
var ay=y00+(y10-y00)*fx;
var bx=x01+(x11-x01)*fx;
var by=y01+(y11-y01)*fx;
var fvx=ax+(bx-ax)*fy;
var fvy=ay+(by-ay)*fy;
var sm=S[n]*SPD;
var tx=fvx*sm, ty=fvy*sm;
vx+=(tx-vx)*K;
vy+=(ty-vy)*K;
px+=vx*dtS;
py+=vy*dtS;
if(px<0)px+=W; else if(px>=W)px-=W;
if(py<0)py+=H; else if(py>=H)py-=H;
P[i2]=px; P[i2+1]=py;
V[i2]=vx; V[i2+1]=vy;
}
gl.uniform1f(uT,t);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bufferData(gl.ARRAY_BUFFER,P,gl.DYNAMIC_DRAW);
gl.drawArrays(gl.POINTS,0,N);
frames++;
if((frames%15)===0){
fpsEl.textContent=(1000/ema).toFixed(1);
cntEl.textContent=(P.length/2).toString();
}
}
requestAnimationFrame(frame);
</script>
</body>
</html>
Nothing dropped.