Box Instanced Grid

box-instanced-grid.js

Show Example Source
// enable shadow map
shadowMap();

// configure orthographic camera
ortho([3, 3, 3], 0, {controls: true});

const w = 0.02; // width
const h = 0.02; // height
const d = 0.02; //  depth
const count = 50000; // how many instances
const drawLines = false; // toggle between lines and solid boxes

// create box geometry and material
let geometry = geom.box(w, h, d);

let material;
if (drawLines) {
    // convert box to edges
    geometry = geom.edges(geometry);
    // black line basic material
    material = mat.lineBasic({ color: color(0, 0, 0) });
}
else {
    // grey solid color material with lambert shading cached as a texture
    material = solid(0.5,0.5,0.5).lambert().texMat(o1);
}

// create scene with yellow background and default lighting setup
const sc = stage({background: color(1,1,0), name: "instanced-grid", key: "instanced-grid"})
    .lights()
    .render();

// add instanced box mesh to scene using public API
sc.mesh(
    geometry,
    material,
    {instanced: count, key: "instanced-grid-mesh"}
);
const box = sc.at(0);

if (drawLines) {
    // fix box if drawing lines
    box.isMesh = false;
    box.isLine = true;
    box.isLineSegments = true;
}

const calcHeight = (x, z) => {
    // get simplex noise between -2 and 5, using zoom 1
    const simplexNoise = noiseUtil.get2(x, z, -2, 5, 1);
    // get yellow fbm noise between 0 and 20, using zoom 0.5
    const yellowNoise = noiseUtil.get2(x, z, 0, 20, 0.5, noiseUtil.YELLOW);
    // this makes the high rises come from lower regions
    return simplexNoise < 0 ? yellowNoise : simplexNoise;
}

// set matrix for each instance
const matrix = mat4(); // THREE.Matrix4
for ( let i = 0; i < count; i++ ) {
    const position = vec3(); // THREE.Vector3
    const quaternion = quat(); // THREE.Quaternion
    const scale = vec3(1.0, 1.0, 1.0); // THREE.Vector3

    const sqr = Math.sqrt(count);
    const [x, z] = [(i % sqr), Math.floor(i / sqr)];
    const y = calcHeight(x, z);

    position.x = x * w - sqr * w / 2;
    position.z = z * d - sqr * d / 2;
    position.y = y * h / 2;
    scale.y = y;

    // compose THREE.Matrix4 from position, quaternion and scale
    matrix.compose( position, quaternion, scale );

    // set matrix for each instance
    box.setMatrixAt( i, matrix );
}