JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script type="x-shader/x-vertex" id="vert">
attribute vec3 offset;
attribute vec2 uvOffset;
attribute vec2 uvScale;
varying vec2 vUv;
void main() {
vUv = uvOffset + uv * uvScale;
vec2 scale = vec2( 20.0 ); // create a uniform for this
vec2 alignedPosition = ( ( position.xy * scale ) + offset.xy );
//vec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );
vec4 mvPosition = vec4( modelViewMatrix[3][0], modelViewMatrix[3][1], modelViewMatrix[3][2], modelViewMatrix[3][3] );
mvPosition.xy += alignedPosition;
gl_Position = projectionMatrix * mvPosition;
}</script>
<script type="x-shader/x-fragment" id="frag">
precision highp float;
varying vec2 vUv;
uniform sampler2D texture;
uniform vec3 textColor;
uniform vec3 outlineColor;
uniform float outlineDistance;
uniform float opacity;
float aastep(float base, float value) {
#ifdef GL_OES_standard_derivatives
float afwidth = length(vec2(dFdx(value), dFdy(value))) * 0.70710678118654757;
#else
float afwidth = (1.0 / 32.0) * (1.4142135623730951 / (2.0 * gl_FragCoord.w));
#endif
return smoothstep(base - afwidth, base + afwidth, value);
}
void main() {
float distance = texture2D(texture, vUv).a;
float outlineFactor = aastep(0.5, distance);
vec3 color = mix(outlineColor, textColor, outlineFactor);
float alpha = aastep(outlineDistance, distance);
gl_FragColor = vec4(color, opacity * alpha);
if (gl_FragColor.a < 0.0001) discard;
}
</script>
JavaScript
// a basic three.js scene
var container, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer({
antialias: false
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xccccff);
container = document.createElement('div');
document.body.appendChild(container);
container.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 200, 800);
//camera.lookAt(scene.position);
scene.add(new THREE.CameraHelper(camera));
//instances geometry
var geometry = new THREE.InstancedBufferGeometry();
var vertices = new Float32Array( [
- 0.5, - 0.5, 0,
0.5, - 0.5, 0,
0.5, 0.5, 0,
- 0.5, 0.5, 0
] );
var uvs = new Float32Array( [
0, 0,
1, 0,
1, 1,
0, 1
] );
geometry.addAttribute("position", new THREE.Float32BufferAttribute( vertices, 3 ) );
geometry.addAttribute("uv", new THREE.Float32BufferAttribute( uvs, 2 ) );
geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
var count = 3;
var offsets = new Float32Array(count * 3);
var uvOffset = new Float32Array(count * 2);
var uvScales = new Float32Array(count * 2);
//iterators
var offsetIterator = 0;
var uvOffsetIterator = 0;
var uvScalesIterator = 0;
var cX = 389;
var cY = 109;
var cWidth = 25;
var cHeight = 28;
var left = cX / 512;
var top = (512 - (cY + cHeight)) / 512;
for (let i = 0; i < count; i++) {
offsets[offsetIterator++] = 100 + (19) * i;
offsets[offsetIterator++] = 50;
offsets[offsetIterator++] = 0.0;
uvOffset[uvOffsetIterator++] = left;
uvOffset[uvOffsetIterator++] = top;
uvScales[uvScalesIterator++] = cWidth / 512;
uvScales[uvScalesIterator++] = cHeight / 512;
}
...