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() {
//HERE ! !
vUv = uv * uvScale + uvOffset;
// STOP.
vec3 pos = position + offset;
gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );
}</script>
<script type="x-shader/x-fragment" id="frag">
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
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));
var src = new THREE.BufferGeometry().fromGeometry(new THREE.PlaneGeometry(25, 28, 1, 1));
//instances geometry
var geometry = new THREE.InstancedBufferGeometry();
geometry.addAttribute("position", new THREE.BufferAttribute(src.getAttribute("position").array, 3));
geometry.addAttribute("uv", new THREE.BufferAttribute(src.getAttribute("uv").array, 2));
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++] = 1.0;
uvOffset[uvOffsetIterator++] = left;
uvOffset[uvOffsetIterator++] = top;
uvScales[uvScalesIterator++] = cWidth / 512;
uvScales[uvScalesIterator++] = cHeight / 512;
}
//add buffers
geometry.addAttribute(
"offset",
new THREE.InstancedBufferAttribute(offsets, 3, 1)
);
...