Simple Projection

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">
  //Each point has a position and color
  attribute vec3 position;
  attribute vec4 color;

  // The transformation matrices
  uniform mat4 model;
  uniform mat4 projection;

  // Pass the color attribute down to the fragment shader
  varying vec4 vColor;

  void main() {
    
    // Pass the color down to the fragment shader
    vColor = color;
    
    // Read the multiplication in reverse order, the original point is moved
    // into clip space, and then projected into a perspective view by filling
    // in the W component
    gl_Position = projection * model * 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;
  varying vec4 vColor;
  
  void main() {
    gl_FragColor = vColor;
    // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
  }
</script>
  
<canvas id="canvas"></canvas>
  
<h1 class='lesson-title'>
  <a href='../04-divide-by-w'>&larr;</a>
  Simple Projection
  <a href='../06-perspective-matrix'>&rarr;</a>
</h1>

<script>
  //Shared code for the examples
    
    
  // Define the MDN global
  var MDN = {};

  // Define the data that is needed to make a 3d cube
  MDN.createCubeData = function() {
  
    var positions = [
      // Front face
      -1.0, -1.0,  1.0,
       1.0, -1.0,  1.0,
       1.0,  1.0,  1.0,
      -1.0,  1.0,  1.0,

      // Back face
      -1.0, -1.0, -1.0,
      -1.0,  1.0, -1.0,
       1.0,  1.0, -1.0,
       1.0, -1.0, -1.0,

      // Top face
      -1.0,  1.0, -1.0,
      -1.0,  1.0,  1.0,
       1.0,  1.0,  1.0,
       1.0,  1.0, -1.0,

      // Bottom face
      -1.0, -1.0, -1.0,
       1.0, -1.0, -1.0,
       1.0, -1.0,  1.0,
      -1.0, -1.0,  1.0,

      // Right face
       1.0, -1.0, -1.0,
       1.0,  1.0, -1.0,
  ...

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 last step of filling in the W component can actually be accomplished with a simple matrix. Start with the identity matrix:
*/

  var identity = [
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, 0,
	0, 0, 0, 1,
  ];

  MDN.multiplyPoint( identity, [2,3,4,1] );
  //> [2, 3, 4, 1]


// Then move the last column's 1 up one space.
  
  var copyZ = [
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, 1,
	0, 0, 0, 0,
  ];

  MDN.multiplyPoint( copyZ, [2,3,4,1] );
  //> [2, 3, 4, 4]


// However in the last example we performed (z + 1) * scaleFactor
  
  var scaleFactor = 0.5;

  var simpleProjection = [
	1, 0, 0, 0,
	0, 1, 0, 0,
	0, 0, 1, scaleFactor,
	0, 0, 0, scaleFactor,
  ];

  MDN.multiplyPoint( simpleProjection, [2,3,4,1] );
  //> [2, 3, 4, 2.5]


// Breaking this out a little further we can see how the works
  
  var x = (2*1) + (3*0) + (4*0) + (1*0) 
  var y = (2*0) + (3*1) + (4*0) + (1*0) 
  var z = (2*0) + (3*0) + (4*1) + (1*0) 
  var w = (2*0) + (3*0) + (4*scaleFactor) + (1*scaleFactor) 
  

// The last line could be simplified to:

  w = (4 * scaleFactor) + (1 * scaleFactor)

// Then factoring out the scaleFactor

  w = (4 + 1) * scaleFactor

/*
Which is exactly (z + 1) * scaleFactor that we used in the previous example.

In the code below there is an additional .computeSimpleProjectionMatrix() method. This is called in the .draw() method and is passed the scale factor. Adjust this scale factor to verify that it works the same as the previous example.
*/

function CubeDemo () {
  
  // Prep the canvas
  this.canvas = document.getElementById("canvas");
  this.canvas.width = window.innerWidth;
  this.canvas.height = window.innerHeight;
  
  // Grab a context
  this.gl = MDN.createContext(this.canvas);

  this.transforms = {}; // All of the matrix transforms
  this.locations = {}; //All of the shader locations
  
  // Get the rest going
  this.buffers = MDN.createBuffersForCube(this.gl, MDN.createCubeData() );
  this.webglProgram = this.setupProgram();
 ...