<div class="world" id="world">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Today's Date</title>
<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>
</head>
html,
body {
margin: 0;
padding: 0;
background: linear-gradient(#266F92, #111214);
}
import * as THREE from "https://cdn.skypack.dev/[email protected]";
import {
OrbitControls
} from "https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls";
import {
EffectComposer
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/EffectComposer.js';
import {
RenderPass
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/RenderPass.js';
import {
ShaderPass
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/ShaderPass.js';
import {
UnrealBloomPass
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/postprocessing/UnrealBloomPass.js';
import {
ImprovedNoise
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/math/ImprovedNoise.js';
const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
///////////////////////////////////////////////////////////////////////////////
export function create_geo(config) {
let geo;
if (config.geometry_shape == "Box") {
geo = new THREE.BoxGeometry(config.geometry_size_x, config.geometry_size_y, config.geometry_size_z);
}
if (config.geometry_shape == "Icosahedron") {
geo = new THREE.IcosahedronGeometry(config.geometry_size_x, config.geometry_divisions);
}
if (config.geometry_shape == "Plane") {
geo = new THREE.PlaneGeometry(config.geometry_size_x, config.geometry_size_z);
}
if (config.geometry_shape == "Sphere") {
geo = new THREE.SphereGeometry(config.geometry_radius, config.geometry_divisions, config.geometry_divisions);
}
if (config.geometry_shape == "Triangle") {
let shape = new THREE.Shape();
const x = 0;
const y = 0;
const sommet = .1
shape.moveTo(x - sommet, y - sommet);
shape.lineTo(x + sommet, y - sommet);
shape.lineTo(x, y + 1);
geo = new THREE.ShapeGeometry(shape);
}
return geo;
}
export class Instance {
/*
count : number of instance
geom
: geometry_shape
: geometry_size_x
: geometry_radius
: geometry_divisions
color : 0xffffff
bloom : 0 éteint - 1 allumé
*/
constructor(config) {
this.config = config;
this.dummy = [];
this.geom = create_geo(this.config)
this.mat = new THREE.MeshPhongMaterial({
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;
`
);
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);
`
);
}
});
this.color = new THREE.Color();
this.mesh = new THREE.InstancedMesh(this.geom, this.mat, this.config.count);
for (let i = 0; i < this.config.count; i++) {
this.dummy[i] = new THREE.Object3D();
this.dummy[i].position.set(0, 0, 0);
this.dummy[i].updateMatrix()
this.mesh.setMatrixAt(i, this.dummy[i].matrix)
this.mesh.setColorAt(i, this.color.set(this.config.color))
};
this.geom.setAttribute("shine", new THREE.InstancedBufferAttribute(new Float32Array(new Array(this.config.count).fill(0).map(m => {
return Math.random() < 0.025 ? 1 : 0
})), 1));
scene.add(this.mesh);
this.bloom();
}
bloom() {
let bloom = this.geom.attributes.shine;
for (let i = 0; i < this.config.count; i++) {
bloom.setX(i, this.config.bloom);
}
bloom.needsUpdate = true;
}
animate() {
this.mesh.instanceMatrix.needsUpdate = true;
for (let i = 0; i < (this.config.count); i++) {
this.dummy[i].updateMatrix();
this.mesh.setMatrixAt(i, this.dummy[i].matrix);
}
}
}
/////////////////////////////////////////////////////////////////////////////
let scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x020C26, 0, 500);
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.setClearColor(0x01010d, 1);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
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(new THREE.AmbientLight(0xffffff, 0.5));
let globalUniforms = {
bloom: {
value: 0
}
}
let conf_master = {
count: 10,
color: 0xffeb00,
bloom: 0,
geometry_shape: 'Box',
geometry_size_x: .2,
geometry_size_y: .2,
geometry_size_z: .2,
}
let conf_slave = {
count: 10,
color: 0xffffff,
bloom: 1,
geometry_shape: 'Box',
geometry_size_x: .1,
geometry_size_y: .2,
geometry_size_z: .1,
}
let master = new Instance(conf_master)
let slave = new Instance(conf_slave)
for (let i = 0; i < conf_master.count; i++) {
master.dummy[i].position.set(random(-5, 5), random(-1, 1), random(-5, 5))
slave.dummy[i].position.set(master.dummy[i].position.x, master.dummy[i].position.y, master.dummy[i].position.z - .05)
master.dummy[i].add(slave.dummy[i])
};
// DON'T WORKS
// master.mesh.add(slave.mesh)
// BLOOM
const params = {
exposure: 4,
bloomStrength: 1,
bloomThreshold: .1,
bloomRadius: 10
};
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);
renderer.setAnimationLoop(() => {
globalUniforms.bloom.value = 1;
bloomComposer.render();
globalUniforms.bloom.value = 0;
finalComposer.render();
master.animate()
slave.animate()
for (let i = 0; i < conf_master.count; i++) {
//master.dummy[i].rotation.y += 0.1
};
////////////////////////////////////////////////////////////////////////////////////
// WHAT I WOULD LIKE :
// i would like that slave.dummy follow master.dummy and turn also but with the origin of master
////////////////////////////////////////////////////////////////////////////////////
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.