Point textures
by tfoller
HTML
<canvas id="main_canvas" style="border: solid 1px red;" width=400 height=300></canvas>
<script type="x-shader/x-vertex" id="vs_texpoint">
attribute float psize;
varying float psz;
void main() {
gl_PointSize = psize;
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * mvPosition;
psz = psize;
}
</script>
<script type="x-shader/x-fragment" id="fs_texpoint">
uniform sampler2D map;
uniform vec2 text_size;
varying float psz;
void main() {
vec2 uv = vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y) * text_size * psz;
gl_FragColor = uv.x < 1.0 && uv.y < 1.0 ? texture2D(map, uv) : vec4(1.0, 0.0, 1.0, 1.0);
}
</script>
CSS
body {
background: #000;
color: #ccc;
}
JavaScript
import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js'
const get = (id) => document.getElementById(id);
const texldr = new THREE.TextureLoader();
const canvas = get('main_canvas');
const [w, h] = [canvas.width, canvas.height];
const [w2, h2] = [w * 0.5, h * 0.5];
const renderer = new THREE.WebGLRenderer({
antialias: false,
alpha: false,
canvas,
});
renderer.setPixelRatio(window.devicePixelRatio);
const gl = renderer.getContext();
gl.disable(gl.DITHER);
const [near, far] = [1, 200];
const fixedcam = new THREE.OrthographicCamera(-w2, w2, h2, -h2, near, far);
const getShader = (uiObj, id) => {
let src = get(id).textContent;
src = src.replace(/#include '([^']+)'/g,
function () {
return get(arguments[1]).textContent;
});
src = src.replace(/<sh ([^>]+)>/g,
function () {
return eval('uiObj.shader_expr.' + arguments[1]);
});
src = src.replace(/<js ([^>]+)>/g,
function () {
return eval('uiObj.js_expr.' + arguments[1]);
});
return src.replace(/<hub ([^>]+)>/g,
function () {
return eval('HUB.' + arguments[1]);
});
}
function shaderPQuad(vert, psize, vs, fs, subx = 1, suby = 1, x = 0, y = 0, z = 0) {
this.geo = new THREE.BufferGeometry();
const pos = new THREE.Float32BufferAttribute(vert, 3);
this.geo.setAttribute('position', pos);
const psz = new THREE.Float32BufferAttribute(psize, 1);
this.geo.setAttribute('psize', psz);
this.mat = new THREE.ShaderMaterial({
vertexShader: getShader({}, vs),
fragmentShader: getShader({}, fs),
uniforms: {
map: { value: texldr.load(
'https://source.unsplash.com/random/75x100',
render,
undefined,
err => { console.log('texture load err:', err) }
)},
text_size: {value: [1/75, 1/100]}
},
});
this.mesh = new THREE.Points(this.geo, this.mat);
this.mesh.position.set(x, y, z);
...