Skip to content

Commit 245f116

Browse files
committed
Fix datamosh effect rendering black — correct accumulation formula
The accum buffer was using decay+blend_factor that summed to ~0.96 instead of 1.0, causing steady-state brightness of only 6% of actual pixel values (near-black output). Fix: use a proper lerp (accum += (pixel - accum) * rate) so accum always converges to full pixel brightness. Also seed accum from the first live frame so the image appears immediately rather than fading up from black.
1 parent b32ce37 commit 245f116

1 file changed

Lines changed: 17 additions & 8 deletions

File tree

datamosh-editor.html

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@
336336

337337
// ── Buffers ──────────────────────────────────────────
338338
let accum =new Float32Array(PIX*4);
339+
let accumInited=false;
339340
let prev =new Uint8ClampedArray(PIX*4);
340341
let prev2 =new Uint8ClampedArray(PIX*4);
341342
let motX =new Float32Array(PIX);
@@ -580,19 +581,27 @@
580581
// ── Datamosh ─────────────────────────────────────────
581582
function fxDatamosh(src,p){
582583
const d=src.data;
584+
// Seed accum with the first real frame so the image is never black
585+
if(!accumInited){for(let i=0;i<d.length;i++)accum[i]=d[i];accumInited=true;}
583586
for(let i=0;i<d.length;i+=4){
584587
const dr=d[i]-prev[i],dg=d[i+1]-prev[i+1],db=d[i+2]-prev[i+2];
585588
const m=(Math.abs(dr)+Math.abs(dg)+Math.abs(db))/3;
586-
const bl=m>p.threshold?(1-p.blend)*.4:(1-p.blend)*.018;
587-
accum[i]=accum[i]*p.decay+d[i]*bl;
588-
accum[i+1]=accum[i+1]*p.decay+d[i+1]*bl;
589-
accum[i+2]=accum[i+2]*p.decay+d[i+2]*bl;
589+
// Proper lerp — (1-rate)+rate == 1.0, so accum converges to full pixel value
590+
// High motion → accum follows new scene faster; low motion → holds old scene (datamosh)
591+
const rate=m>p.threshold?(1-p.blend)*0.55:(1-p.blend)*0.04;
592+
accum[i] +=( d[i] -accum[i] )*rate;
593+
accum[i+1]+=(d[i+1]-accum[i+1])*rate;
594+
accum[i+2]+=(d[i+2]-accum[i+2])*rate;
590595
}
591596
const out=new ImageData(W,H);
592597
for(let i=0;i<d.length;i+=4){
593-
const dr=(d[i]-prev[i])*p.motAmp,dg=(d[i+1]-prev[i+1])*p.motAmp,db=(d[i+2]-prev[i+2])*p.motAmp;
594-
out.data[i]=clamp(accum[i]+dr,0,255);out.data[i+1]=clamp(accum[i+1]+dg,0,255);
595-
out.data[i+2]=clamp(accum[i+2]+db,0,255);out.data[i+3]=255;
598+
const dr=(d[i] -prev[i] )*p.motAmp;
599+
const dg=(d[i+1]-prev[i+1])*p.motAmp;
600+
const db=(d[i+2]-prev[i+2])*p.motAmp;
601+
out.data[i] =clamp(accum[i] +dr,0,255);
602+
out.data[i+1]=clamp(accum[i+1]+dg,0,255);
603+
out.data[i+2]=clamp(accum[i+2]+db,0,255);
604+
out.data[i+3]=255;
596605
}
597606
return out;
598607
}
@@ -973,7 +982,7 @@
973982
}
974983

975984
function resetAccum(){
976-
accum.fill(0);motX.fill(0);motY.fill(0);fhist.length=0;chrR.length=0;chrG.length=0;chrB.length=0;
985+
accum.fill(0);accumInited=false;motX.fill(0);motY.fill(0);fhist.length=0;chrR.length=0;chrG.length=0;chrB.length=0;
977986
scanL.length=0;prev.fill(0);prev2.fill(0);fc=0;sessStart=Date.now();waveT=0;bendRng=1234567;
978987
setState('ACCUM CLEARED');
979988
}

0 commit comments

Comments
 (0)