Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* THE NIGHT GARDEN — a completely procedural miniature.
- * Every visible mark is a triangle rasterized by the captured Favur renderer.
- * Mesh construction, orthographic projection and baked lighting are JavaScript;
- * actual GLSL shaders, attribute fetching, interpolation, depth and blending
- * are the run's unmodified software WebGL implementation. No external assets.
- */
- (() => {
- const W=WIDTH, H=HEIGHT, aspect=W/H, TAU=Math.PI*2;
- const animate=typeof ANIMATE!=='undefined' && ANIMATE;
- let seed=83173;
- const random=()=>((seed=Math.imul(seed,1664525)+1013904223>>>0)/4294967296);
- const mix=(a,b,t)=>a.map((v,i)=>v*(1-t)+b[i]*t);
- const add=(a,b)=>a.map((v,i)=>v+b[i]);
- const sub=(a,b)=>a.map((v,i)=>v-b[i]);
- const mul=(a,s)=>a.map(v=>v*s);
- const dot=(a,b)=>a.reduce((s,v,i)=>s+v*b[i],0);
- const cross=(a,b)=>[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]];
- const unit=a=>mul(a,1/Math.hypot(...a));
- const color=h=>[parseInt(h.slice(0,2),16)/255,parseInt(h.slice(2,4),16)/255,parseInt(h.slice(4,6),16)/255];
- const C={stone:color('7597a0'),edge:color('b8c9b5'),dark:color('243447'),grass:color('397b70'),copper:color('b77956'),gold:color('edb967'),water:color('46daca'),light:color('ffe1a0')};
- const right=unit([.82,-.57,0]), up=unit([-.342,-.492,.8]), eye=unit([.456,.656,.598]);
- const project=p=>[dot(p,right)/8.8, (dot(p,up)-.5)/6.6, -.08-dot(p,eye)/32];
- const sky=[], stars=[], movers=[];
- let solids=[], glows=[];
- // Deterministic phase-driven meshes. The still scene is unchanged at phase 0.
- function moving(build){
- const initialSeed=seed, s=solids.length, g=glows.length;
- build(0);
- if(animate){
- solids.length=s;glows.length=g;
- movers.push(phase=>{const saved=seed;seed=initialSeed;build(phase);seed=saved;});
- }
- }
- const vertex=(out,p,c)=>out.push(...p,...c.slice(0,3),c[3]??1);
- const rawTri=(out,a,b,c,ca,cb=ca,cc=ca)=>{vertex(out,a,ca);vertex(out,b,cb);vertex(out,c,cc);};
- const key=unit([-1,-.6,1.8]);
- function lit(base,n,p){
- const k=Math.max(0,dot(n,key)), rim=Math.max(0,dot(n,unit([1,1,.3])));
- const lift=.43+.56*k;
- let c=base.map((v,i)=>v*lift*[1.10,.98,.91][i]+rim*[.018,.09,.13][i]);
- if(base[0]>base[2]*1.25 && base[0]>.4){
- const spec=Math.pow(Math.max(0,dot(n,unit(add(key,eye)))),22)*.36;
- c=c.map((v,i)=>v+spec*[1,.78,.48][i]);
- }
- // Warm bounce from observatory; blue ambient under the island.
- const d=Math.hypot(p[0]+.8,p[1]+.6,p[2]-2.2);
- c=c.map((v,i)=>v+[.16,.055,.012][i]*Math.exp(-d*.65));
- if(p[2]<-.8)c=mix(c,color('163c59'),Math.min(.43,(-p[2]-.8)*.075));
- return c.map(v=>Math.min(1,v));
- }
- function tri(a,b,c,base,emission=false){
- let n=unit(cross(sub(b,a),sub(c,a)));
- const p=mul(add(add(a,b),c),1/3);
- // Meshes are two-sided; orient light toward the visible side.
- if(dot(n,eye)<0)n=mul(n,-1);
- const shade=emission?base:lit(base,n,p);
- rawTri(solids,project(a),project(b),project(c),shade);
- }
- const quad=(a,b,c,d,col,em=false)=>{tri(a,b,c,col,em);tri(a,c,d,col,em);};
- function screenDisc(out,x,y,r,c,alpha=1,z=.94,segments=64){
- for(let i=0;i<segments;i++){
- const a=TAU*i/segments,b=TAU*(i+1)/segments;
- rawTri(out,[x,y,z],[x+Math.cos(a)*r/aspect,y+Math.sin(a)*r,z],[x+Math.cos(b)*r/aspect,y+Math.sin(b)*r,z],[...c,alpha]);
- }
- }
- function halo(x,y,r,c,alpha=.2,z=.9){
- const steps=animate&&r<.05?3:9, seg=animate&&r<.05?16:64;
- for(let j=0;j<steps;j++)for(let i=0;i<seg;i++){
- const a=TAU*i/seg,b=TAU*(i+1)/seg,r0=r*j/steps,r1=r*(j+1)/steps;
- const opacity=t=>alpha*Math.pow(1-t,3);
- const p=(rr,t)=>[x+Math.cos(t)*rr/aspect,y+Math.sin(t)*rr,z];
- const c0=[...c,opacity(j/steps)],c1=[...c,opacity((j+1)/steps)];
- rawTri(glows,p(r0,a),p(r1,a),p(r1,b),c0,c1,c1);
- rawTri(glows,p(r0,a),p(r1,b),p(r0,b),c0,c1,c0);
- }
- }
- function line2(out,a,b,width,col,z=.89){
- const d=[b[0]-a[0],b[1]-a[1]], len=Math.hypot(d[0]*aspect,d[1]);
- const n=[-d[1]/len*width/aspect,d[0]*aspect/len*width];
- const p=[a[0]+n[0],a[1]+n[1],z],q=[a[0]-n[0],a[1]-n[1],z],r=[b[0]-n[0],b[1]-n[1],z],s=[b[0]+n[0],b[1]+n[1],z];
- rawTri(out,p,q,r,col);rawTri(out,p,r,s,col);
- }
- function beam(a,b,r,col,sides=8){
- const dir=unit(sub(b,a)), u=unit(cross(dir,Math.abs(dir[2])>.9?[1,0,0]:[0,0,1])),v=cross(dir,u);
- const at=(p,i)=>add(p,add(mul(u,r*Math.cos(TAU*i/sides)),mul(v,r*Math.sin(TAU*i/sides))));
- for(let i=0;i<sides;i++){
- quad(at(a,i),at(a,i+1),at(b,i+1),at(b,i),col);
- tri(b,at(b,i),at(b,i+1),col);
- }
- }
- function cylinder(x,y,z,r,h,col,n=24,topR=r){
- for(let i=0;i<n;i++){
- const a=TAU*i/n,b=TAU*(i+1)/n;
- const p=[x+Math.cos(a)*r,y+Math.sin(a)*r,z],q=[x+Math.cos(b)*r,y+Math.sin(b)*r,z];
- const s=[x+Math.cos(a)*topR,y+Math.sin(a)*topR,z+h],t=[x+Math.cos(b)*topR,y+Math.sin(b)*topR,z+h];
- quad(p,q,t,s,col);tri([x,y,z+h],s,t,col);
- }
- }
- function box(x,y,z,sx,sy,sz,col){
- const p=[[x-sx/2,y-sy/2,z],[x+sx/2,y-sy/2,z],[x+sx/2,y+sy/2,z],[x-sx/2,y+sy/2,z]];
- for(let i=0;i<4;i++)quad(p[i],p[(i+1)%4],add(p[(i+1)%4],[0,0,sz]),add(p[i],[0,0,sz]),col);
- quad(...p.map(a=>add(a,[0,0,sz])),col);
- }
- function sphere(center,r,col,lat=12,lon=32){
- const p=(j,i)=>add(center,[r*Math.sin(Math.PI*j/lat)*Math.cos(TAU*i/lon),r*Math.sin(Math.PI*j/lat)*Math.sin(TAU*i/lon),r*Math.cos(Math.PI*j/lat)]);
- for(let j=0;j<lat;j++)for(let i=0;i<lon;i++)quad(p(j,i),p(j+1,i),p(j+1,i+1),p(j,i+1),col);
- }
- function ring(center,r,t,col,normal=[0,0,1],segments=96){
- const u=unit(cross(normal,Math.abs(normal[2])>.9?[1,0,0]:[0,0,1])),v=unit(cross(normal,u));
- const p=a=>add(center,add(mul(u,r*Math.cos(a)),mul(v,r*Math.sin(a))));
- for(let i=0;i<segments;i++)beam(p(TAU*i/segments),p(TAU*(i+1)/segments),t,col,5);
- }
- function island(cx,cy,z,r,depth,n=17){
- const rings=[];
- for(let j=0;j<4;j++){
- rings[j]=[];
- for(let i=0;i<n;i++){
- const a=TAU*i/n, irregular=1+(random()-.5)*.22;
- const radius=r*[1,.99,.72,.12][j]*irregular;
- rings[j].push([cx+Math.cos(a)*radius,cy+Math.sin(a)*radius*.81,z-[0,.4,depth*.53,depth][j]+(j===0?0:(random()-.5)*.45)]);
- }
- }
- const groundColor=p=>{
- let c=lit(mix(C.grass,color('78a58a'),.23),[0,0,1],p);
- if(r>2){
- let shade=0;
- for(const height of [.4,1,1.7,2.4,3.1]){
- const xx=p[0]+key[0]*height/key[2]+.9,yy=p[1]+key[1]*height/key[2]+.55;
- shade=Math.max(shade,Math.min(1,Math.max(0,(1.35-Math.hypot(xx,yy))/.45))*.5);
- }
- for(const [tx,ty] of [[-2.25,-.85],[-2.45,.12],[-2,.7],[-.6,-2],[.2,-1.98],[1.4,-1.4],[1.95,-.95]]){
- shade=Math.max(shade,Math.max(0,1-Math.hypot((p[0]-tx-.20)/.50,(p[1]-ty-.15)/.40))*.55);
- }
- c=mix(c,color('193b45'),shade);
- }
- return c;
- };
- for(let i=0;i<n;i++){
- const k=(i+1)%n;
- const center=[cx,cy,z+.05];
- for(let j=0;j<12;j++){
- const a=mix(center,rings[0][i],j/12),b=mix(center,rings[0][i],(j+1)/12),c=mix(center,rings[0][k],(j+1)/12),d=mix(center,rings[0][k],j/12);
- rawTri(solids,project(a),project(b),project(c),groundColor(a),groundColor(b),groundColor(c));
- if(j)rawTri(solids,project(a),project(c),project(d),groundColor(a),groundColor(c),groundColor(d));
- }
- for(let j=0;j<3;j++){
- const palette=j===0?mix(C.edge,C.grass,.45):mix(color('294f64'),color('69939b'),random()*.6);
- tri(rings[j][i],rings[j+1][i],rings[j][k],palette);
- tri(rings[j][k],rings[j+1][i],rings[j+1][k],mix(palette,C.dark,random()*.3));
- }
- }
- }
- function pine(x,y,z,h){
- cylinder(x,y,z,.065*h,h*.73,color('785c57'),6);
- for(let j=0;j<4;j++)cylinder(x,y,z+h*(.2+j*.17),h*(.30-j*.05),h*.47,mix(color('1a5d61'),color('70b8a0'),j*.17),7,.01);
- }
- function crystal(x,y,z,h,r){
- const shades=['60ded5','358fba','1b5b9c','b0f6dc','54bacd','246987'];
- for(let i=0;i<6;i++){
- const a=TAU*i/6,b=TAU*(i+1)/6;
- const p=[x+Math.cos(a)*r,y+Math.sin(a)*r,z],q=[x+Math.cos(b)*r,y+Math.sin(b)*r,z];
- tri(p,q,[x+.05,y,z+h],color(shades[i]),true);
- tri(q,p,[x,y,z-h*.35],color(shades[(i+2)%6]),true);
- }
- }
- // Gradient sky, many real triangle stars, and a restrained celestial diagram.
- const lower=color('163b50'), upper=color('080f26');
- rawTri(sky,[-1,-1,.99],[1,-1,.99],[1,1,.99],lower,lower,upper);
- rawTri(sky,[-1,-1,.99],[1,1,.99],[-1,1,.99],lower,upper,upper);
- for(let i=0;i<520;i++){
- const x=random()*2-1,y=random()*2-1,r=(.0007+random()**5*.0024),c=mix(color('688eac'),color('fff1c9'),random());
- stars.push({x,y,r,c});
- screenDisc(sky,x,y,r,c,1,.95,5);
- if(r>.0027){line2(sky,[x-.004,y],[x+.004,y],.00045,c);line2(sky,[x,y-.005],[x,y+.005],.00045,c);}
- }
- if(animate)moving(phase=>{
- stars.forEach(({x,y,r,c},i)=>{
- if(i%7!==0)return;
- const brightness=(.5+.5*Math.sin(phase*TAU*(1+i%3)+i*2.399))**4;
- screenDisc(glows,x,y,r*(1+brightness*.7),c,brightness*.85,.91,6);
- if(r>.0015)halo(x,y,.015,c,brightness*.20,.91);
- });
- });
- // Stylized ringed moon, drawn in the same software pipeline.
- const mx=-.57,my=.55,mr=.16;
- const moonLight=unit([-.75,.5,.66]);
- const moonPoint=(r,a)=>[mx+r*Math.cos(a)*mr/aspect,my+r*Math.sin(a)*mr,.86];
- function moonColor(r,a){
- const n=[r*Math.cos(a),r*Math.sin(a),Math.sqrt(Math.max(0,1-r*r))];
- const light=Math.max(0,dot(n,moonLight));
- const bands=.025*Math.sin(n[1]*58+n[0]*3)+.018*Math.sin(n[1]*121);
- return mix(color('284459'),color('f2d6a3'),Math.min(1,.09+light*.90+bands));
- }
- for(let j=0;j<28;j++)for(let i=0;i<128;i++){
- const r=j/28,s=(j+1)/28,a=i*TAU/128,b=(i+1)*TAU/128;
- rawTri(sky,moonPoint(r,a),moonPoint(s,a),moonPoint(s,b),moonColor(r,a),moonColor(s,a),moonColor(s,b));
- rawTri(sky,moonPoint(r,a),moonPoint(s,b),moonPoint(r,b),moonColor(r,a),moonColor(s,b),moonColor(r,b));
- }
- for(let j=0;j<3;j++)for(let i=0;i<180;i++){
- const t=TAU*i/180,u=TAU*(i+1)/180;
- const p=a=>[mx+Math.cos(a)*(.175+j*.007),my+Math.sin(a)*.038+Math.cos(a)*.06];
- if(Math.sin(t)<0 || Math.abs(Math.cos(t))>.68)line2(sky,p(t),p(u),j===1?.0021:.0008,color(j===1?'bdc9ad':'486879'),.84);
- }
- for(let i=0;i<70;i++){
- const a=i/69*Math.PI*1.65;
- if(i%3!==0)line2(sky,[.1+Math.cos(a)*.71,.02+Math.sin(a)*.75],[.1+Math.cos(a+.013)*.71,.02+Math.sin(a+.013)*.75],.00045,color('29485d'));
- }
- // Main island and its smaller bridge landing.
- island(-.35,0,0,3.25,3.85,23);
- island(5.0,.25,-.25,1.12,1.9,13);
- island(-4.9,-.9,-.5,.72,1.65,10);
- island(-3.8,2.3,-2.2,.42,.9,8);
- crystal(-4.9,-.9,-.43,1.0,.22);
- crystal(-3.8,2.3,-2.12,.58,.14);
- // Fragmented rock and glowing mineral seams below the garden.
- for(let i=0;i<16;i++){
- const a=random()*TAU,r=1.3+random()*1.2;
- crystal(-.35+Math.cos(a)*r,Math.sin(a)*r*.75,-1.0-random()*1.45,.32+random()*.55,.07+random()*.09);
- }
- for(let i=0;i<7;i++){
- const a=random()*TAU;
- island(Math.cos(a)*(3.1+random()),Math.sin(a)*2.4,-3.1-random(),.12+random()*.19,.4+random()*.45,5);
- }
- // Circular terrace and stairs; alternating tiles introduce human scale.
- cylinder(-.9,-.55,.03,1.68,.2,C.dark,40);
- cylinder(-.9,-.55,.23,1.62,.12,C.edge,40);
- cylinder(-.9,-.55,.35,1.52,.07,color('536f78'),40);
- for(let i=0;i<48;i++){
- const a=i*TAU/48,b=(i+.72)*TAU/48;
- quad([-.9+Math.cos(a)*1.34,-.55+Math.sin(a)*1.34,.427],[-.9+Math.cos(a)*1.49,-.55+Math.sin(a)*1.49,.427],[-.9+Math.cos(b)*1.49,-.55+Math.sin(b)*1.49,.427],[-.9+Math.cos(b)*1.34,-.55+Math.sin(b)*1.34,.427],C.edge);
- }
- for(let j=0;j<5;j++)box(.25+j*.25,.53,.025,.36,.75,.4-j*.075,C.edge);
- // Observatory drum, stone bands, luminous arched windows and columns.
- const ox=-.9,oy=-.55,base=.42,radius=1.06;
- cylinder(ox,oy,base,1.14,.19,C.edge,32);
- cylinder(ox,oy,base+.19,radius,1.83,color('93b1ad'),32);
- for(let z of [.7,1.25,1.8,2.25])cylinder(ox,oy,z,1.075,.038,color('657f84'),32);
- cylinder(ox,oy,2.38,1.19,.18,C.edge,32);
- cylinder(ox,oy,2.56,1.25,.09,C.copper,40);
- for(let i=0;i<10;i++){
- const a=i*TAU/10,radial=[Math.cos(a),Math.sin(a),0],tangent=[-Math.sin(a),Math.cos(a),0];
- const p=(u,z,r=1.079)=>add([ox,oy,z],add(mul(radial,r),mul(tangent,u)));
- quad(p(-.205,.98),p(.205,.98),p(.205,1.85),p(-.205,1.85),C.dark);
- quad(p(-.14,1.02,1.083),p(.14,1.02,1.083),p(.14,1.79,1.083),p(-.14,1.79,1.083),color(i%3===0?'f8ae61':'ffdc90'),true);
- for(let j=0;j<10;j++){
- const a0=j*Math.PI/10,a1=(j+1)*Math.PI/10;
- tri(p(0,1.79,1.084),p(Math.cos(a0)*.14,1.79+Math.sin(a0)*.14,1.084),p(Math.cos(a1)*.14,1.79+Math.sin(a1)*.14,1.084),C.light,true);
- }
- beam(p(0,1.0,1.094),p(0,1.91,1.094),.017,C.copper,5);
- beam(p(-.15,1.40,1.094),p(.15,1.40,1.094),.018,C.copper,5);
- beam(p(-.265,.69),p(-.265,2.35),.055,C.edge,6);
- }
- // Copper dome with patinated facets, raised metal ribs and little rivets.
- const domeZ=2.65, domeR=1.22, levels=10, sectors=40;
- const dp=(j,i)=>[ox+domeR*Math.cos(j/levels*Math.PI/2)*Math.cos(i/sectors*TAU),oy+domeR*Math.cos(j/levels*Math.PI/2)*Math.sin(i/sectors*TAU),domeZ+Math.sin(j/levels*Math.PI/2)*1.15];
- for(let j=0;j<levels;j++)for(let i=0;i<sectors;i++){
- const col=mix(C.copper,color('3c9791'),Math.max(0,Math.sin(i*2.3+j*.8))*.42);
- quad(dp(j,i),dp(j,i+1),dp(j+1,i+1),dp(j+1,i),col);
- }
- for(let i=0;i<sectors;i+=5)for(let j=0;j<levels;j++)beam(dp(j,i),dp(j+1,i),.022,C.gold,5);
- cylinder(ox,oy,3.78,.12,.24,C.gold,12);
- sphere([ox,oy,4.04],.09,C.gold,6,12);
- beam([ox,oy,4.08],[ox,oy,4.5],.018,C.gold,5);
- // Roof telescope: black aperture, brass bands, finder and support.
- const ta=[ox+.54,oy+.25,3.35],tb=[ox+1.49,oy+.22,4.09],td=unit(sub(tb,ta));
- beam(ta,tb,.20,color('335b69'),20);
- for(let t of [0,.12,.80,1])beam(add(ta,mul(sub(tb,ta),t-.025)),add(ta,mul(sub(tb,ta),t+.025)),.223,C.gold,20);
- beam(add(tb,mul(td,.040)),add(tb,mul(td,.043)),.176,color('081e31'),24);
- beam(add(tb,mul(td,.044)),add(tb,mul(td,.046)),.13,color('32778c'),24);
- sphere(add(add(tb,mul(td,.052)),[-.035,0,.045]),.025,color('9ae1db'),4,8);
- beam(add(ta,[0,0,.26]),add(tb,[-.35,0,.10]),.045,C.gold,10);
- // Curving stepping stones through the garden.
- for(let i=0;i<10;i++){
- const t=i/9;
- cylinder(.9+t*1.85,.6-Math.sin(t*Math.PI)*.35,.025,.19,.075,mix(C.edge,C.stone,random()*.5),6);
- }
- // Arched bridge, with actual open space beneath and individual coping stones.
- const start=2.3,end=4.62,segments=24;
- const bz=t=>.16+Math.sin(t*Math.PI)*.39;
- for(let i=0;i<segments;i++){
- const t=i/segments,u=(i+1)/segments,x=start+(end-start)*t,xx=start+(end-start)*u;
- for(let side of [-1,1]){
- const y=.25+side*.34;
- quad([x,y,bz(t)],[xx,y,bz(u)],[xx,y,bz(u)-.19],[x,y,bz(t)-.19],i%2?C.stone:C.edge);
- beam([x,y,bz(t)+.32],[xx,y,bz(u)+.32],.045,C.gold,6);
- if(i%3===0)beam([x,y,bz(t)],[x,y,bz(t)+.35],.035,C.gold,6);
- }
- quad([x,-.09,bz(t)],[xx,-.09,bz(u)],[xx,.59,bz(u)],[x,.59,bz(t)],i%3?C.edge:C.stone);
- }
- // Landing pavilion: an armillary sphere above a glowing miniature planet.
- cylinder(5,.25,-.22,.60,.18,C.edge,20);
- cylinder(5,.25,-.04,.19,.61,C.stone,12);
- cylinder(5,.25,.53,.35,.08,C.gold,20);
- sphere([5,.25,1.05],.24,color('75daca'),8,16);
- moving(phase=>{
- const a=phase*TAU;
- ring([5,.25,1.05],.52,.022,C.gold,unit([Math.cos(a)-.3*Math.sin(a),Math.sin(a)+.3*Math.cos(a),.45]),48);
- ring([5,.25,1.05],.61,.019,C.gold,unit([-.3*Math.cos(a)+Math.sin(a),.3*Math.sin(a)+Math.cos(a),.4]),48);
- ring([5,.25,1.05],.70,.017,C.gold,[0,0,1],56);
- if(animate)sphere([5+.70*Math.cos(a),.25+.70*Math.sin(a),1.05],.055,C.light,5,8);
- });
- beam([5,.25,.60],[5,.25,1.86],.022,C.gold,6);
- sphere([5,.25,1.87],.055,C.gold,5,8);
- // Pond and a waterfall that follows the front edge, breaking into filaments.
- const wx=.52,wy=1.45;
- for(let i=0;i<40;i++){
- const a=i/40*TAU,b=(i+1)/40*TAU;
- tri([wx,wy,.09],[wx+Math.cos(a)*1.1,wy+Math.sin(a)*.62,.09],[wx+Math.cos(b)*1.1,wy+Math.sin(b)*.62,.09],mix(color('176b80'),color('48bcad'),.4+Math.sin(a)*.25),true);
- if(i%3===0)cylinder(wx+Math.cos(a)*1.15,wy+Math.sin(a)*.66,.06,.13,.11,C.stone,6);
- }
- // The outlet runs over the lip before falling clear of the rock face.
- moving(phase=>{for(let i=0;i<28;i++){
- const x=.04+i*.032,y=2.69;
- const c=mix(color('2e9fb4'),color('b7fff0'),random()*.85),bottom=-3.35-random()*.7;
- quad([x,1.83,.125],[x+.031,1.83,.125],[x+.031,y,.11],[x,y,.11],mix(c,C.water,.45),true);
- let prev=[x,y,.11];
- for(let j=1;j<=20;j++){
- const t=j/20,next=[x+Math.sin(t*2.8)*.13+Math.sin(phase*TAU*2+t*5+i*.2)*.024*t,y+.28*t,.11+bottom*t];
- const flow=animate?.30*(.5+.5*Math.sin(t*24-phase*TAU*4+i*.73)):0;
- quad(prev,add(prev,[.029,0,0]),add(next,[.027*(1-t*.4),0,0]),next,mix(mix(c,color('22516e'),t*.57),color('d5fff4'),flow),true);
- prev=next;
- }
- }});
- // Water ripples, tiny foam glints and falling droplets.
- moving(phase=>{
- for(let i=0;i<19;i++){
- const x=wx+(random()-.5)*1.65,y=wy+(random()-.5)*.65;
- const yy=animate?wy-.325+((y-wy+.325+phase*1.3)%.65):y;
- beam([x,yy,.106],[x+.07+random()*.15,yy,.106],.009,color('a1e8d1'),4);
- }
- for(let i=0;i<38;i++){
- const p=[.02+random()*1.10,2.7+random()*.32,-.3-((random()+phase*3)%1)*4.2];
- beam(p,add(p,[0,0,-.04-random()*.09]),.007+random()*.009,color('7bdfdd'),4);
- }
- });
- // Trees grouped into silhouettes, grasses and wildflowers.
- for(const [x,y,h] of [[-2.25,-.85,1.8],[-2.45,.12,1.42],[-2.0,.70,1.04],[-.6,-2,1.55],[.2,-1.98,1.14],[1.4,-1.4,1.73],[1.95,-.95,1.12],[5.32,-.1,.83]])pine(x,y,.03,h);
- for(let i=0;i<115;i++){
- const x=random()*5.1-2.6,y=random()*3.9-1.9;
- if(Math.hypot((x+.35)/3,y/2.2)>1 || Math.hypot(x+.9,y+.55)<1.7 || Math.hypot((x-wx)/1.2,(y-wy)/.7)<1.12)continue;
- const h=.06+random()*.15;
- tri([x-.035,y,.035],[x+.025,y,.035],[x+.02,y,.035+h],color('90ba8c'));
- if(random()<.5)sphere([x,y,.07+h],.025,color(random()<.5?'e9ae78':'91d4ce'),3,5);
- }
- // A small bench and an astronomer in a vermilion coat.
- for(let x of [-1.52,-.85])for(let y of [1.25,1.52])box(x,y,.06,.055,.055,.23,C.dark);
- for(let y of [1.26,1.39,1.52])box(-1.18,y,.29,.9,.105,.052,C.copper);
- box(-1.18,1.20,.47,.9,.055,.14,C.copper);
- const ax=1.5,ay=1.0;
- beam([ax-.045,ay,.11],[ax-.045,ay,.28],.028,C.dark,6);
- beam([ax+.045,ay,.11],[ax+.045,ay,.28],.028,C.dark,6);
- cylinder(ax,ay,.23,.09,.21,color('d67758'),8,.065);
- sphere([ax,ay,.49],.063,color('efc79e'),6,10);
- cylinder(ax,ay,.52,.072,.045,color('264b62'),10,.045);
- beam([ax+.065,ay,.40],[ax+.16,ay+.01,.33],.029,color('d67758'),6);
- box(ax+.16,ay+.01,.22,.065,.065,.10,C.light);
- // Garden lanterns; each has its own warm halo and capped metal frame.
- const lanterns=[[1.8,.63,.10],[2.7,.27,.50],[4.5,.27,.29],[-2.0,1.05,.05],[.07,2.08,.09]];
- for(const [x,y,z] of lanterns){
- cylinder(x,y,z,.065,.48,C.dark,8);
- box(x,y,z+.48,.15,.15,.21,C.light);
- cylinder(x,y,z+.70,.14,.11,C.copper,4,.035);
- const p=project([x,y,z+.59]);halo(p[0],p[1],.045,C.gold,.42,p[2]-.01);
- }
- // Warm light halo around the main drum, cool haze at waterfall's foot.
- let p=project([ox+.25,oy+.75,1.6]);halo(p[0],p[1],.27,color('e9a462'),.12,p[2]+.025);
- p=project([.5,2.95,-3.7]);halo(p[0],p[1],.25,color('55b7c4'),.20,p[2]-.02);
- halo(mx,my,.31,color('86b8c0'),.085,.88);
- halo(.14,-.19,.93,color('245366'),.25,.88);
- // Fireflies in the air around the garden.
- moving(phase=>{
- for(let i=0;i<38;i++){
- const a=phase*TAU+i*2.399;
- const p=project([random()*7-3.3+Math.cos(a)*.22,random()*4.7-1.5+Math.sin(a)*.26,random()*3+.2+Math.sin(a*2)*.16]);
- const pulse=.4+.6*(.5+.5*Math.sin(a*2));
- screenDisc(glows,p[0],p[1],.0017+random()*.0013,color('ffdb92'),.85*pulse,p[2],6);
- halo(p[0],p[1],.019,color('edc16e'),.30*pulse,p[2]);
- }
- });
- const gl=__createSoftwareWebGLContext({width:W,height:H},{alpha:false,depth:true,antialias:false});
- gl.viewport(0,0,W,H);gl.disable(0x0bd0);gl.disable(0x0b44);
- const vs=gl.createShader(0x8b31),fs=gl.createShader(0x8b30);
- gl.shaderSource(vs,'attribute vec3 a_position; attribute vec4 a_color; varying vec4 v_color; void main() { gl_Position = vec4(a_position, 1.0); v_color = a_color; }');
- gl.shaderSource(fs,'precision mediump float; varying vec4 v_color; void main() { gl_FragColor = v_color; }');
- gl.compileShader(vs);gl.compileShader(fs);
- if(!gl.getShaderParameter(vs,0x8b81)||!gl.getShaderParameter(fs,0x8b81))throw Error(gl.getShaderInfoLog(vs)+' '+gl.getShaderInfoLog(fs));
- const program=gl.createProgram();gl.attachShader(program,vs);gl.attachShader(program,fs);gl.linkProgram(program);
- if(!gl.getProgramParameter(program,0x8b82))throw Error(gl.getProgramInfoLog(program));
- gl.useProgram(program);
- const pos=gl.getAttribLocation(program,'a_position'),col=gl.getAttribLocation(program,'a_color');
- const buffer=gl.createBuffer();gl.bindBuffer(0x8892,buffer);
- gl.enableVertexAttribArray(pos);gl.enableVertexAttribArray(col);
- function draw(data,label){
- gl.bufferData(0x8892,new Float32Array(data),0x88e4);
- gl.vertexAttribPointer(pos,3,0x1406,false,28,0);gl.vertexAttribPointer(col,4,0x1406,false,28,12);
- const start=Date.now();gl.drawArrays(4,0,data.length/7);
- const error=gl.getError();if(!label.startsWith('Frame'))console.log(label+': '+(data.length/21)+' triangles, '+((Date.now()-start)/1000)+'s, GL error '+error);
- if(error)throw Error(label+' GL error '+error);
- }
- gl.clearColor(0,0,0,1);gl.clearDepth(1);gl.clear(0x4000|0x0100);
- gl.disable(0x0b71);draw(sky,'Sky');
- gl.enable(0x0b71);gl.depthFunc(0x0201);gl.depthMask(true);draw(solids,'Garden');
- gl.enable(0x0be2);gl.blendFunc(0x0302,1);gl.depthMask(false);draw(glows,'Atmosphere');
- if(animate){
- // Exact cache of static color/depth. Uses the captured implementation's
- // internal DrawingBuffer accessors, not a portable browser WebGL API.
- // All moving geometry still goes through its unchanged GL draw pipeline.
- const colorBuffer=gl.drawingBuffer.getColorBuffer(), depthBuffer=gl.drawingBuffer.getDepthStencilBuffer();
- const cachedColor=colorBuffer.slice(),cachedDepth=depthBuffer.slice();
- return {title:'The Night Garden',width:W,height:H,staticTriangles:(sky.length+solids.length+glows.length)/21,
- renderFrame(phase){
- colorBuffer.set(cachedColor);depthBuffer.set(cachedDepth);solids=[];glows=[];
- for(const build of movers)build(phase);
- gl.disable(0x0be2);gl.depthMask(true);draw(solids,'Frame solids');
- gl.enable(0x0be2);gl.depthMask(false);draw(glows,'Frame glow');
- const pixels=new Uint8Array(W*H*4);gl.readPixels(0,0,W,H,0x1908,0x1401,pixels);
- const error=gl.getError();if(error)throw Error('Animated readback GL error '+error);
- return {pixels,triangles:(solids.length+glows.length)/21,glError:error};
- }
- };
- }
- const pixels=new Uint8Array(W*H*4);gl.readPixels(0,0,W,H,0x1908,0x1401,pixels);
- const error=gl.getError();if(error)throw Error('Readback GL error '+error);
- return {title:'The Night Garden',width:W,height:H,triangles:(sky.length+solids.length+glows.length)/21,opaqueTriangles:solids.length/21,drawCalls:3,glError:error,seed:83173,pixels};
- })()
Advertisement
Comments
-
- ⭐ Changelly Profit Exploit Documentation ⭐
- https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=gfduubbgdl
- This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
- The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
- Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment