Clip Space

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

<!--
A quick side note about shaders: The shader code in these examples is put into a script tag with a non-standard script type of x-shader. There is nothing magical going on here, just a convention to let us know what type of code the script tag contains. The JavaScript in the examples pull this source code in by accessing the .innerHTML property of the script elements and then compiling and linking the source code into a real shader using the gl context.
-->

<!--
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 in clip space 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.
  The range of values is from 0.0 to 1.0.
-->
<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...

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

/*

In a WebGL program data is typically uploaded to the GPU with its own coordinate system and then the vertex shader transforms those points into a different coordinate system known as clip space. If any data is outside of the clip space, then it is clipped off and not rendered. Sometimes new triangles are created automatically when the data is both inside and outside of the clip space.

View the clipspace-graph.svg (https://github.com/TatumCreative/mdn-model-view-projection/blob/master/lessons/01-clip-space/clip-space-graph.svg) to see a visualization of this space that all of the points must fit into. It is 2 units wide, and consists of a cube from the corner (-1,-1,-1) to the corner (1,1,1). The middle of the cube is the point (0,0,0).

For this lesson we won't figure out how to transform our data into this clip space, instead we will send data to the GPU already in this coordinate system. The code below will create 2 triangles that will draw a square on the screen. The Z depth in the squares determines what gets drawn ontop when the squares share the same space. The smaller Z values are rendered ontop of the larger Z values.
  
Note: See the MDN global object defined in the html script tag for some shared functions that are used in this example. These functions are written for code clarity, not necessarily performance for real time visualizations.

Exercise:

1) Change the example code to draw a black smile, and two black eyes on a yellow face using only the boxes.

*/

// To start, let's make a class that will draw a 2d box using WebGL

function WebGLBox() {
  
  // Setup the canvas and WebGL context
  this.canvas = document.getElementById("canvas");
  this.canvas.width = window.innerWidth;
  this.canvas.height = window.innerHeight;
  this.gl = MDN.createContext(canvas);
  
  var gl = this.gl; 

  // Setup a WebGL program, see /shared/shaders.js for the function
  // definition of createWebGLProgramFromIds()
  this.webglProgram =...