Instanced + properties
by tfoller
HTML
<canvas id="main_canvas" style="border: solid 1px red;" width=400 height=300></canvas>
CSS
body {
background: #000;
}
JavaScript
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.126/build/three.module.js'
import UTL from 'https://alikim.com/jsm/utils.module.js'
const genRNG = (n, beg = 0, end = 1) => {
const mult = end - beg;
const shft = beg;
const rng = [];
for (let i = 0; i < n; i++) rng[i] = shft + mult * UTL.rndF();
return rng;
}
const renderer = new THREE.WebGLRenderer({
antialias: false,
alpha: true,
canvas: document.querySelector('#main_canvas'),
});
renderer.setPixelRatio(window.devicePixelRatio);
const [cw, ch] = [400, 300];
const camera = new THREE.OrthographicCamera(-cw / 2, cw / 2, ch / 2, -ch / 2, 0, 100);
const str_num = 20;
const mat = new THREE.MeshBasicMaterial();
const geo = new THREE.SphereGeometry(1, 16, 16);
const stars = new THREE.InstancedMesh(geo, mat, str_num);
const [sz, h, s, v, op] = [[1.5, 3], [0, 1], [0.5, 1], [0.5, 1], [0.2, 1]];
const str_pos = { x: genRNG(str_num, -cw/2, cw/2), y: genRNG(str_num, -ch/2, ch/2) };
const str = {};
const prs = ['sz', 'h', 's', 'v', 'op'];
prs.forEach(p => { str[p] = genRNG(str_num, eval(p)[0], eval(p)[1]) });
const clr = [];
const matrix = new THREE.Matrix4();
for (let j = 0; j < str_num; j++) {
clr.push(...UTL.HSVtoRGB(str.h[j], str.s[j], str.v[j]));
const sc = str.sz[j];
matrix.makeScale(sc, sc, sc).setPosition(str_pos.x[j], str_pos.y[j], -10);
stars.setMatrixAt(j, matrix);
}
mat.transparent = true;
mat.vertexColors = true;
geo.setAttribute('opacity', new THREE.InstancedBufferAttribute(new Float32Array(str.op), 1));
geo.setAttribute('color', new THREE.InstancedBufferAttribute(new Float32Array(clr), 3));
console.log(str.op);
const scene = new THREE.Scene().add(stars);
const lightD = new THREE.DirectionalLight(0xffffff, 1);
lightD.position.set(20, 30, 100);
scene.add(lightD);
renderer.render(scene, camera);