Skip to content

Instantly share code, notes, and snippets.

@RamboRogers
Created December 21, 2022 02:59
Show Gist options
  • Select an option

  • Save RamboRogers/73b5a041993a8bac373907b295bd9382 to your computer and use it in GitHub Desktop.

Select an option

Save RamboRogers/73b5a041993a8bac373907b295bd9382 to your computer and use it in GitHub Desktop.
THREE.js Smoke Particles
import * as THREE from 'https://cdn.skypack.dev/three@0.134';
class Smoke {
constructor(options) {
const defaults = {
width: window.innerWidth,
height: window.innerHeight
};
Object.assign(this, options, defaults);
this.onResize = this.onResize.bind(this);
this.addEventListeners();
this.init();
}
init() {
const { width, height } = this;
this.clock = new THREE.Clock();
const renderer = this.renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
this.scene = new THREE.Scene();
const meshGeometry = new THREE.BufferGeometry(200, 200, 200);
const meshMaterial = new THREE.MeshLambertMaterial({
color: 0xaa6666,
wireframe: false
});
this.mesh = new THREE.Mesh(meshGeometry, meshMaterial);
this.cubeSineDriver = 0;
this.addCamera();
this.addLights();
this.addParticles();
this.addBackground();
document.body.appendChild(renderer.domElement);
}
evolveSmoke(delta) {
const { smokeParticles } = this;
let smokeParticlesLength = smokeParticles.length;
while(smokeParticlesLength--) {
smokeParticles[smokeParticlesLength].rotation.z += delta * 0.2;
}
}
addLights() {
const { scene } = this;
const light = new THREE.DirectionalLight(0xffffff, 0.75);
light.position.set(-1, 0, 1);
scene.add(light);
}
addCamera() {
const { scene } = this;
const camera = this.camera = new THREE.PerspectiveCamera(75, this.width / this.height, 1, 10000);
camera.position.z = 1000;
scene.add(camera);
}
addParticles() {
const { scene } = this;
const textureLoader = new THREE.TextureLoader();
const smokeParticles = this.smokeParticles = [];
textureLoader.load('https://rawgit.com/marcobiedermann/playground/master/three.js/smoke-particles/dist/assets/images/clouds.png', texture => {
const smokeMaterial = new THREE.MeshLambertMaterial({
color: 0xffffff,
map: texture,
transparent: true
});
smokeMaterial.map.minFilter = THREE.LinearFilter;
const smokeGeometry = new THREE.PlaneBufferGeometry(300, 300);
const smokeMeshes = [];
let limit = 150;
while(limit--) {
smokeMeshes[limit] = new THREE.Mesh(smokeGeometry, smokeMaterial);
smokeMeshes[limit].position.set(Math.random() * 500 - 250, Math.random() * 500 - 250, Math.random() * 1000 - 100);
smokeMeshes[limit].rotation.z = Math.random() * 360;
smokeParticles.push(smokeMeshes[limit]);
scene.add(smokeMeshes[limit]);
}
});
}
addBackground() {
const { scene } = this;
const textureLoader = new THREE.TextureLoader();
const textGeometry = new THREE.PlaneBufferGeometry(600, 320);
textureLoader.load('https://rawgit.com/marcobiedermann/playground/master/three.js/smoke-particles/dist/assets/images/background.jpg', texture => {
const textMaterial = new THREE.MeshLambertMaterial({
blending: THREE.AdditiveBlending,
color: 0xffffff,
map: texture,
opacity: 1,
transparent: true
});
textMaterial.map.minFilter = THREE.LinearFilter;
const text = new THREE.Mesh(textGeometry, textMaterial);
text.position.z = 800;
scene.add(text);
});
}
render() {
const { mesh } = this;
let { cubeSineDriver } = this;
cubeSineDriver += 0.01;
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
mesh.position.z = 100 + Math.sin(cubeSineDriver) * 500;
this.renderer.render(this.scene, this.camera);
}
update() {
this.evolveSmoke(this.clock.getDelta());
this.render();
requestAnimationFrame(this.update.bind(this));
}
onResize() {
const { camera } = this;
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
camera.aspect = windowWidth / windowHeight;
camera.updateProjectionMatrix();
this.renderer.setSize(windowWidth, windowHeight);
}
addEventListeners() {
window.addEventListener('resize', this.onResize);
}
}
/* app.js */
const smoke = new Smoke();
smoke.update();
/* layout/base.css */
body {
margin: 0;
}
/* modules/canvas.css */
canvas {
height: auto;
max-width: 100%;
vertical-align: middle;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment