Cailean Finn
7 months ago
5 changed files with 275 additions and 4 deletions
After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,148 @@ |
|||||
|
import * as THREE from 'three' |
||||
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.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 { randFloat } from 'three/src/math/MathUtils.js'; |
||||
|
|
||||
|
|
||||
|
let scene, camera, renderer |
||||
|
let aspect, frustumSize |
||||
|
let time = 0 |
||||
|
let lastTime = 0 |
||||
|
let controls |
||||
|
let mesh |
||||
|
let composer |
||||
|
let cubeGroup = [] |
||||
|
let instancedMesh, dummy, count |
||||
|
|
||||
|
const texture = new THREE.TextureLoader().load("public/images/dither.png") |
||||
|
texture.minFilter = THREE.NearestFilter |
||||
|
texture.colorSpace = THREE.SRGBColorSpace; |
||||
|
texture.wrapS = THREE.RepeatWrapping; |
||||
|
texture.wrapT = THREE.RepeatWrapping; |
||||
|
|
||||
|
|
||||
|
function init(){ |
||||
|
SetupRenderer() |
||||
|
scene = new THREE.Scene() |
||||
|
SetupCamera() |
||||
|
SetupControls() |
||||
|
composer = new EffectComposer( renderer ); |
||||
|
const renderPixelatedPass = new RenderPixelatedPass( 8, scene, camera ); |
||||
|
renderPixelatedPass.normalEdgeStrength = 0; |
||||
|
renderPixelatedPass.depthEdgeStrength = 1; |
||||
|
renderPixelatedPass.pixelAlignedPanning = false; |
||||
|
composer.addPass( renderPixelatedPass ); |
||||
|
const outputPass = new OutputPass(); |
||||
|
composer.addPass( outputPass ); |
||||
|
SetupCubes() |
||||
|
AddLights() |
||||
|
animate() |
||||
|
} |
||||
|
|
||||
|
|
||||
|
function SetupCubes() { |
||||
|
const cubeGeometry = new THREE.BoxGeometry(); |
||||
|
const cubeMaterial = new THREE.MeshPhongMaterial({ map: texture }); |
||||
|
|
||||
|
// Create an InstancedMesh
|
||||
|
count = 100; |
||||
|
instancedMesh = new THREE.InstancedMesh(cubeGeometry, cubeMaterial, 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(-10, 10), randFloat(-6, 3), 0); |
||||
|
dummy.updateMatrix(); |
||||
|
instancedMesh.setMatrixAt(i, dummy.matrix); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
function SetupRenderer(){ |
||||
|
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }) |
||||
|
renderer.setClearColor(0xffffff, 0); |
||||
|
renderer.setSize(window.innerWidth, window.innerHeight) |
||||
|
document.getElementById('container').appendChild(renderer.domElement) |
||||
|
} |
||||
|
|
||||
|
function SetupCamera(){ |
||||
|
aspect = (window.innerWidth) / (window.innerHeight) |
||||
|
frustumSize = 10 |
||||
|
camera = new THREE.OrthographicCamera( |
||||
|
frustumSize * aspect / -2, |
||||
|
frustumSize * aspect / 2, |
||||
|
frustumSize / 2, |
||||
|
frustumSize / -2, |
||||
|
0.01, |
||||
|
5000 |
||||
|
) |
||||
|
|
||||
|
camera.position.x = 5 |
||||
|
} |
||||
|
|
||||
|
function SetupControls(){ |
||||
|
controls = new OrbitControls(camera, renderer.domElement) |
||||
|
controls.enableRotate = false; |
||||
|
controls.enablePan = false |
||||
|
controls.zoomToCursor = false; |
||||
|
controls.mouseButtons = { |
||||
|
RIGHT: THREE.MOUSE.ROTATE, |
||||
|
MIDDLE: THREE.MOUSE.DOLLY, |
||||
|
LEFT: THREE.MOUSE.PAN |
||||
|
} |
||||
|
camera.position.set(0, 0, 20) |
||||
|
controls.update() |
||||
|
} |
||||
|
|
||||
|
function AddLights() { |
||||
|
// Add Ambient Light
|
||||
|
const ambientLight = new THREE.AmbientLight(0xffffff, 10); // Soft white light
|
||||
|
scene.add(ambientLight); |
||||
|
|
||||
|
// Add Directional Light
|
||||
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 0); // Soft white light
|
||||
|
directionalLight.position.set(-5, 0, 5).normalize(); |
||||
|
scene.add(directionalLight); |
||||
|
} |
||||
|
|
||||
|
const matrix = new THREE.Matrix4() |
||||
|
function animate(){ |
||||
|
requestAnimationFrame(animate) |
||||
|
// Rotate instanced meshes
|
||||
|
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 |
||||
|
|
||||
|
composer.render() |
||||
|
//renderer.render(scene, camera)
|
||||
|
} |
||||
|
|
||||
|
window.addEventListener('resize', () => { |
||||
|
aspect = (window.innerWidth) / (window.innerHeight) |
||||
|
camera.left = -frustumSize * aspect / 2 |
||||
|
camera.right = frustumSize * aspect / 2 |
||||
|
camera.top = frustumSize / 2 |
||||
|
camera.bottom = -frustumSize / 2 |
||||
|
camera.updateProjectionMatrix() |
||||
|
renderer.setPixelRatio(window.devicePixelRatio) |
||||
|
renderer.setSize(window.innerWidth, window.innerHeight) |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
init() |
||||
|
|
Loading…
Reference in new issue