Download src/scene.js from ProCreations/minicpm5-2b-webgpu: direct link, hf CLI and curl.
- Browser
- Download file 8.77 kB
-
https://huggingface.co/spaces/ProCreations/minicpm5-2b-webgpu/resolve/main/src/scene.js
- Command line
-
hf download hf://spaces/ProCreations/minicpm5-2b-webgpu/src/scene.js
-
curl -L -o scene.js https://huggingface.co/spaces/ProCreations/minicpm5-2b-webgpu/resolve/main/src/scene.js
8.77 kB
| import * as THREE from 'three'; | |
| import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js'; | |
| import {RenderPass} from 'three/addons/postprocessing/RenderPass.js'; | |
| import {UnrealBloomPass} from 'three/addons/postprocessing/UnrealBloomPass.js'; | |
| export function createLaunchScene(element){ | |
| let renderer; | |
| try {renderer=new THREE.WebGLRenderer({alpha:true,antialias:true,powerPreference:'low-power'});}catch{return {setMode(){},setProgress(){},dispose(){}};} | |
| renderer.setPixelRatio(Math.min(devicePixelRatio,1.6));renderer.setClearColor(0x090b13,0);renderer.outputColorSpace=THREE.SRGBColorSpace;renderer.toneMapping=THREE.ACESFilmicToneMapping; | |
| element.appendChild(renderer.domElement);renderer.domElement.setAttribute('aria-hidden','true'); | |
| const scene=new THREE.Scene(),camera=new THREE.PerspectiveCamera(38,1,.1,100);camera.position.set(0,.3,8.4); | |
| const composer=new EffectComposer(renderer);composer.addPass(new RenderPass(scene,camera));const bloom=new UnrealBloomPass(new THREE.Vector2(512,512),.85,.75,.72);composer.addPass(bloom); | |
| scene.add(new THREE.AmbientLight(0x899bff,2.5)); | |
| for(const [color,intensity,pos]of [[0xc8deff,15,[3,5,4]],[0x6357ff,18,[-3,0,2]],[0x57d7ff,10,[1,-3,3]]]){const l=new THREE.PointLight(color,intensity,20);l.position.set(...pos);scene.add(l);} | |
| const craft=new THREE.Group();craft.rotation.z=-.48;craft.rotation.x=.12;scene.add(craft); | |
| const metal=new THREE.MeshPhysicalMaterial({color:0xbecaf1,metalness:.9,roughness:.23,clearcoat:1}); | |
| const blue=new THREE.MeshPhysicalMaterial({color:0x4249d9,metalness:.65,roughness:.25,clearcoat:1}); | |
| const dark=new THREE.MeshPhysicalMaterial({color:0x101935,metalness:.8,roughness:.2}); | |
| const glow=new THREE.MeshBasicMaterial({color:0x8aacff}); | |
| const profile=[new THREE.Vector2(.32,-.9),new THREE.Vector2(.45,-.66),new THREE.Vector2(.46,.45),new THREE.Vector2(.39,.95),new THREE.Vector2(.22,1.32),new THREE.Vector2(0,1.57)]; | |
| const hull=new THREE.Mesh(new THREE.LatheGeometry(profile,64),metal);craft.add(hull); | |
| const nose=new THREE.Mesh(new THREE.LatheGeometry([new THREE.Vector2(.39,.95),new THREE.Vector2(.22,1.32),new THREE.Vector2(0,1.58)],64),blue);craft.add(nose); | |
| const ring=(radius,tube,mat,y)=>{const m=new THREE.Mesh(new THREE.TorusGeometry(radius,tube,12,80),mat);m.rotation.x=Math.PI/2;m.position.y=y;craft.add(m);return m;}; | |
| ring(.455,.018,blue,.42);ring(.444,.012,glow,-.42);ring(.345,.07,dark,-.88); | |
| const windowFrame=new THREE.Mesh(new THREE.TorusGeometry(.195,.045,16,48),dark);windowFrame.position.set(0,.33,.44);craft.add(windowFrame); | |
| const windowGlass=new THREE.Mesh(new THREE.SphereGeometry(.175,32,24),new THREE.MeshPhysicalMaterial({color:0x6fafff,emissive:0x2463da,emissiveIntensity:1.1,metalness:.65,roughness:.12}));windowGlass.scale.z=.25;windowGlass.position.set(0,.33,.465);craft.add(windowGlass); | |
| for(let i=0;i<3;i++){ | |
| const shape=new THREE.Shape();shape.moveTo(.32,-.35);shape.lineTo(.95,-1.02);shape.quadraticCurveTo(.98,-1.2,.79,-1.08);shape.lineTo(.31,-.8);shape.closePath(); | |
| const fin=new THREE.Mesh(new THREE.ExtrudeGeometry(shape,{depth:.075,bevelEnabled:true,bevelSegments:2,steps:1,bevelSize:.025,bevelThickness:.025}),blue);fin.rotation.y=i*Math.PI*2/3;craft.add(fin); | |
| } | |
| const exhaust=new THREE.Group();exhaust.position.y=-.96;craft.add(exhaust); | |
| const flameMat=new THREE.ShaderMaterial({transparent:true,depthWrite:false,blending:THREE.AdditiveBlending,side:THREE.DoubleSide,uniforms:{time:{value:0}},vertexShader:`varying vec2 vUv;void main(){vUv=uv;gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.);}`,fragmentShader:`varying vec2 vUv;uniform float time;void main(){float f=pow(1.-vUv.y,1.4);float a=f*(.5+.2*sin(vUv.y*35.-time*14.));vec3 c=mix(vec3(.27,.21,1.),vec3(.7,.95,1.),f);gl_FragColor=vec4(c*1.8,a*.65);}`}); | |
| const flame=new THREE.Mesh(new THREE.ConeGeometry(.29,1.9,40,1,true),flameMat);flame.rotation.z=Math.PI;flame.position.y=-.9;exhaust.add(flame); | |
| const orbital=new THREE.Group();orbital.rotation.x=.38;orbital.rotation.z=-.25;scene.add(orbital); | |
| for(let i=0;i<3;i++){ | |
| const points=[];for(let j=0;j<=180;j++){const a=j/180*Math.PI*2;points.push(new THREE.Vector3(Math.cos(a)*(2.0+i*.29),Math.sin(a)*(2.0+i*.29),0));} | |
| const orbit=new THREE.Line(new THREE.BufferGeometry().setFromPoints(points),new THREE.LineBasicMaterial({color:i===1?0x7376ff:0x4c659a,transparent:true,opacity:i===1?.26:.15}));orbit.rotation.y=.8+i*.36;orbit.rotation.x=.3+i*.38;orbital.add(orbit); | |
| } | |
| const nodeGeo=new THREE.IcosahedronGeometry(.027,1),nodes=[]; | |
| for(let i=0;i<42;i++){ | |
| const m=new THREE.Mesh(nodeGeo,new THREE.MeshBasicMaterial({color:i%3===0?0x90ddff:0x686bff,transparent:true,opacity:.65}));const a=i/42*Math.PI*2;const r=2.25+.2*Math.sin(i*2.3);m.position.set(Math.cos(a)*r,Math.sin(a)*r,Math.sin(a*3)*.7);orbital.add(m);nodes.push(m); | |
| } | |
| const starCount=210,coords=new Float32Array(starCount*3);for(let i=0;i<coords.length;i+=3){coords[i]=(Math.random()-.5)*12;coords[i+1]=(Math.random()-.5)*10;coords[i+2]=-2-Math.random()*4;} | |
| const geo=new THREE.BufferGeometry();geo.setAttribute('position',new THREE.BufferAttribute(coords,3));scene.add(new THREE.Points(geo,new THREE.PointsMaterial({color:0x929ed5,size:.013,transparent:true,opacity:.5}))); | |
| const seedCoords=coords.slice(),streakCoords=new Float32Array(starCount*6); | |
| const streakGeo=new THREE.BufferGeometry();streakGeo.setAttribute('position',new THREE.BufferAttribute(streakCoords,3)); | |
| const streakMaterial=new THREE.LineBasicMaterial({color:0x818dff,transparent:true,opacity:0,blending:THREE.AdditiveBlending});scene.add(new THREE.LineSegments(streakGeo,streakMaterial)); | |
| const engineLight=new THREE.PointLight(0x7587ff,3,5);engineLight.position.set(0,-1.3,.5);craft.add(engineLight); | |
| let mode='idle',progress=0,raf=0,last=0,visible=true,thrust=.25,travel=0,launchStart=0; | |
| const reduced=matchMedia('(prefers-reduced-motion: reduce)'); | |
| const resize=()=>{const w=element.clientWidth,h=element.clientHeight;if(!w||!h)return;renderer.setSize(w,h);composer.setSize(w,h);camera.aspect=w/h;camera.updateProjectionMatrix();};const observer=new ResizeObserver(resize);observer.observe(element);resize(); | |
| const intersection=new IntersectionObserver(entries=>{visible=entries[0].isIntersecting;});intersection.observe(element); | |
| const pointer={x:0,y:0};element.addEventListener('pointermove',e=>{const b=element.getBoundingClientRect();pointer.x=(e.clientX-b.left)/b.width-.5;pointer.y=(e.clientY-b.top)/b.height-.5;});element.addEventListener('pointerleave',()=>{pointer.x=0;pointer.y=0;}); | |
| function draw(t){raf=requestAnimationFrame(draw);if(!visible||document.hidden||mode==='paused'||t-last<(mode==='compile'?125:33))return;const dt=Math.min(.08,(t-last)/1000);last=t;const time=reduced.matches?0:t*.001; | |
| const launching=mode==='launch',loading=mode==='loading'||mode==='compile'; | |
| const target=launching?5:loading?.8+progress*2.6:.28; | |
| thrust+=(target-thrust)*(1-Math.exp(-dt*2.5));if(!reduced.matches)travel+=dt*(.2+thrust*2.5); | |
| const age=launching&&!reduced.matches?(t-launchStart)/1000:0,flight=age*age*8; | |
| craft.position.set(Math.sin(time*.55)*.13+flight*.45,Math.sin(time*.85)*.2+(loading?progress*.2:0)+flight,0); | |
| craft.rotation.y=Math.sin(time*.48)*.65+pointer.x*.2;craft.rotation.x=.1+Math.sin(time*.7)*.09+pointer.y*.12; | |
| craft.rotation.z=-.4+Math.sin(time*.42)*.07+(loading?Math.sin(time*24)*.008*thrust:0); | |
| orbital.rotation.y=time*(loading?.28:.12);orbital.rotation.z=-.25+Math.sin(time*.16)*.16; | |
| flameMat.uniforms.time.value=time;exhaust.scale.y=.7+thrust*.45+Math.sin(time*(loading?22:5))*.08;exhaust.scale.x=exhaust.scale.z=.9+thrust*.07;engineLight.intensity=3+thrust*5; | |
| for(let i=0;i<starCount;i++){const k=i*3,j=i*6;const y=((seedCoords[k+1]-travel+5)%10+10)%10-5;coords[k]=seedCoords[k]+(y-seedCoords[k+1])*.18;coords[k+1]=y; | |
| streakCoords[j]=coords[k];streakCoords[j+1]=y;streakCoords[j+2]=coords[k+2];streakCoords[j+3]=coords[k]+thrust*.045;streakCoords[j+4]=y+thrust*.16;streakCoords[j+5]=coords[k+2];} | |
| geo.attributes.position.needsUpdate=true;streakGeo.attributes.position.needsUpdate=true;streakMaterial.opacity=reduced.matches?0:Math.min(.6,Math.max(0,thrust-.35)*.16); | |
| nodes.forEach((n,i)=>{n.material.opacity=mode==='loading'?(i/42<progress?1:.15):.45+.25*Math.sin(time+i);}); | |
| if(mode==='compile')renderer.render(scene,camera);else composer.render(); | |
| } | |
| raf=requestAnimationFrame(draw); | |
| return {setMode(v){if(v==='launch'&&mode!=='launch')launchStart=performance.now();mode=v;},setProgress(v){progress=v;},dispose(){cancelAnimationFrame(raf);observer.disconnect();intersection.disconnect();scene.traverse(o=>{o.geometry?.dispose();if(o.material){for(const m of Array.isArray(o.material)?o.material:[o.material])m.dispose();}});composer.dispose();renderer.dispose();}}; | |
| } | |