Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
- <title>First project</title>
- <style>
- body,html{
- margin:0;padding:0;
- width:100%;height:100%;
- overflow:hidden;background:#000
- }
- canvas{
- display:block;width:100%;height:100%;
- image-rendering:pixelated
- }
- </style>
- </head>
- <body>
- <canvas id="canvas"></canvas>
- <script>
- const canvas=document.getElementById("canvas"),
- ctx=canvas.getContext("2d");
- Object.getOwnPropertyNames(Math).forEach(p=>window[p]=Math[p]);TAU=PI*2;
- mod=(n,m)=>(n%m+m)%m;fract=x=>(x%1+1)%1;
- mix=(a,b,t)=>a*(1-t)+b*t;//a+(b-a)*t;
- createArray=(n,v)=>Array.from({length:n},(_,i)=>typeof v==="function"?v(i):v);
- charRange=(s,e)=>Array(e-s+1).fill().map((_,i)=>String.fromCharCode(s+i)).join("");
- rand=(a,b)=>typeof b==="undefined"?random()*(typeof a==="undefined"?1:a):a+random()*(b-a);
- clamp=(v,a,b)=>min(max(v,a),b);dist=(x0,y0,x1,y1)=>sqrt(pow(x1-x0,2)+pow(y1-y0,2));
- let width,height,imgDat,pixBuf,
- pixelSize=6;
- resize=()=>{
- const dpr=window.devicePixelRatio||1,
- iw=window.innerWidth,ih=window.innerHeight;
- canvas.width=width=floor(iw*dpr/pixelSize);
- canvas.height=height=floor(ih*dpr/pixelSize);
- imgDat=ctx.createImageData(width,height);
- pixBuf=new Uint32Array(imgDat.data.buffer);
- };
- const audioCtx=new AudioContext();
- let audioNode,audioTime=0,sampleRate=audioCtx.sampleRate,sampleDt=1/sampleRate;
- fbCall=()=>{};
- funcbeat=SR=>{
- let num=4,freqs,amps,phases,timer=1,
- randomize=init=>{
- if(init){
- freqs=createArray(num,()=>[0,0]);
- amps=createArray(num,()=>0);
- adds=createArray(num,()=>[0,0,0]);
- phases=createArray(num,()=>rand());
- }
- for(let i=0;i<num;i++){
- freqs[i][0]=mix(100,1e3,rand()**3);
- freqs[i][1]=mix(100,1e3,rand()**3);
- amps[i]=rand()*2e3;
- adds[i][0]=rand(-3e3,4e3)*sampleDt;
- adds[i][1]=rand(-1e3,1e2)*sampleDt;
- adds[i][2]=rand(-1e3,1e2)*sampleDt;
- }
- };
- randomize(true);
- return t=>{
- let sum=0;
- for(let i=0;i<num;i++){
- phases[i]=fract(phases[i]+(freqs[i][0]+amps[i]*sin(timer*freqs[i][1]*TAU))*sampleDt);
- freqs[i][0]+=adds[i][1];freqs[i][1]+=adds[i][2];amps[i]+=adds[i][0];
- sum+=sin(phases[i]*TAU);
- }
- timer-=sampleDt;
- if(timer<=0){randomize();timer+=(rand()**10)*4;fbCall();}
- return tanh((sum/num)+rand(-.01,.01))*.05;
- };
- };
- function initAudio(){
- if(audioNode)return;
- audioNode=audioCtx.createScriptProcessor(4096,0,1);
- const fb=funcbeat(sampleRate);
- audioNode.onaudioprocess=e=>{
- const out=e.outputBuffer.getChannelData(0);
- for(let i=0;i<out.length;i++){
- //out[i]=sin(audioTime*440*TAU)/(1+audioTime*200);
- out[i]=fb(audioTime);
- audioTime+=sampleDt;
- }
- };
- audioNode.connect(audioCtx.destination);
- }
- const pset=(x,y,c)=>{if(x>=0&&x<width&&y>=0&&y<height)pixBuf[y*width+x]=c},
- line=(x0,y0,x1,y1,c)=>{
- x0=floor(x0);y0=floor(y0);x1=floor(x1);y1=floor(y1);
- const dx=abs(x1-x0),sx=x0<x1?1:-1,dy=-abs(y1-y0),sy=y0<y1?1:-1;
- let err=dx+dy;
- while(1){
- pset(x0,y0,c);
- if(x0===x1&&y0===y1)break;
- const e2=2*err;
- if(e2>=dy){err+=dy;x0+=sx}
- if(e2<=dx){err+=dx;y0+=sy}
- }
- },
- rect=(x,y,w,h,c)=>{
- for(let j=floor(y);j<y+h;j++)for(let i=floor(x);i<x+w;i++)pset(i,j,c);
- },
- rectb=(x,y,w,h,c)=>{
- for(let i=floor(x);i<x+w;i++){pset(i,y,c);pset(i,y+h-1,c)}
- for(let j=floor(y);j<y+h;j++){pset(x,j,c);pset(x+w-1,j,c)}
- },
- circb=(xc,yc,r,c)=>{
- xc=floor(xc);yc=floor(yc);r=floor(r);
- let x=0,y=r,d=3-2*r;
- const plot=(x,y)=>{pset(xc+x,yc+y,c);pset(xc-x,yc+y,c);pset(xc+x,yc-y,c);pset(xc-x,yc-y,c);pset(xc+y,yc+x,c);pset(xc-y,yc+x,c);pset(xc+y,yc-x,c);pset(xc-y,yc-x,c)};
- while(y>=x){plot(x,y);x++;if(d>0){y--;d=d+4*(x-y)+10}else d=d+4*x+6}
- },
- circ=(xc,yc,r,c)=>{
- xc=floor(xc);yc=floor(yc);r=floor(r);
- let x=0,y=r,d=3-2*r;
- const span=(x,y,w)=>{for(let i=x-w;i<=x+w;i++){pset(i,yc+y,c);pset(i,yc-y,c)}};
- while(y>=x){span(xc,y,x);span(xc,x,y);x++;if(d>0){y--;d=d+4*(x-y)+10}else d=d+4*x+6}
- };
- tri=(x0,y0,x1,y1,x2,y2,c)=>{
- x0=floor(x0);y0=floor(y0);x1=floor(x1);y1=floor(y1);x2=floor(x2);y2=floor(y2);
- let minX=x0,maxX=x0,minY=y0,maxY=y0;
- if(x1<minX)minX=x1;if(x1>maxX)maxX=x1;if(x2<minX)minX=x2;if(x2>maxX)maxX=x2;
- if(y1<minY)minY=y1;if(y1>maxY)maxY=y1;if(y2<minY)minY=y2;if(y2>maxY)maxY=y2;
- if(maxX-minX>maxY-minY){
- if(x0>x1){let t=x0;x0=x1;x1=t;t=y0;y0=y1;y1=t}
- if(x0>x2){let t=x0;x0=x2;x2=t;t=y0;y0=y2;y2=t}
- if(x1>x2){let t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t}
- if(x0===x2){pset(x0,y0,c);return;}
- let dx02=x2-x0,dx01=x1-x0,dx12=x2-x1;
- for(let x=x0;x<x2;x++){
- let ya=y0+floor((x-x0)*(y2-y0)/dx02),yb;
- if(x<=x1&&dx01!==0)yb=y0+floor((x-x0)*(y1-y0)/dx01);
- else if(dx12!==0)yb=y1+floor((x-x1)*(y2-y1)/dx12);
- else yb=y1;
- if(ya>yb){let t=ya;ya=yb;yb=t}
- for(let y=ya;y<=yb;y++)pset(x,y,c);
- }
- }else{
- if(y0>y1){let t=x0;x0=x1;x1=t;t=y0;y0=y1;y1=t}
- if(y0>y2){let t=x0;x0=x2;x2=t;t=y0;y0=y2;y2=t}
- if(y1>y2){let t=x1;x1=x2;x2=t;t=y1;y1=y2;y2=t}
- if(y0===y2){for(let x=minX;x<=maxX;x++)pset(x,y0,c);return;}
- let dy02=y2-y0,dy01=y1-y0,dy12=y2-y1;
- for(let y=y0;y<y2;y++){
- let xa=x0+floor((y-y0)*(x2-x0)/dy02),xb;
- if(y<=y1&&dy01!==0)xb=x0+floor((y-y0)*(x1-x0)/dy01);
- else if(dy12!==0)xb=x1+floor((y-y1)*(x2-x1)/dy12);
- else xb=x1;
- if(xa>xb){let t=xa;xa=xb;xb=t}
- for(let x=xa;x<=xb;x++)pset(x,y,c);
- }
- }
- };
- trib=(x0,y0,x1,y1,x2,y2,c)=>{line(x0,y0,x1,y1,c);line(x1,y1,x2,y2,c);line(x2,y2,x0,y0,c);};
- dotLine=(x0,y0,x1,y1,sp,sh,c)=>{
- let dx=x1-x0,dy=y1-y0,len=max(abs(dx),abs(dy)),
- vx=dx/len,vy=dy/len;
- for(let i=mod(-sh,sp);i<=len;i+=sp)pset(floor(x0+vx*i),floor(y0+vy*i),c);
- };
- vectorFont={
- width:3,height:5,spacing:.25,leading:1,
- //UPPERCASE
- A:[[[0,4],[0,1],[1,0],[2,1],[2,4]],[[0,2],[2,2]]],
- B:[[[0,0],[1.5,0],[2,1],[1.5,2],[0,2],[1.5,2],[2,3],[1.5,4],[0,4],[0,0]]],
- C:[[[2,0],[0,0],[0,4],[2,4]]],
- D:[[[0,0],[1,0],[2,1],[2,3],[1,4],[0,4],[0,0]]],
- E:[[[2,0],[0,0],[0,4],[2,4]],[[0,2],[1.5,2]]],
- F:[[[2,0],[0,0],[0,4]],[[0,2],[1.5,2]]],
- G:[[[2,1],[2,0],[0,0],[0,4],[2,4],[2,2],[1,2]]],
- H:[[[0,0],[0,4]],[[2,0],[2,4]],[[0,2],[2,2]]],
- I:[[[1,0],[1,4]],[[0,0],[2,0]],[[0,4],[2,4]]],
- J:[[[2,0],[2,3],[1,4],[0,3]]],
- K:[[[0,0],[0,4]],[[2,0],[0,2],[2,4]]],
- L:[[[0,0],[0,4],[2,4]]],
- M:[[[0,4],[0,0],[1,2],[2,0],[2,4]]],
- N:[[[0,4],[0,0],[2,4],[2,0]]],
- O:[[[0,1],[1,0],[2,1],[2,3],[1,4],[0,3],[0,1]]],
- P:[[[0,4],[0,0],[2,0],[2,2],[0,2]]],
- Q:[[[0,1],[1,0],[2,1],[2,3],[1,4],[0,3],[0,1]],[[1,3],[2,5]]],
- R:[[[0,4],[0,0],[2,0],[2,2],[0,2],[2,4]]],
- S:[[[2,0],[0,0],[0,2],[2,2],[2,4],[0,4]]],
- T:[[[1,0],[1,4]],[[0,0],[2,0]]],
- U:[[[0,0],[0,4],[2,4],[2,0]]],
- V:[[[0,0],[1,4],[2,0]]],W:[[[0,0],[0,4],[1,3],[2,4],[2,0]]],
- X:[[[0,0],[2,4]],[[2,0],[0,4]]],
- Y:[[[0,0],[1,2],[2,0]],[[1,2],[1,4]]],
- Z:[[[0,0],[2,0],[0,4],[2,4]]],
- //lowercase
- a:[[[0,2],[2,2],[2,4],[0,4],[0,3],[2,3]]],
- b:[[[0,0],[0,4],[2,4],[2,2],[0,2]]],
- c:[[[2,2],[0,2],[0,4],[2,4]]],
- d:[[[2,0],[2,4],[0,4],[0,2],[2,2]]],
- e:[[[0,3],[2,3],[2,2],[0,2],[0,4],[2,4]]],
- f:[[[2,0],[1,0],[1,4]],[[0,2],[2,2]]],
- g:[[[2,4],[2,2],[0,2],[0,4],[2,4],[2,6],[0,6]]],
- h:[[[0,0],[0,4]],[[0,2],[2,2],[2,4]]],
- i:[[[1,1],[1,1]],[[1,2],[1,4]]],
- j:[[[1,1],[1,1]],[[1,2],[1,5],[0,5]]],
- k:[[[0,0],[0,4]],[[2,2],[0,3]],[[1,3],[2,4]]],
- l:[[[1,0],[1,4]]],
- m:[[[0,2],[0,4]],[[1,2],[1,4]],[[2,2],[2,4]],[[0,2],[2,2]]],
- n:[[[0,2],[0,4]],[[0,2],[2,2],[2,4]]],
- o:[[[0,2],[2,2],[2,4],[0,4],[0,2]]],
- p:[[[0,2],[0,6]],[[0,2],[2,2],[2,4],[0,4]]],
- q:[[[2,2],[2,6]],[[2,2],[0,2],[0,4],[2,4]]],
- r:[[[0,2],[0,4]],[[0,3],[2,2]]],
- s:[[[2,2],[0,2],[0,3],[2,3],[2,4],[0,4]]],
- t:[[[1,0],[1,4]],[[0,2],[2,2]]],
- u:[[[0,2],[0,4],[2,4],[2,2]]],
- v:[[[0,2],[1,4],[2,2]]],
- w:[[[0,2],[0,4],[1,3],[2,4],[2,2]]],
- x:[[[0,2],[2,4]],[[2,2],[0,4]]],
- y:[[[0,2],[0,4],[2,4],[2,2]],[[2,4],[2,6],[0,6]]],
- z:[[[0,2],[2,2],[0,4],[2,4]]],
- //digits & symbols
- 1:[[[1,0],[1,4]],[[0,1],[1,0]]],
- 2:[[[0,1],[1,0],[2,1],[0,4],[2,4]]],
- 3:[[[0,0],[2,0],[1,2],[2,4],[0,4]]],
- 4:[[[0,0],[0,2],[2,2]],[[2,0],[2,4]]],
- 5:[[[2,0],[0,0],[0,2],[2,2],[2,4],[0,4]]],
- 6:[[[2,0],[0,2],[0,4],[2,4],[2,2],[0,2]]],
- 7:[[[0,0],[2,0],[0,4]]],
- 8:[[[0,0],[0,1],[2,3],[2,4],[0,4],[0,3],[2,1],[2,0],[0,0]]],
- 9:[[[2,2],[0,2],[0,0],[2,0],[2,4],[0,4]]],
- 0:[[[0,0],[2,0],[2,4],[0,4],[0,0]],[[2,0],[0,4]]],
- "!":[[[1,0],[1,2]],[[1,4],[1,4]]],
- "?":[[[0,1],[1,0],[2,1],[1,2],[1,3]],[[1,4],[1,4]]],
- ".":[[[1,4],[1,4]]],
- ",":[[[1,4],[1,5]]],
- ":":[[[1,1],[1,1]],[[1,3],[1,3]]],
- ";":[[[1,1],[1,1]],[[1,3],[1,4]]],
- " ":[],
- "-":[[[0,2],[2,2]]],
- "+":[[[1,1],[1,3]],[[0,2],[2,2]]],
- "=":[[[0,1.5],[2,1.5]],[[0,2.5],[2,2.5]]],
- "/":[[[2,0],[0,4]]],
- "(":[[[1,0],[0,1],[0,3],[1,4]]],
- ")":[[[0,0],[1,1],[1,3],[0,4]]],
- "[":[[[1.5,0],[0.5,0],[0.5,4],[1.5,4]]],"]":[[[0.5,0],[1.5,0],[1.5,4],[0.5,4]]],
- "{":[[[2,.25],[1.5,0],[1,1],[1,1.75],[0,2],[1,2.25],[1,3],[1.5,4],[2,3.75]]],"}":[[[0,.25],[0.5,0],[1,1],[1,1.75],[2,2],[1,2.25],[1,3],[.5,4],[0,3.75]]],
- "<":[[[2,0],[0,2],[2,4]]],">":[[[0,0],[2,2],[0,4]]],
- "|":[[[1,0],[1,4]]],"\\":[[[0,0],[2,4]]],"_":[[[0,4],[2,4]]],"^":[[[0,1],[1,0],[2,1]]],"`":[[[0,0],[1,1]]],"~":[[[0,3],[0.5,2],[1.5,3],[2,2]]],
- "@":[[[2,4],[0,4],[0,0],[2,0],[2,2],[1,2],[1,1]]],"#":[[[0.5,0],[0.5,4]],[[1.5,0],[1.5,4]],[[0,1],[2,1]],[[0,3],[2,3]]],
- "$":[[[0,4],[2,4],[2,2],[0,2],[0,0],[2,0]],[[1,-0.5],[1,4.5]]],"%":[[[0,4],[2,0]],[[0.5,0.5],[0.5,0.5]],[[1.5,3.5],[1.5,3.5]]],
- "&":[[[2,4],[0,1],[1,0],[2,1],[0,4],[1,4],[2,3]]],"*":[[[1,1],[1,3]],[[0.5,1.5],[1.5,2.5]],[[1.5,1.5],[0.5,2.5]]],
- "'":[[[1,0],[1,1]]],'"':[[[0.5,0],[0.5,1]],[[1.5,0],[1.5,1]]]
- };
- vectorText=(str,x,y,s,c)=>{
- let tx=0,ty=0;
- str.split("").forEach(char=>{
- if(char==="\n"){tx=0;ty+=(vectorFont.height+vectorFont.leading)*s;return}
- const g=vectorFont[char]||vectorFont[char.toUpperCase()];
- if(g)g.forEach(p=>{
- for(let j=0;j<p.length-1;j++)line(x+tx+p[j][0]*s,y+ty+p[j][1]*s,x+tx+p[j+1][0]*s,y+ty+p[j+1][1]*s,c);
- });
- tx+=(vectorFont.width+vectorFont.spacing)*s;
- });
- };
- mouseX=mouseY=pmouseX=pmouseY=mouseXpress=mouseYpress=0;mouseDown=pmouseDown=mouseClicked=mouseReleased=false;
- const trackMouse=e=>{
- if(e.cancelable)e.preventDefault();
- if(audioCtx.state==="suspended")audioCtx.resume();
- initAudio();
- const r=canvas.getBoundingClientRect(),t=(e.touches&&e.touches.length)?e.touches[0]:e;
- if(e.type!=="touchend"&&e.type!=="pointerup"){
- mouseX=((t.clientX-r.left)*(width/r.width))|0;
- mouseY=((t.clientY-r.top)*(height/r.height))|0;
- }
- if(e.type==="pointerdown"||e.type==="touchstart")mouseDown=true;
- if(e.type==="pointerup"||e.type==="touchend")mouseDown=false;
- };
- ["pointerdown","pointermove","pointerup","touchstart","touchmove","touchend"].forEach(ev=>canvas.addEventListener(ev,trackMouse,{passive:false}));
- mInRect=(x,y,w,h)=>mouseX>=x&&mouseX<x+w&&mouseY>=y&&mouseY<y+h;
- function parseBigInt(str,base=10){
- return[...str].reduce((acc,curr)=>acc*BigInt(base)+BigInt(parseInt(curr,base)),0n);
- }
- font3x5="6fm,19,iv1,7tq,gbp,l2i,i,djo,429,9h,15c,3y8,cg,6bk,3ok,odr,n16,mn7,b6r,elp,b7z,oge,3on,o8f,bfz,sw,3yo,dhw,2t4,45t,6g3,jqi,i5m,bmz,jf2,bqj,mvj,3wv,l72,i5p,n13,8is,hyl,mkp,i2n,i23,8kq,3qj,kfe,hyj,b66,787,odp,8kt,p65,hwt,78t,mnb,jva,ebt,adv,16,m4g,h,nuo,bm1,jnk,l9g,jpc,7h0,beo,hxl,79e,41u,h8p,djn,iww,hxc,8e8,69s,fr4,4lc,akg,dsi,l6o,8jk,p4w,gu8,c3k,jwg,jx2,782,akz,bc".
- split(",").map(s=>parseBigInt(s,36));
- drawBigInt=(n,x,y,w,h,c)=>{
- for(let i=0;i<w*h;i++)
- if((n>>BigInt(i))&1n)
- pset(x+mod(i,w),y+floor(i/w),c)
- }
- text3x5=(str,x,y,c)=>{
- x=floor(x);y=floor(y);
- let dx=0,dy=0;
- for(let char of str){
- if(char==="\n"){dx=0;dy+=6;continue;}
- let code=char.charCodeAt(0)-33;
- if(code>=0&&code<font3x5.length){
- drawBigInt(font3x5[code],x+dx,y+dy,3,5,c);
- }
- dx+=4;
- }
- }
- class BitmapEditor{
- constructor(x,y,w,h,pS=4,n=0n){
- Object.assign(this,{x,y,w,h,pS,n:BigInt(n),drag:false,c:true})
- }
- update(){
- let{x,y,w,h,pS,n}=this,inside=mInRect(x,y,w*pS,h*pS);
- if(mouseClicked){
- this.drag=inside;
- if(inside){
- let px=floor((mouseX-x)/pS),
- py=floor((mouseY-y)/pS),
- idx=BigInt(py*w+px);
- this.c=!((n>>idx)&1n);
- }
- }
- if(mouseDown&&this.drag&&inside){
- let px=clamp(floor((mouseX-x)/pS),0,w-1),
- py=clamp(floor((mouseY-y)/pS),0,h-1),
- idx=BigInt(py*w+px);
- if(this.c)this.n|=1n<<idx;else this.n&=~(1n<<idx);
- }
- }
- draw(){
- let{x,y,w,h,pS,n}=this;
- for(let i=0;i<w*h;i++){
- const cx=x+mod(i,w)*pS,cy=y+floor(i/w)*pS;
- rect(cx,cy,pS-1,pS-1,(n>>BigInt(i))&BigInt(1)?0xFFFFFFFF:0xFF000000);
- }
- }
- toString(b=36){return this.n.toString(b);}
- fromString(s,b=36){this.n=parseBigInt(s,b);}
- static drawStr(str,x,y,w,h,pS=1){
- let n=parseBigInt(str,36);
- for(let i=0;i<w*h;i++){
- if((n>>BigInt(i))&1n){
- const cx=x+mod(i,w)*pS,cy=y+floor(i/w)*pS;
- rect(cx,cy,pS,pS,0xFFFFFFFF);
- }
- }
- }
- }
- class Button{
- constructor(x,y,w,h,onClick){
- Object.assign(this,{x,y,w,h,onClick,hold:false});
- }
- update(){
- let{x,y,w,h}=this,inside=mInRect(x,y,w,h);
- if(mouseClicked)this.hold=inside;
- if(mouseReleased&&this.hold&&inside)this.onClick();
- }
- draw(){
- let{x,y,w,h}=this,inside=mInRect(x,y,w,h);
- rect(x,y,w,h,0xFFA0A0A0);
- rectb(x,y,w,h,mouseDown&&this.hold&&inside?0xFFFFFFFF:0xFFCCCCCC);
- }
- }
- window.addEventListener("resize",resize);
- resize();
- //init
- chooseRand=a=>a[floor(random()*a.length)];
- let zBuf=new Float32Array(0);
- const vec3=(x=0,y=0,z=0)=>({x,y,z}),
- dot=(v1,v2)=>v1.x*v2.x+v1.y*v2.y+v1.z*v2.z,
- normalize=v=>{let l=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);return l===0?vec3():vec3(v.x/l,v.y/l,v.z/l)},
- rotX=(p,a)=>{let c=cos(a),s=sin(a);return vec3(p.x,p.y*c-p.z*s,p.y*s+p.z*c)},
- rotY=(p,a)=>{let c=cos(a),s=sin(a);return vec3(p.x*c+p.z*s,p.y,-p.x*s+p.z*c)},
- colSel={f:[i=>clamp(i,0,1),i=>clamp(i*i,0,1),i=>clamp(sin(i*PI),0,1),i=>clamp(cos(i*PI),0,1)],cur:[],init:()=>{
- for(let i=0;i<3;i++)
- colSel.cur[i]=chooseRand(colSel.f);
- }};colSel.init();
- getColor=i=>{
- let r=floor(colSel.cur[0](i)*255),g=floor(colSel.cur[1](i)*255),b=floor(colSel.cur[2](i)*255);
- return 0xFF000000|(b<<16)|(g<<8)|r;
- },
- tri3d=(p0,n0,p1,n1,p2,n2,lp,vp)=>{
- let x0=floor(p0.x),y0=floor(p0.y),z0=p0.z,
- x1=floor(p1.x),y1=floor(p1.y),z1=p1.z,
- x2=floor(p2.x),y2=floor(p2.y),z2=p2.z,
- minX=max(0,min(x0,x1,x2)),maxX=min(width-1,max(x0,x1,x2)),
- minY=max(0,min(y0,y1,y2)),maxY=min(height-1,max(y0,y1,y2)),
- denom=(y1-y2)*(x0-x2)+(x2-x1)*(y0-y2);
- if(denom===0)return;
- function pixel(x,y){
- let w0=((y1-y2)*(x-x2)+(x2-x1)*(y-y2))/denom,w1=((y2-y0)*(x-x2)+(x0-x2)*(y-y2))/denom,w2=1-w0-w1;
- if(w0<-0.001||w1<-0.001||w2<-0.001)return;
- let z=w0*z0+w1*z1+w2*z2,idx=y*width+x;
- if(z>zBuf[idx]){
- zBuf[idx]=z;
- let px=w0*p0.wx+w1*p1.wx+w2*p2.wx,py=w0*p0.wy+w1*p1.wy+w2*p2.wy,pz=w0*p0.wz+w1*p1.wz+w2*p2.wz,
- N=normalize(vec3(w0*n0.x+w1*n1.x+w2*n2.x,w0*n0.y+w1*n1.y+w2*n2.y,w0*n0.z+w1*n1.z+w2*n2.z)),
- L=normalize(vec3(lp.x-px,lp.y-py,lp.z-pz)),V=normalize(vec3(vp.x-px,vp.y-py,vp.z-pz)),
- R=vec3(2*dot(N,L)*N.x-L.x,2*dot(N,L)*N.y-L.y,2*dot(N,L)*N.z-L.z);
- pixBuf[idx]=getColor(0.15+max(dot(N,L)*.5+.25,0)*.5+pow(max(dot(R,V),0),16)*0.3);
- }
- }
- for(let y=minY;y<=maxY;y++){
- for(let x=minX;x<=maxX;x++){
- pixel(x,y);
- }
- }
- };
- let sphereVertices=[],sphereIndices=[],cubeVertices=[],cubeIndices=[];
- const initSphere=(rings,sectors)=>{
- sphereVertices=[];sphereIndices=[];
- for(let r=0;r<=rings;r++){
- let phi=(r*PI)/rings,sinPhi=sin(phi),cosPhi=cos(phi);
- for(let s=0;s<=sectors;s++){
- let theta=(s*TAU)/sectors,x=cos(theta)*sinPhi,y=cosPhi,z=sin(theta)*sinPhi;
- sphereVertices.push({pos:vec3(x,y,z),normal:vec3(x,y,z)});
- }
- }
- for(let r=0;r<rings;r++)for(let s=0;s<sectors;s++){
- let first=r*(sectors+1)+s,second=first+sectors+1;
- sphereIndices.push(first,second,first+1,second,second+1,first+1);
- }
- },
- initCube=()=>{
- cubeVertices=[];cubeIndices=[];
- let d=[[-1,-1,1],[1,-1,1],[1,1,1],[-1,1,1],[-1,-1,-1],[-1,1,-1],[1,1,-1],[1,-1,-1]],
- f=[[0,1,2,3,[0,0,1]],[4,5,6,7,[0,0,-1]],[3,2,6,5,[0,1,0]],[0,4,7,1,[0,-1,0]],[1,7,6,2,[1,0,0]],[0,3,5,4,[-1,0,0]]];
- f.forEach(w=>{
- let n=vec3(w[4][0],w[4][1],w[4][2]),idx=cubeVertices.length;
- w.slice(0,4).forEach(v=>cubeVertices.push({pos:vec3(d[v][0]*0.7,d[v][1]*0.7,d[v][2]*0.7),normal:n}));
- cubeIndices.push(idx,idx+1,idx+2,idx,idx+2,idx+3);
- });
- };
- initSphere(12,18);initCube();
- let rotDragX=0,rotDragY=0;
- linew=(x0,y0,x1,y1,w,c)=>{
- let d=dist(x0,y0,x1,y1),dx=(x1-x0)/d,dy=(y1-y0)/d,r=w/2;
- if(d<1e-11)return;
- tri(x0+dy*r,y0-dx*r,x1+dy*r,y1-dx*r,x1-dy*r,y1+dx*r,c);
- tri(x1-dy*r,y1+dx*r,x0-dy*r,y0+dx*r,x0+dy*r,y0-dx*r,c);
- };
- bgCol=0xFFA0A0A0;
- const setRandomBg=()=>{
- let r=floor(random()*256),g=floor(random()*256),b=floor(random()*256);
- bgCol=0xFF000000|(b<<16)|(g<<8)|r;
- };
- t=0;fbCall=()=>{setRandomBg();colSel.init();t=0;};
- scrollerText=(str,y,c,sh=0)=>text3x5(str,mod(sh-frame,width+(str.length*4))-str.length*4,y,c);
- frame=0;
- function render(){
- mouseClicked=!pmouseDown&&mouseDown;mouseReleased=pmouseDown&&!mouseDown;
- if(mouseClicked){mouseXpress=mouseX;mouseYpress=mouseY;}
- //---
- pixBuf.fill(bgCol);
- rectb(0,0,width,height,bgCol^0xFFFFFF);
- linew(mouseXpress,mouseYpress,mouseX,mouseY,t,0xFFA03030);
- t++;
- dotLine(mouseX,0,mouseX,height,4-mouseDown,frame/10,0xFFC0C0C0);
- dotLine(0,mouseY,width,mouseY,4-mouseDown,frame/10,0xFFC0C0C0);
- text3x5(`(${mouseX},${mouseY})`,mouseX+2,mouseY-7,0xFFD0D0D0);
- //---
- let totalPixels=width*height;
- if(zBuf.length!==totalPixels)zBuf=new Float32Array(totalPixels);
- zBuf.fill(-999999);
- let fov=100,cx=width/2,cy=height/2,angX=frame*0.015+rotDragX,angY=frame*0.011+rotDragY,
- lp=vec3(cos(frame*.04)*8,sin(frame*.02)*4,sin(frame*.01)*5),vp=vec3(cos(frame*.01)*8,sin(frame*.01)*4,sin(frame*.005)*5),
- drawMesh=(ind,vert,tx)=>{
- for(let i=0;i<ind.length;i+=3){
- let v0=vert[ind[i]],v1=vert[ind[i+1]],v2=vert[ind[i+2]],
- rp0=rotY(rotX(v0.pos,angX),angY),rp1=rotY(rotX(v1.pos,angX),angY),rp2=rotY(rotX(v2.pos,angX),angY);
- rp0.x+=tx;rp1.x+=tx;rp2.x+=tx;
- let zp0=rp0.z+3.5,zp1=rp1.z+3.5,zp2=rp2.z+3.5,
- p0_scr={x:(rp0.x*fov)/zp0+cx,y:(rp0.y*fov)/zp0+cy,z:1/zp0,wx:rp0.x,wy:rp0.y,wz:rp0.z},
- p1_scr={x:(rp1.x*fov)/zp1+cx,y:(rp1.y*fov)/zp1+cy,z:1/zp1,wx:rp1.x,wy:rp1.y,wz:rp1.z},
- p2_scr={x:(rp2.x*fov)/zp2+cx,y:(rp2.y*fov)/zp2+cy,z:1/zp2,wx:rp2.x,wy:rp2.y,wz:rp2.z};
- if((p1_scr.x-p0_scr.x)*(p2_scr.y-p0_scr.y)-(p1_scr.y-p0_scr.y)*(p2_scr.x-p0_scr.x)>=0)continue;
- let rn0=rotY(rotX(v0.normal,angX),angY),rn1=rotY(rotX(v1.normal,angX),angY),rn2=rotY(rotX(v2.normal,angX),angY);
- tri3d(p0_scr,rn0,p1_scr,rn1,p2_scr,rn2,lp,vp);
- }
- };
- drawMesh(sphereIndices,sphereVertices,-1);
- drawMesh(cubeIndices,cubeVertices,1);
- scrollerText("Everything you see here is pure unfiltered slop, but having something is better than nothing... probably?",4,0xFFFFFFFF);
- scrollerText("Why isn't there a minimal website dedicated to similar projects like these at least? I'd like to see what other people would come up with. It would be a very nice gallery.",10,0xFFFFFFFF,100);
- for(let i=0;i<4;i++){
- let c=0xFF000000|(floor((i/4)*255)*0x010101);
- vectorText("Woah, this looks\nfucking awful!",4,36-t*.03,2+sqrt(t)*(.02+i*.03),c);
- }
- vectorText("Woah, this looks\nfucking awful!",4,36,2,0xFFFFFFFF);
- //---
- ctx.putImageData(imgDat,0,0);
- pmouseX=mouseX;pmouseY=mouseY;pmouseDown=mouseDown;
- frame++;requestAnimationFrame(render);
- }
- requestAnimationFrame(render);
- </script></body></html>
Advertisement
Add Comment
Please, Sign In to add comment