diff --git a/public/css/styles.css b/public/css/styles.css index cd05a59..ac8ae31 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -2,7 +2,7 @@ body { margin: 0; padding: 0; overflow: hidden; - background-color: whitesmoke; + background-color: rgb(255, 0, 0); } #container { diff --git a/public/images/cn-logo-green.png b/public/images/cn-logo-green.png new file mode 100644 index 0000000..e01b1a0 Binary files /dev/null and b/public/images/cn-logo-green.png differ diff --git a/public/images/cn-logo.png b/public/images/cn-logo.png new file mode 100644 index 0000000..dffd48b Binary files /dev/null and b/public/images/cn-logo.png differ diff --git a/public/index.html b/public/index.html index c5c3929..5c4fd77 100644 --- a/public/index.html +++ b/public/index.html @@ -15,6 +15,7 @@ } } +
@@ -22,4 +23,5 @@
+ diff --git a/public/js/main.js b/public/js/main.js index 924ad71..c4f9ccb 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -2,26 +2,40 @@ import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' import { Vector3 } from 'three' import { randFloat, randInt } from 'three/src/math/MathUtils.js' +import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js'; +import { RenderPixelatedPass } from 'three/addons/postprocessing/RenderPixelatedPass.js'; +import { OutputPass } from 'three/addons/postprocessing/OutputPass.js'; +import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; -let scene, camera, renderer +let scene, camera, renderer, composer let aspect, frustumSize let mesh let delta let controls +let gui, params +let instancedMesh, dummy, count, lastTime +let frames = []; +const totalFrames = 300; // Number of frames to capture +let frameCount = 0; +let iter = 0 + var clock = new THREE.Clock() +const matrix = new THREE.Matrix4() function init(){ SetupRenderer() scene = new THREE.Scene() scene.background = new THREE.Color('white') SetupCamera() + //AddLights() SetupControls() + SetupComposer() SetupObjects() animate() } function SetupRenderer(){ - renderer = new THREE.WebGLRenderer({ antialias: true }) + renderer = new THREE.WebGLRenderer({alpha: true}) renderer.setSize(window.innerWidth, window.innerHeight) document.getElementById('container').appendChild(renderer.domElement) } @@ -55,20 +69,122 @@ function SetupControls(){ controls.update() } +function AddLights() { + // Add Ambient Light + const ambientLight = new THREE.AmbientLight(0xFF0000, 5); // Soft white light + scene.add(ambientLight); + + // Add Directional Light + const directionalLight = new THREE.DirectionalLight(0xFF0000, 10); // Soft white light + directionalLight.position.set(-5, 0, 5).normalize(); + scene.add(directionalLight); +} + +function SetupComposer(){ + composer = new EffectComposer( renderer ) + const renderPixelPass = new RenderPixelatedPass( 8, scene, camera ) + renderPixelPass.normalEdgeStrength = 0 + renderPixelPass.depthEdgeStrength = 0 + composer.addPass( renderPixelPass ) + const outputPass = new OutputPass() + composer.addPass( outputPass ) + + // gui = new GUI() + // params = { pixelSize: 3, normalEdgeStrength: .3, depthEdgeStrength: .4, pixelAlignedPanning: true }; + // gui.add( params, 'pixelSize' ).min( 1 ).max( 16 ).step( 1 ) + // .onChange( () => { + + // renderPixelPass.setPixelSize( params.pixelSize ); + + // } ); + // gui.add( renderPixelPass, 'normalEdgeStrength' ).min( 0 ).max( 2 ).step( .05 ); + // gui.add( renderPixelPass, 'depthEdgeStrength' ).min( 0 ).max( 1 ).step( .05 ); + // gui.add( params, 'pixelAlignedPanning' ); +} + + function SetupObjects() { + const loader = new THREE.TextureLoader() + let txt = loader.load('../images/cn-logo-green.png') + txt.magFilter = THREE.NearestFilter + txt.minFilter = THREE.NearestFilter + txt.wrapS = THREE.RepeatWrapping + txt.wrapT = THREE.RepeatWrapping + txt.colorSpace = THREE.SRGBColorSpace let geo = new THREE.BoxGeometry(1, 1, 1) - let mat = new THREE.MeshNormalMaterial() - mesh = new THREE.Mesh(geo, mat) - scene.add(mesh) + let mat = new THREE.MeshBasicMaterial({map: txt}) + count = 1000 + instancedMesh = new THREE.InstancedMesh(geo, mat, count); + scene.add(instancedMesh) + dummy = new THREE.Object3D(); + for (let i = 0; i < count; i++) { + let size = randFloat(5, 8); + dummy.scale.set(size, size, size); + dummy.position.set(randFloat(-20, 20), randFloat(-20,20), 0); + dummy.updateMatrix(); + instancedMesh.setMatrixAt(i, dummy.matrix); + } +} + +function captureFrame() { + renderer.domElement.toDataURL('image/png').replace("image/png", "image/octet-stream"); + let imgData = renderer.domElement.toDataURL("image/png"); + frames.push(imgData); + frameCount++; + + // If last frame, prepare the download + if (frameCount === totalFrames) { + //prepareDownload(); + if( iter == 0 ){ + frameCount = 0 + iter = 1 + } + } +} + +function prepareDownload() { + let zip = new JSZip(); + console.log('zipping..') + frames.forEach((dataUrl, index) => { + let imgData = dataUrl.split(',')[1]; // Get base64 data part + zip.file(`frame_${index.toString().padStart(4, '0')}.png`, imgData, {base64: true}); + }); + console.log('zipped!') + zip.generateAsync({type: "blob"}) + .then(function(content) { + const a = document.createElement("a"); + a.href = URL.createObjectURL(content); + a.download = "frames.zip"; + console.log('zip dl ready!') + a.click(); + + }); } function animate(){ requestAnimationFrame(animate) controls.update() - delta = clock.getDelta() / 10 - mesh.rotation.x += delta - mesh.rotation.z += delta - renderer.render(scene, camera) + delta = clock.getDelta() * 0.4 + const time = performance.now() * 0.001; + const rotationSpeedX = 0.02; + const rotationSpeedY = 0.01; + lastTime = time + + + for (let i = 0; i < count; i++) { + instancedMesh.getMatrixAt(i, matrix) + matrix.decompose(dummy.position, dummy.rotation, dummy.scale) + dummy.rotation.set(i/1000 * time, i/1000 * time, i/1000 * time); + dummy.updateMatrix(); + instancedMesh.setMatrixAt(i, dummy.matrix); + } + instancedMesh.instanceMatrix.needsUpdate = true + // renderer.render(scene, camera) + composer.render() + // Capture the frame + if (frameCount < totalFrames) { + captureFrame(); + } } window.addEventListener('resize', () => {