Shader Coordinates - Fl-Matrix

Demo

by David Komer

HTML

<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary-type-identifiers/master/index.js"></script>
<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary-type-classes/master/index.js"></script>
<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary-def/master/index.js"></script>
<script src="https://cdn.rawgit.com/sanctuary-js/sanctuary/master/index.js"></script>
<script src="https://unpkg.com/fl-matrix/dist/fl-matrix.browser-production.js"></script>
<canvas id="canvas"></canvas>

CSS

html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
}

#canvas {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

JavaScript

//Globals
const canvas = document.getElementById("canvas");
const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");

updateCanvasSize();

//Config
const QUAD_WIDTH = 200;
const QUAD_HEIGHT = 200;
const QUAD_COLOR = [1.0, 0, 0, 1.0];
const LIMIT_X = canvas.clientWidth - QUAD_WIDTH;
const LIMIT_Y = canvas.clientHeight - QUAD_HEIGHT;

const S = window.sanctuary.create({
  checkTypes: false,
  env: window.sanctuary.env
});

const velocity = FlMatrix.vectorFromElements([100,100]);

//Screen projection transform - using "setValueAtPosition" for illustrative purposes here
//There's several other approaches that are more efficient, but since this is just created once it's no biggie
const projectionMatrix = FlMatrix.identityMatrix (3) (3)
		.setValueAtPosition (0) (0) (2/canvas.clientWidth)
		.setValueAtPosition (1) (1) (2/canvas.clientHeight)
    .setValueAtPosition (2) (0) (-1)
    .setValueAtPosition (2) (1) (-1);
    
//The cool thing is that this drives the whole transformation pipeline. 
//We could chain one matrix after another via compose() or S.compose :)
const getTransformMatrix = S.compose(projectionMatrix); //projectionMatrix.compose would also work

const status = S.chain(program => {
  //set vertex data
  const vertices = makeBuffer(program, "a_Vertex");
  vertices.write(new Float32Array([
    0, QUAD_HEIGHT, // top-left
    0, 0, //bottom-left
    QUAD_WIDTH, QUAD_HEIGHT, // top-right
    QUAD_WIDTH, 0 // bottom-right
  ]));
  
  //set uniforms - requires resetting the program pointer first
  gl.useProgram(program);
  
  //set color
  const colorLocation = gl.getUniformLocation(program, "u_Color");
  gl.uniform4fv(colorLocation, QUAD_COLOR);
  
  //prepare object matrix for transformations
  let objectMatrix = FlMatrix.identityMatrix (3) (3);
  
  //deltaTime calculator
  let lastNow;
  
  const updatePosition = (m) => (deltaTime) => 
  	m.mapElements(el => {
    	if(el.column === 2) {
      	if(el.row === 0) {
        	const x =...