read vertex position as pixel

by brunoimbrizi

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/95/three.min.js"></script>
<div class='container'></div>
<div class='info rgba'></div>
<div class='info xyz'></div>

CSS

body {
  margin: 0;
  overflow: hidden;
  color: #FFF;
  background-color: #000;
  font-family: monospace;
}

.container {
  position: absolute;
  top: 20px;
  left: 20px;
}

.info {
  position: absolute;
  top: 20px;
  left: 170px;
}

.info.xyz {
  left: 260px;
}

JavaScript

// pass vertex position to fragment
// render as texture and read pixels

var renderer, camera, scene, texture, geometry, material, buffer;

var width = 5;
var height = 5;

function init() {
	scene = new THREE.Scene();
	
  camera = new THREE.OrthographicCamera(width / -2, width / 2, height / 2, height / -2, -1, 1);
  
  renderer = new THREE.WebGLRenderer({ premultipliedAlpha: false });
  renderer.setSize(128, 128);
  document.querySelector('.container').appendChild(renderer.domElement);

  texture = new THREE.WebGLRenderTarget(width, height, { 
  	minFilter: THREE.LinearFilter,
    magFilter: THREE.NearestFilter,
    format: THREE.RGBAFormat,
    type: THREE.FloatType
  });
  
  material = new THREE.ShaderMaterial( {
    uniforms: { 
      width: { value: width },
      height: { value: height },
    },
    vertexShader: `
    	attribute float pindex;
    
    	uniform float width;
  		uniform float height;
      
    	varying vec4 vOut;
  
			void main() {
      	vec2 pos = vec2(mod(pindex, width) / width, floor(pindex / width) / height) * 2.0 - 1.0;
    		pos += 1.0 / width;
    
      	gl_PointSize = 1.0;
        gl_Position = vec4(pos, 0.0, 1.0);
        
        vOut = vec4(position, pindex);
			}
    `,
    fragmentShader: `
    	varying vec4 vOut;
    
    	void main() {
				gl_FragColor = vOut;
    	}
    `,
  });
  
  var indices = new Float32Array(width * height);
  for (var i = 0; i < width * height; i++) {
  	indices[i] = i;
  }
  
  geometry = new THREE.PlaneBufferGeometry(width - 1, height - 1, width - 1, height - 1);
	geometry.addAttribute('pindex', new THREE.BufferAttribute(indices, 1, 1));

  var quad = new THREE.Points(geometry, material);
  scene.add(quad);
  
  buffer = new Float32Array(4 * width * height);
}

function animate() {
  requestAnimationFrame(animate);
  render();
  read();
}

function render() {
  renderer.render(scene, camera, texture, true);
  renderer.render(scene, camera);
}

function read()...