V1ruS & TintaNova
Ever thought about using code to paint a dreamscape? If we mix algorithms with visual layers, we could create a hyperreal canvas that shifts with user input—like a story that rewrites itself in real time. What do you think?
That sounds like a wild, impossible canvas right now, but I love the idea of a living dream that you can tug on with your fingers. Imagine each line shifting, each color dissolving into a new scene—like a story that lives in code, not just paint. We could start with a simple noise generator, layer that over a fractal, and then let the user’s mouse pull a branch of the narrative out. I’m all in, but the detail will make me pull my hair. Let's sketch the skeleton first, then let the chaos bloom.
Sounds good, but keep the noise low‑level and the fractals deterministic; we don't want rogue patterns breaking the flow. Start with a simple simplex noise, overlay a Mandelbrot slice, then map mouse X to a parameter that shifts the hue and pulls a branch out. Once we have the skeleton, the chaos will follow its own logic. Let's keep the code tight, no unnecessary bloat.
Sounds perfect—simple noise, a slice of the Mandelbrot, and the mouse pulling the hue like a puppet master. I’ll start with a compact simplex function, stack the fractal on top, then bind the X position to a hue offset that will tug a branch out in real time. No extra libraries, just pure JS and canvas. Ready to test the skeleton?
Sure, just fire up a blank canvas, drop a minimal simplex routine, then add the Mandelbrot iteration. Hook mousemove to adjust a hue offset and trigger a redraw. No libs, pure JS. Go ahead, let me see the output.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dreamscape Demo</title>
<style>body{margin:0;overflow:hidden}canvas{display:block}</style>
</head>
<body>
<canvas id="c"></canvas>
<script>
const canvas=document.getElementById('c');
const ctx=canvas.getContext('2d');
let w=canvas.width=window.innerWidth;
let h=canvas.height=window.innerHeight;
let hueOffset=0;
// Simplex noise (tiny version)
function simplexNoise(x,y){
const grad3=[[1,1],[−1,1],[1,−1],[−1,−1],[1,0],[−1,0],[0,1],[0,−1]];
const F2=(Math.sqrt(3)-1)/2;
const G2=(3-Math.sqrt(3))/6;
let s=(x+y)*F2;
let i=Math.floor(x+s);
let j=Math.floor(y+s);
let t=(i+j)*G2;
let X0=i-t;
let Y0=j-t;
let x0=x-X0;
let y0=y-Y0;
let i1,j1;
if(x0>y0){i1=1;j1=0}else{i1=0;j1=1}
let x1=x0-i1+G2;
let y1=y0-j1+G2;
let x2=x0-1+2*G2;
let y2=y0-1+2*G2;
let ii=i&255,jj=j&255;
let gi0=perm[ii+perm[jj]]%8;
let gi1=perm[ii+i1+perm[jj+j1]]%8;
let gi2=perm[ii+1+perm[jj+1]]%8;
let t0=0.5-(x0*x0+y0*y0);
let n0=t0>0? t0*t0*grad3[gi0][0]*x0+grad3[gi0][1]*y0:0;
let t1=0.5-(x1*x1+y1*y1);
let n1=t1>0? t1*t1*grad3[gi1][0]*x1+grad3[gi1][1]*y1:0;
let t2=0.5-(x2*x2+y2*y2);
let n2=t2>0? t2*t2*grad3[gi2][0]*x2+grad3[gi2][1]*y2:0;
return 70*(n0+n1+n2);
}
const perm=new Uint8Array(512);
for(let i=0;i<256;i++) perm[i]=i;
for(let i=255;i>0;i--){
let j=Math.floor(Math.random()*(i+1));
[perm[i],perm[j]]=[perm[j],perm[i]];
}
for(let i=0;i<256;i++) perm[i+256]=perm[i];
// Mandelbrot iteration (simple slice)
function mandelbrot(x,y){
let zx=0, zy=0, cx=x, cy=y, iter=0, maxIter=50;
while(zx*zx+zy*zy<4 && iter<maxIter){
let temp=zx*zx-zy*zy+cx;
zy=2*zx*zy+cy;
zx=temp;
iter++;
}
return iter/maxIter;
}
function draw(){
const imgData=ctx.createImageData(w,h);
const data=imgData.data;
for(let y=0;y<h;y++){
for(let x=0;x<w;x++){
let nx=x/w*3;
let ny=y/h*3;
let noiseVal= simplexNoise(nx,ny);
let mandVal= mandelbrot(nx-1.5,ny-1.5);
let hue=(noiseVal*240 + hueOffset) % 360;
let sat=70+mandVal*30;
let bri=50+mandVal*20;
let [r,g,b] = hslToRgb(hue/360,sat/100,bri/100);
let i=(y*w+x)*4;
data[i]=r; data[i+1]=g; data[i+2]=b; data[i+3]=255;
}
}
ctx.putImageData(imgData,0,0);
}
function hslToRgb(h,s,l){
let r,g,b;
if(s==0){r=g=b=l*255;return[r,g,b];}
let q=l<0.5?l*(1+s):l+s-l*s;
let p=2*l-q;
const hk=[h+1/3,h,h-1/3];
for(let i=0;i<3;i++){
let t=hk[i];
if(t<0)t+=1;
if(t>1)t-=1;
if(t<1/6) [r,g,b]=[q,p,p];
else if(t<1/2)[r,g,b]=[q,p,p];
else if(t<2/3)[r,g,b]=[p,q,p];
else [r,g,b]=[p,p,q];
}
return [Math.round(r*255),Math.round(g*255),Math.round(b*255)];
}
canvas.addEventListener('mousemove',e=>{
hueOffset= e.clientX/w*360;
draw();
});
draw();
window.addEventListener('resize',()=>{w=canvas.width=window.innerWidth;h=canvas.height=window.innerHeight;draw();});
</script>
</body>
</html>