Skip to content

Instantly share code, notes, and snippets.

@likr
Last active May 30, 2016 13:13
Show Gist options
  • Save likr/4aae545dee18d5bdbb210d28a9604b7d to your computer and use it in GitHub Desktop.
Save likr/4aae545dee18d5bdbb210d28a9604b7d to your computer and use it in GitHub Desktop.
const THREE = require('three')
const EffectComposer = require('three-effectcomposer')(THREE)
class EnsembleAveragePass {
constructor (scene, camera, repeat) {
this.scene = scene
this.camera = camera
this.uniforms = THREE.UniformsUtils.clone({
accBuffer: {type: 't', value: null},
newBuffer: {type: 't', value: null},
scale: {type: 'f', value: 1 / repeat}
})
this.material = new THREE.ShaderMaterial({
uniforms: this.uniforms,
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform sampler2D accBuffer;
uniform sampler2D newBuffer;
uniform float scale;
varying vec2 vUv;
void main() {
vec4 accColor = texture2D(accBuffer, vUv);
vec4 newColor = texture2D(newBuffer, vUv) * scale;
newColor.a = 1.0;
gl_FragColor = accColor + newColor;
}
`
})
this.enabled = true
this.needsSwap = true
}
render (renderer, writeBuffer, readBuffer) {
if (!EnsembleAveragePass.sceneBuffer) {
EnsembleAveragePass.sceneBuffer = readBuffer.clone() // XXX
}
renderer.render(this.scene, this.camera, EnsembleAveragePass.sceneBuffer, true)
this.uniforms.accBuffer.value = readBuffer
this.uniforms.newBuffer.value = EnsembleAveragePass.sceneBuffer
EffectComposer.quad.material = this.material
if (this.renderToScreen) {
renderer.render(EffectComposer.scene, EffectComposer.camera)
} else {
renderer.render(EffectComposer.scene, EffectComposer.camera, writeBuffer, true)
}
}
}
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const r = 400
const camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000)
camera.position.z = r
const composer = new EffectComposer(renderer)
composer.addPass(new EffectComposer.ShaderPass({
vertexShader: `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
`
}))
const repeat = 10
for (let j = 0; j < repeat; ++j) {
const scene = new THREE.Scene()
scene.fog = new THREE.Fog(0x000000, 1, 1000)
const object = new THREE.Object3D()
scene.add(object)
const geometry = new THREE.SphereGeometry(1, 4, 4)
const material = new THREE.MeshPhongMaterial({
color: 0xffffff,
shading: THREE.FlatShading
})
for (let i = 0; i < 100; i++) {
const mesh = new THREE.Mesh(geometry, material)
mesh.position.set(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize()
mesh.position.multiplyScalar(Math.random() * 400)
mesh.rotation.set(Math.random() * 2, Math.random() * 2, Math.random() * 2)
mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 50
object.add(mesh)
}
scene.add(new THREE.AmbientLight(0x222222))
const light = new THREE.DirectionalLight(0xffffff)
light.position.set(1, 1, 1)
scene.add(light)
const effect = new EnsembleAveragePass(scene, camera, repeat)
if (j === repeat - 1) {
effect.renderToScreen = true
}
composer.addPass(effect)
}
const start = new Date()
const render = () => {
window.requestAnimationFrame(render)
const seconds = new Date() - start
const theta = Math.PI * seconds / 2500
camera.position.z = r * Math.cos(theta)
camera.position.x = r * Math.sin(theta)
camera.lookAt({x: 0, y: 0, z: 0})
composer.render()
}
render()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment