JSFiddle - React, Tailwind, and code Playground
by Paul West
HTML
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.5/dat.gui.min.js"></script>
<script>
var vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`;
var fragmentShader = `
//#extension GL_OES_standard_derivatives : enable
varying vec2 vUv;
uniform float thickness;
uniform vec3 color;
float edgeFactor(vec2 p){
vec2 grid = abs(fract(p - 0.5) - 0.5) / fwidth(p) / thickness;
return min(grid.x, grid.y);
}
void main() {
float a = clamp(edgeFactor(vUv), 0., 1.);
vec3 c = mix(vec3(0), color, a);
gl_FragColor = vec4(c, 1.0);
}
`;
</script>
CSS
body {
overflow: hidden;
margin: 0;
}
JavaScript
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(8, 16, 12);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.target = new THREE.Vector3(0, 2.5, 0);
controls.update();
var geom = new THREE.BoxBufferGeometry();
geom.translate(0, 0.5, 0);
var material = new THREE.ShaderMaterial({
uniforms: {
thickness: {
value: 1.5
},
color: {
value: new THREE.Color()
}
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
extensions: {derivatives: true}
});
for(let i = -4.5; i <= 4.5; i++){
for(let j = -4.5; j <= 4.5; j++){
let box = new THREE.Mesh( geom, material.clone() );
box.material.uniforms.color.value.set(Math.random() * 0xffffff);
box.scale.y = THREE.Math.randInt(1, 10);
box.position.set(i, 0, j);
scene.add( box );
}
}
var gui = new dat.GUI();
gui.add(material.uniforms.thickness, "value", 1, 3).name("thickness");
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}