Homogeneous Coordinates

This fiddle is part of the MDN content kit for WebGL Model View Projection. https://github.com/TatumCreative/mdn-model-view-projection

by tatumcreative

HTML

<!-- The vertex shader operates on individual vertices in our model data by setting gl_Position -->
<script id="vertex-shader" type="x-shader/x-vertex">
  // The individual position vertex
  attribute vec3 position;

  void main() {
  
    // the gl_Position is the final position after the vertex shader modifies it
    gl_Position = vec4(position, 1.0);
  }
</script>

<!-- The fragment shader determines the color of the final pixel by setting gl_FragColor -->
<script id="fragment-shader" type="x-shader/x-fragment">
  precision mediump float;
  uniform vec4 color;

  void main() {
    gl_FragColor = color;
  }
</script>
  
<canvas id="canvas"></canvas>

<!-- The SVG overlay showing clip space -->
<svg
  style='width:100%; height:100%; position:absolute; top:0; left:0;'
  version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
  x="0px" y="0px"
	viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve" preserveAspectRatio="none">
  
	<g>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,25.5 249.5,25.5 249.5,0.5 274,0.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,50.5 249.5,50.5 249.5,25.5 262,25.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,75.5 249.5,75.5 249.5,50.5 262,50.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,100.5 249.5,100.5 249.5,75.5 262,75.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="274,125.5 249.5,125.5 249.5,100.5 262,100.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,150.5 249.5,150.5 249.5,125.5 274,125.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,175.5 249.5,175.5 249.5,150.5 262,150.5"/>
		<polyline fill="none" stroke="#000000" stroke-miterlimit="10" points="262,200.5 249.5,200.5 249.5,175.5 262,175.5"/>
		<polyline fill="none" stroke="#000000"...

CSS

html, body {
	width:100%;
	height:100%;
	margin: 0;
}
canvas {
	width: 100% !important;
	height: 100% !important;
}
.lesson-title {
  position: absolute;
  bottom: 0;
  left: 0;
  margin: 0.7em;
  font-family: sans-serif;
  font-size: 1em;
  color: #888;
  font-weight: normal;
}
.lesson-title a {
	text-decoration: none;
	color: #668;
}
.lesson-title a:hover {
	color: #338;
}

JavaScript

/*
The main line of the previous clip space vertex shader contained this code:

  gl_Position = vec4(position, 1.0);
  
The position variable is what was passed in as an attribute to the shader and was defined in the draw method. This is a three dimensional point, but the gl_Position variable that ends up getting passed down through the pipeline is actually 4 dimensions. Instead of (x,y,z) it is (x,y,z,w). In this example   the w coordinate is being set to 1.0. The obvious question is "why the extra dimension?" It turns out that this addition allows for lots of nice techniques for manipulating 3d data.

A three dimensional point is defined in a typical Cartesian coordinate system.  The added 4th dimension changes this point into a homogeneous coordinate. It still represents a point in 3d space and it can easily be demonstrated how to construct this type of coordinate through a pair of simple functions.
*/

function cartesianToHomogeneous (point) {
  
  var x = point[0];
  var y = point[1];
  var z = point[2];
  
  return [x, y, z, 1];
}

function homogeneousToCartesian (point) {

  var x = point[0];
  var y = point[1];
  var z = point[2];
  var w = point[3];
  
  return [x/w, y/w, z/w];
}

/*
As can be seen, the w component divides the x, y, and z components. When the w component is a non-zero real number then homogeneous coordinate easily translates back into a normal point in Cartesian space. Now what happens if the w component is zero? In JavaScript the value returned would be as follows.
*/

homogeneousToCartesian([10,4,5,0]);

// Evaluates to: [Infinity, Infinity, Infinity]

/*
This homogeneous coordinate represents some point at infinity. This is a handy way to represent a ray shooting off from the origin in a specific direction. In addition to a ray, it could also be thought of as a representation of a directional vector. If this homogeneous coordinate is multiplied against a matrix with a translation then the translation is effectively stripped out.

TODO...