Skip to content

Instantly share code, notes, and snippets.

@espace3d
Created February 22, 2022 18:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save espace3d/89d545ebf77dcd63d1f39606d9ac4fdb to your computer and use it in GitHub Desktop.
Save espace3d/89d545ebf77dcd63d1f39606d9ac4fdb to your computer and use it in GitHub Desktop.
InstancedMesh + SelectiveBloom
<script type="x-shader/x-vertex" id="vertexshader">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script type="x-shader/x-fragment" id="fragmentshader">
uniform sampler2D baseTexture;
uniform sampler2D bloomTexture;
varying vec2 vUv;
void main() {
gl_FragColor = ( texture2D( baseTexture, vUv ) + vec4( 1.0 ) * texture2D( bloomTexture, vUv ) );
}
</script>
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
import { EffectComposer } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/postprocessing/RenderPass.js';
import { ShaderPass } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/postprocessing/ShaderPass.js';
import { UnrealBloomPass } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/postprocessing/UnrealBloomPass.js';
import { ImprovedNoise } from 'https://cdn.skypack.dev/three@0.136.0/examples/jsm/math/ImprovedNoise.js';
let noise = new ImprovedNoise();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
renderer.toneMapping = THREE.ReinhardToneMapping;
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight)
})
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 1.5);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let MAX_COUNT = 10000;
let globalUniforms = {
bloom: {value: 0}
}
let g = new THREE.BoxGeometry(0.1, 0.1, 0.1);
let m = new THREE.MeshLambertMaterial({
onBeforeCompile: shader => {
shader.uniforms.bloom = globalUniforms.bloom;
shader.vertexShader = `
attribute float shine;
varying float vShine;
${shader.vertexShader}
`.replace(
`#include <color_vertex>`,
`#include <color_vertex>
vShine = shine;
`
);
//console.log(shader.vertexShader);
shader.fragmentShader = `
uniform float bloom;
varying float vShine;
${shader.fragmentShader}
`.replace(
`#include <dithering_fragment>`,
`#include <dithering_fragment>
gl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0), bloom);
gl_FragColor.rgb = mix(gl_FragColor.rgb, vColor, vShine);
`
);
console.log(shader.fragmentShader);
}
});
let o = new THREE.InstancedMesh(g, m, MAX_COUNT);
let dummy = new THREE.Object3D();
let rvec = new THREE.Vector3();
let col = new THREE.Color();
for(let i = 0; i < MAX_COUNT; i++){
dummy.position.randomDirection();
let n = noise.noise(dummy.position.x, dummy.position.y, dummy.position.z);
dummy.position.setLength(3 + Math.abs(n) * 3);
dummy.rotation.setFromVector3(rvec.random().subScalar(0.5).multiplyScalar(Math.PI * 2));
dummy.updateMatrix();
o.setMatrixAt(i, dummy.matrix);
o.setColorAt(i, col.set(Math.random() > 0.5 ? 0xff3232 : 0x00ffff));
}
g.setAttribute("shine", new THREE.InstancedBufferAttribute(new Float32Array(new Array(MAX_COUNT).fill(0).map(m => {return Math.random() < 0.025 ? 1 : 0})), 1));
scene.add(o);
// BLOOM
const params = {
exposure: 1,
bloomStrength: 5,
bloomThreshold: 0,
bloomRadius: 0.5
};
const renderScene = new RenderPass( scene, camera );
const bloomPass = new UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
const bloomComposer = new EffectComposer( renderer );
bloomComposer.renderToScreen = false;
bloomComposer.addPass( renderScene );
bloomComposer.addPass( bloomPass );
const finalPass = new ShaderPass(
new THREE.ShaderMaterial( {
uniforms: {
baseTexture: { value: null },
bloomTexture: { value: bloomComposer.renderTarget2.texture }
},
vertexShader: document.getElementById( 'vertexshader' ).textContent,
fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
defines: {}
} ), 'baseTexture'
);
finalPass.needsSwap = true;
const finalComposer = new EffectComposer( renderer );
finalComposer.addPass( renderScene );
finalComposer.addPass( finalPass );
setInterval(() => {
let shine = g.attributes.shine;
for(let i = 0; i < MAX_COUNT; i++){
shine.setX(i, Math.random() < 0.025 ? 1 : 0);
}
shine.needsUpdate = true;
}, 1500);
renderer.setAnimationLoop(() => {
o.rotation.y += 0.001;
globalUniforms.bloom.value = 1;
bloomComposer.render();
globalUniforms.bloom.value = 0;
finalComposer.render();
//renderer.render(scene, camera);
});
body{
overflow: hidden;
margin: 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment