<script id='vertex-shader' type='x-shader/x-vertex'>
precision mediump float;
// these come built in with three.js; they're basically always used in the same way (see below)
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform vec3 cameraPosition;
// these are uniforms we specified
uniform float atlasPx;
uniform float cellPx;
uniform float pointScale;
// these are the buffer attributes we specified when creating the geometry
attribute vec2 position;
attribute vec2 uv;
// these are attributes we will pass from the vertex to the fragment shader
varying vec2 vUv;
void main() {
// get the position of the particle
vec4 mvPosition = modelViewMatrix * vec4(position, 0.0, 1.0);
gl_Position = projectionMatrix * mvPosition;
// set the point size
gl_PointSize = pointScale;
// pass the varying data to the fragment shader
vUv = uv;
}
</script>
<script id='fragment-shader' type='x-shader/x-fragment'>
precision mediump float;
uniform sampler2D texture;
uniform float atlasPx;
uniform float cellPx;
varying vec2 vUv;
void main() {
vec2 uv = (vUv * cellPx + gl_PointCoord.xy * cellPx) / atlasPx;
gl_FragColor = texture2D(texture, uv);
// this line mixes the actual texture color with some red
//gl_FragColor = mix(gl_FragColor, vec4(1.0, 0.0, 0.0, 1.0), 0.5);
}
</script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r111/three.min.js'></script>
CSS
body { margin: 0 }
canvas { display: block }
JavaScript
var camera, scene, renderer, geometry, material, mesh, n, rootN;
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1.8;
scene = new THREE.Scene();
n = 60; // number of cells to render
rootN = Math.ceil(Math.pow(n, 0.5)); // positions in each axis of grid
// create buffer attributes
const uvs = new Float32Array(n * 2)
const positions = new Float32Array(n * 2)
for (var i=0; i<n; i++) {
var x = i % rootN; // x position 0:rootN-1
var y = Math.floor(i / rootN); // y position 0:rootN-1
var clipX = ((x / (rootN-1))-0.5)*2; // scale x dimension -1:1
var clipY = -((y / Math.floor(n/rootN))-0.5)*2; // scale y dimension -1:1
positions[i*2] = clipX;
positions[i*2+1] = clipY;
uvs[i*2] = x; // store uv as x,y grid unit offset of the cell
uvs[i*2+1] = y;
}
// create geometry
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 2, true));
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2, true));
const url = 'https://raw.githubusercontent.com/slnsw/dxlab-fellowship-2019/master/public/assets/medals.jpg';
const texture = new THREE.TextureLoader().load(url);
texture.flipY = false;
const material = new THREE.RawShaderMaterial({
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent,
uniforms: {
texture: {
type: 't',
value: texture,
},
atlasPx: {
type: 'f',
value: 256,
},
cellPx: {
type: 'f',
value: 32,
},
pointScale: {
type: 'f',
value: getPointSize(),
},
},
});
mesh = new THREE.Points(geometry, material);
mesh.frustumCulled = false;
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize(...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.