Flickering Torch
Noise-based point light flicker simulating a handheld torch.
What this code does
- Procedural Flicker: combines sine waves with pseudorandom noise for realistic torch flicker.
- PRNG Function: seeded random number generator ensures consistent but unpredictable behavior.
- Dynamic Intensity: point light intensity varies based on flicker algorithm.
- Visual Flame: small sphere scales with light intensity to simulate flame size.
- Interactive Controls: adjust flicker intensity and speed in real-time.
- Atmospheric Lighting: warm orange light creates cozy torch ambiance.
JavaScript (plain)
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
function prng (seed) {
let s = seed >>> 0
return () => {
s ^= s << 13
s ^= s >>> 17
s ^= s << 5
return (s >>> 0) / 0xffffffff
}
}
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(70, width / height, 0.1, 100)
camera.position.set(0, 1.5, 3.5)
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(width, height)
document.querySelector('#app').appendChild(renderer.domElement)
const controls = new OrbitControls(camera, renderer.domElement)
controls.target.set(0, 1, 0)
controls.update()
const plane = new THREE.Mesh(
new THREE.PlaneGeometry(10, 10),
new THREE.MeshStandardMaterial({ color: 0x0e0e0e })
)
plane.rotation.x = -Math.PI / 2
plane.position.y = 0
scene.add(plane)
const wall = new THREE.Mesh(
new THREE.PlaneGeometry(10, 4),
new THREE.MeshStandardMaterial({ color: 0x080808 })
)
wall.position.set(0, 2, -3)
scene.add(wall)
const torch = new THREE.PointLight(0xffaa55, 2, 10, 2)
torch.position.set(0, 1.5, 0)
scene.add(torch)
const flame = new THREE.Mesh(
new THREE.SphereGeometry(0.05, 8, 8),
new THREE.MeshBasicMaterial({ color: 0xffddaa })
)
flame.position.copy(torch.position)
scene.add(flame)
const rng = prng(1337)
let time = 0
function animate(t) {
requestAnimationFrame(animate)
time += (t || 16) / 1000
const noise = (rng() - 0.5) * 2
const n2 = (rng() - 0.5) * 2
const flickerIntensity = 0.6
const speed = 6.0
const base = 1.8
const flick = base + flickerIntensity * (Math.sin(time * speed) * 0.5 + 0.5 * noise + 0.25 * n2)
torch.intensity = Math.max(0.2, flick)
flame.scale.setScalar(0.8 + (torch.intensity - base) * 0.2)
controls.update()
renderer.render(scene, camera)
}
animate()