Skip to content

Instantly share code, notes, and snippets.

@lancejpollard
Created February 20, 2014 07:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lancejpollard/9108471 to your computer and use it in GitHub Desktop.
Save lancejpollard/9108471 to your computer and use it in GitHub Desktop.
webgl basics
var vs = document.getElementById('vs').textContent;
var fs = document.getElementById('fs').textContent;
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('experimental-webgl', {
alpha: false,
antialias: true,
premultipliedAlpha: false,
stencil: true
});
ctx.disable(ctx.DEPTH_TEST);
ctx.disable(ctx.CULL_FACE);
ctx.viewport(0, 0, canvas.width, canvas.height);
ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
ctx.clearColor(1, 1, 1, 1);
ctx.clear(ctx.COLOR_BUFFER_BIT);
ctx.activeTexture(ctx.TEXTURE0);
var program = ctx.createProgram();
var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
ctx.shaderSource(vertexShader, vs);
ctx.compileShader(vertexShader);
ctx.shaderSource(fragmentShader, fs);
ctx.compileShader(fragmentShader);
ctx.attachShader(program, vertexShader);
ctx.attachShader(program, fragmentShader);
ctx.linkProgram(program);
ctx.useProgram(program);
var vertices = [
-0.5, -0.5,
0.5, -0.5,
0, 0.5
];
var indices = [
0, 1, 2
];
var vertexBuffer = ctx.createBuffer();
ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);
var indexBuffer = ctx.createBuffer();
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.STATIC_DRAW);
var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
ctx.enableVertexAttribArray(aVertexPosition);
ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 0, 0);
var aColor = ctx.getAttribLocation(program, 'aColor');
ctx.enableVertexAttribArray(aVertexPosition);
ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 0, 0);
ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
ctx.drawArrays(ctx.TRIANGLES, 0, 3);
@lancejpollard
Copy link
Author

The number of colors must equal the number of vertices:

<canvas width="600" height="400"></canvas>
<script id="vs" type="x-shader/x-vertex">
  attribute vec4 aVertexColor;
  attribute vec2 aVertexPosition;
  uniform mat3 translationMatrix;
  uniform vec2 projectionVector;
  uniform vec2 offsetVector;
  uniform float alpha;
  uniform vec3 tint;
  varying vec4 vColor;

  void main(void) {
    vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);
    //v -= offsetVector.xyx;
    vColor = aVertexColor;
    //gl_Position = vec4(projectionVector.x - 1.0, projectionVector.y + 1.0, 0.0, 1.0);
    gl_Position = vec4(aVertexPosition, 0, 1);
  }
</script>
<script id="fs" type="x-shader/x-fragment">
  precision mediump float;
  varying vec4 vColor;

  void main(void) {
    gl_FragColor = vColor;
  }
</script>
<script>
  var vs = document.getElementById('vs').textContent;
  var fs = document.getElementById('fs').textContent;
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('experimental-webgl', {
     alpha: false,
     antialias: true,
     premultipliedAlpha: false,
     stencil: true
  });

  ctx.disable(ctx.DEPTH_TEST);
  ctx.disable(ctx.CULL_FACE);
  ctx.viewport(0, 0, canvas.width, canvas.height);
  ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
  ctx.clearColor(1, 1, 1, 1);
  ctx.clear(ctx.COLOR_BUFFER_BIT);
  //ctx.activeTexture(ctx.TEXTURE0);

  var program = ctx.createProgram();
  var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
  var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
  ctx.shaderSource(vertexShader, vs);
  ctx.compileShader(vertexShader);
  ctx.shaderSource(fragmentShader, fs);
  ctx.compileShader(fragmentShader);
  ctx.attachShader(program, vertexShader);
  ctx.attachShader(program, fragmentShader);
  ctx.linkProgram(program);
  ctx.useProgram(program);

  var vertices = [
    -0.5, -0.5, 
    0.5, -0.5,
    0, 0.5
  ];

  var colors = [
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0
  ];

  var indices = [
    0, 1, 2
  ];

  var vertexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);

  var colorBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(colors), ctx.STATIC_DRAW);

  // var indexBuffer = ctx.createBuffer();
  // ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  // ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.STATIC_DRAW);

  var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
  // this is key to be called:
  // https://www.opengl.org/wiki/Vertex_Specification
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.enableVertexAttribArray(aVertexPosition);

  var aVertexColor = ctx.getAttribLocation(program, 'aVertexColor');
  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.enableVertexAttribArray(aVertexColor);

  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 0, 0);

  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.vertexAttribPointer(aVertexColor, 4, ctx.FLOAT, false, 0, 0);

  //ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.drawArrays(ctx.TRIANGLE_STRIP, 0, 3);
  var pointCount = indices.length;
  //ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  //ctx.drawElements(ctx.TRIANGLES, pointCount, ctx.UNSIGNED_SHORT, 0);  
  // http://www.opengl.org/wiki/GLAPI/glDrawElements
  // ctx.drawElements
</script>

@lancejpollard
Copy link
Author

Draw a square:

<canvas width="600" height="400"></canvas>
<script id="vs" type="x-shader/x-vertex">
  attribute vec4 aVertexColor;
  attribute vec2 aVertexPosition;
  uniform mat3 translationMatrix;
  uniform vec2 projectionVector;
  uniform vec2 offsetVector;
  uniform float alpha;
  uniform vec3 tint;
  varying vec4 vColor;

  void main(void) {
    vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);
    //v -= offsetVector.xyx;
    vColor = aVertexColor;
    //gl_Position = vec4(projectionVector.x - 1.0, projectionVector.y + 1.0, 0.0, 1.0);
    gl_Position = vec4(aVertexPosition, 0, 1);
  }
</script>
<script id="fs" type="x-shader/x-fragment">
  precision mediump float;
  varying vec4 vColor;

  void main(void) {
    gl_FragColor = vColor;
  }
</script>
<script>
  var vs = document.getElementById('vs').textContent;
  var fs = document.getElementById('fs').textContent;
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('experimental-webgl', {
     alpha: false,
     antialias: true,
     premultipliedAlpha: false,
     stencil: true
  });

  ctx.disable(ctx.DEPTH_TEST);
  ctx.disable(ctx.CULL_FACE);
  ctx.viewport(0, 0, canvas.width, canvas.height);
  ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
  ctx.clearColor(1, 1, 1, 1);
  ctx.clear(ctx.COLOR_BUFFER_BIT);
  //ctx.activeTexture(ctx.TEXTURE0);

  var program = ctx.createProgram();
  var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
  var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
  ctx.shaderSource(vertexShader, vs);
  ctx.compileShader(vertexShader);
  ctx.shaderSource(fragmentShader, fs);
  ctx.compileShader(fragmentShader);
  ctx.attachShader(program, vertexShader);
  ctx.attachShader(program, fragmentShader);
  ctx.linkProgram(program);
  ctx.useProgram(program);

  var vertices = [
    -0.5, -0.5, 
    0.5, -0.5,
    -0.5, 0.5,
    0.5, 0.5
  ];

  var colors = [
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0
  ];

  var indices = [
    0, 1, 2, 4
  ];

  var vertexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);

  var colorBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(colors), ctx.STATIC_DRAW);

  // var indexBuffer = ctx.createBuffer();
  // ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  // ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.STATIC_DRAW);

  var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
  // this is key to be called:
  // https://www.opengl.org/wiki/Vertex_Specification
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.enableVertexAttribArray(aVertexPosition);

  var aVertexColor = ctx.getAttribLocation(program, 'aVertexColor');
  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.enableVertexAttribArray(aVertexColor);

  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 0, 0);

  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.vertexAttribPointer(aVertexColor, 4, ctx.FLOAT, false, 0, 0);

  var pointCount = indices.length;
  ctx.drawArrays(ctx.TRIANGLE_STRIP, 0, pointCount);
</script>

@lancejpollard
Copy link
Author

Draw square using drawElements:

<canvas width="600" height="400"></canvas>
<script id="vs" type="x-shader/x-vertex">
  attribute vec4 aVertexColor;
  attribute vec2 aVertexPosition;
  uniform mat3 translationMatrix;
  uniform vec2 projectionVector;
  uniform vec2 offsetVector;
  uniform float alpha;
  uniform vec3 tint;
  varying vec4 vColor;

  void main(void) {
    vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);
    //v -= offsetVector.xyx;
    vColor = aVertexColor;
    //gl_Position = vec4(projectionVector.x - 1.0, projectionVector.y + 1.0, 0.0, 1.0);
    gl_Position = vec4(aVertexPosition, 0, 1);
  }
</script>
<script id="fs" type="x-shader/x-fragment">
  precision mediump float;
  varying vec4 vColor;

  void main(void) {
    gl_FragColor = vColor;
  }
</script>
<script>
  var vs = document.getElementById('vs').textContent;
  var fs = document.getElementById('fs').textContent;
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('experimental-webgl', {
     alpha: false,
     antialias: true,
     premultipliedAlpha: false,
     stencil: true
  });

  ctx.disable(ctx.DEPTH_TEST);
  ctx.disable(ctx.CULL_FACE);
  ctx.viewport(0, 0, canvas.width, canvas.height);
  ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
  ctx.clearColor(1, 1, 1, 1);
  ctx.clear(ctx.COLOR_BUFFER_BIT);
  //ctx.activeTexture(ctx.TEXTURE0);

  var program = ctx.createProgram();
  var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
  var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
  ctx.shaderSource(vertexShader, vs);
  ctx.compileShader(vertexShader);
  ctx.shaderSource(fragmentShader, fs);
  ctx.compileShader(fragmentShader);
  ctx.attachShader(program, vertexShader);
  ctx.attachShader(program, fragmentShader);
  ctx.linkProgram(program);
  ctx.useProgram(program);

  var vertices = [
    -0.5, -0.5, 
    0.5, -0.5,
    -0.5, 0.5,
    0.5, 0.5
  ];

  var colors = [
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0,
    0.0, 0.8, 0.0, 1.0
  ];

  var indices = [
    0, 1, 2, 3 // if you change on of these to `4` or something,  it breaks. so these point to actual indices
  ];

  var vertexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);

  var colorBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(colors), ctx.STATIC_DRAW);

  var indexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.STATIC_DRAW);

  var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
  // this is key to be called:
  // https://www.opengl.org/wiki/Vertex_Specification
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.enableVertexAttribArray(aVertexPosition);

  var aVertexColor = ctx.getAttribLocation(program, 'aVertexColor');
  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.enableVertexAttribArray(aVertexColor);

  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 0, 0);

  ctx.bindBuffer(ctx.ARRAY_BUFFER, colorBuffer);
  ctx.vertexAttribPointer(aVertexColor, 4, ctx.FLOAT, false, 0, 0);

  var pointCount = indices.length;
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.drawElements(ctx.TRIANGLE_STRIP, pointCount, ctx.UNSIGNED_SHORT, 0);
</script>

@lancejpollard
Copy link
Author

Here is how you'd combine the colors and vertices into one large array (for optimization):

<script>
  var vs = document.getElementById('vs').textContent;
  var fs = document.getElementById('fs').textContent;
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('experimental-webgl', {
     alpha: false,
     antialias: true,
     premultipliedAlpha: false,
     stencil: true
  });

  ctx.disable(ctx.DEPTH_TEST);
  ctx.disable(ctx.CULL_FACE);
  ctx.viewport(0, 0, canvas.width, canvas.height);
  ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
  ctx.clearColor(1, 1, 1, 1);
  ctx.clear(ctx.COLOR_BUFFER_BIT);
  //ctx.activeTexture(ctx.TEXTURE0);

  var program = ctx.createProgram();
  var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
  var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
  ctx.shaderSource(vertexShader, vs);
  ctx.compileShader(vertexShader);
  ctx.shaderSource(fragmentShader, fs);
  ctx.compileShader(fragmentShader);
  ctx.attachShader(program, vertexShader);
  ctx.attachShader(program, fragmentShader);
  ctx.linkProgram(program);
  ctx.useProgram(program);

  var vertices = [
    -0.5, -0.5, 0.0, 0.8, 0.0, 1.0,
    0.5, -0.5, 0.0, 0.8, 0.0, 1.0,
    -0.5, 0.5, 0.0, 0.8, 0.0, 1.0,
    0.5, 0.5, 0.0, 0.8, 0.0, 1.0
  ];

  var indices = [
    0, 1, 2, 3
  ];

  var vertexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);

  var indexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.STATIC_DRAW);

  var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
  var aVertexColor = ctx.getAttribLocation(program, 'aVertexColor');
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.enableVertexAttribArray(aVertexPosition);
  ctx.enableVertexAttribArray(aVertexColor);

  // 4 * 6 is the "stride", 4 bytes per float, 6 floats per "vertex"
  ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 4 * 6, 0);
  // 4 * 2 is the "offset", 4 bytes per float, and colors start 2 after the x,y coordinates
  ctx.vertexAttribPointer(aVertexColor, 4, ctx.FLOAT, false, 4 * 6, 4 * 2);

  var pointCount = indices.length;
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.drawElements(ctx.TRIANGLE_STRIP, pointCount, ctx.UNSIGNED_SHORT, 0);
</script>

@lancejpollard
Copy link
Author

Example with basic shapes (triangle, square, circle):

<script>
  var vs = document.getElementById('vs').textContent;
  var fs = document.getElementById('fs').textContent;
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('experimental-webgl', {
     alpha: false,
     antialias: true,
     premultipliedAlpha: false,
     stencil: true
  });

  ctx.disable(ctx.DEPTH_TEST);
  ctx.disable(ctx.CULL_FACE);
  ctx.viewport(0, 0, canvas.width, canvas.height);
  ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
  ctx.clearColor(1, 1, 1, 1);
  ctx.clear(ctx.COLOR_BUFFER_BIT);
  //ctx.activeTexture(ctx.TEXTURE0);

  var program = ctx.createProgram();
  var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
  var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
  ctx.shaderSource(vertexShader, vs);
  ctx.compileShader(vertexShader);
  ctx.shaderSource(fragmentShader, fs);
  ctx.compileShader(fragmentShader);
  ctx.attachShader(program, vertexShader);
  ctx.attachShader(program, fragmentShader);
  ctx.linkProgram(program);
  ctx.useProgram(program);

  var vertices = [];
  var indices = [];
  var r = 0.0;
  var g = 0.8;
  var b = 0.0;
  var a = 1.0;

  // triangle();
  // square();
  circle();

  var vertexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, new Float32Array(vertices), ctx.STATIC_DRAW);

  var indexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.STATIC_DRAW);

  var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
  var aVertexColor = ctx.getAttribLocation(program, 'aVertexColor');
  // this is key to be called:
  // https://www.opengl.org/wiki/Vertex_Specification
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.enableVertexAttribArray(aVertexPosition);
  ctx.enableVertexAttribArray(aVertexColor);

  ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 4 * 6, 0);
  ctx.vertexAttribPointer(aVertexColor, 4, ctx.FLOAT, false, 4 * 6, 4 * 2);

  var pointCount = indices.length;
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.drawElements(ctx.TRIANGLE_STRIP, pointCount, ctx.UNSIGNED_SHORT, 0);

  function circle() {
    var arr = [];
    var index = 0;
    var segments = 40; // arbitrary number of points to define circumference.
    var segment = (2 * Math.PI) / segments;
    var x = 0;
    var y = 0;
    var width = 0.5;
    var height = 0.5;

    // add the first index
    indices.push(index);

    for (var i = 0, n = segments + 1; i < n; i++) {
      vertices.push(x, y, r, g, b, a);

      vertices.push(
        x + Math.sin(segment * i) * width,
        y + Math.cos(segment * i) * height,
        r, g, b, a
      );

      indices.push(index++, index++);
    }

    indices.push(index - 1);
  }

  function square() {
    vertices = [
      -0.5, -0.5, r, g, b, a,
      0.5, -0.5, r, g, b, a,
      -0.5, 0.5, r, g, b, a,
      0.5, 0.5, r, g, b, a
    ];

    indices = [
      0, 1, 2, 3
    ];
  }

  function triangle() {
    vertices = [
      -0.5, -0.5, r, g, b, a,
      0.5, -0.5, r, g, b, a,
      -0.5, 0.5, r, g, b, a
    ];

    indices = [
      0, 1, 2
    ];
  }
</script>

@lancejpollard
Copy link
Author

Basic animation:

<canvas width="600" height="400"></canvas>
<script id="vs" type="x-shader/x-vertex">
  attribute vec4 aVertexColor;
  attribute vec2 aVertexPosition;
  uniform mat3 translationMatrix;
  uniform vec2 projectionVector;
  uniform vec2 offsetVector;
  uniform float alpha;
  uniform vec3 tint;
  varying vec4 vColor;

  void main(void) {
    vec3 v = translationMatrix * vec3(aVertexPosition, 1.0);
    //v -= offsetVector.xyx;
    vColor = aVertexColor;
    //gl_Position = vec4(projectionVector.x - 1.0, projectionVector.y + 1.0, 0.0, 1.0);
    gl_Position = vec4(aVertexPosition, 0, 1);
  }
</script>
<script id="fs" type="x-shader/x-fragment">
  precision mediump float;
  varying vec4 vColor;

  void main(void) {
    gl_FragColor = vColor;
  }
</script>
<script>
  var next = require('component-raf');
  var vs = document.getElementById('vs').textContent;
  var fs = document.getElementById('fs').textContent;
  var canvas = document.querySelector('canvas');
  var ctx = canvas.getContext('experimental-webgl', {
     alpha: false,
     antialias: true,
     premultipliedAlpha: false,
     stencil: true
  });

  ctx.disable(ctx.DEPTH_TEST);
  ctx.disable(ctx.CULL_FACE);
  ctx.viewport(0, 0, canvas.width, canvas.height);
  ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
  ctx.clearColor(1, 1, 1, 1);
  ctx.clear(ctx.COLOR_BUFFER_BIT);
  //ctx.activeTexture(ctx.TEXTURE0);

  var program = ctx.createProgram();
  var vertexShader = ctx.createShader(ctx.VERTEX_SHADER);
  var fragmentShader = ctx.createShader(ctx.FRAGMENT_SHADER);
  ctx.shaderSource(vertexShader, vs);
  ctx.compileShader(vertexShader);
  ctx.shaderSource(fragmentShader, fs);
  ctx.compileShader(fragmentShader);
  ctx.attachShader(program, vertexShader);
  ctx.attachShader(program, fragmentShader);
  ctx.linkProgram(program);
  ctx.useProgram(program);

  var vertices = [];
  var indices = [];
  var r = 0.0;
  var g = 0.8;
  var b = 0.0;
  var a = 1.0;

  // triangle();
  square();
  // circle();

  var vertexBuffer = ctx.createBuffer();
  var verticesArray = new Float32Array(vertices);
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.bufferData(ctx.ARRAY_BUFFER, verticesArray, ctx.DYNAMIC_DRAW);

  var indexBuffer = ctx.createBuffer();
  ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
  ctx.bufferData(ctx.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), ctx.DYNAMIC_DRAW);

  var aVertexPosition = ctx.getAttribLocation(program, 'aVertexPosition');
  var aVertexColor = ctx.getAttribLocation(program, 'aVertexColor');
  // this is key to be called:
  // https://www.opengl.org/wiki/Vertex_Specification
  ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
  ctx.enableVertexAttribArray(aVertexPosition);
  ctx.enableVertexAttribArray(aVertexColor);

  function draw() {
    ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
    ctx.vertexAttribPointer(aVertexPosition, 2, ctx.FLOAT, false, 4 * 6, 0);
    ctx.vertexAttribPointer(aVertexColor, 4, ctx.FLOAT, false, 4 * 6, 4 * 2);

    var pointCount = indices.length;
    ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, indexBuffer);
    ctx.drawElements(ctx.TRIANGLE_STRIP, pointCount, ctx.UNSIGNED_SHORT, 0);

    ctx.bindBuffer(ctx.ARRAY_BUFFER, vertexBuffer);
    ctx.bufferSubData(ctx.ARRAY_BUFFER, 0, verticesArray);
  }

  animate();

  function animate() {
    for (var i = 0, n = verticesArray.length; i < n; i++) {
      verticesArray[i] += (0.001 * i);
    }

    draw();
    next(animate);
  }

  function circle() {
    var arr = [];
    var index = 0;
    var segments = 40; // arbitrary number of points to define circumference.
    var segment = (2 * Math.PI) / segments;
    var x = 0;
    var y = 0;
    var width = 0.5;
    var height = 0.5;

    // add the first index
    indices.push(index);

    for (var i = 0, n = segments + 1; i < n; i++) {
      vertices.push(x, y, r, g, b, a);

      vertices.push(
        x + Math.sin(segment * i) * width,
        y + Math.cos(segment * i) * height,
        r, g, b, a
      );

      indices.push(index++, index++);
    }

    indices.push(index - 1);
  }

  function square() {
    vertices = [
      -0.5, -0.5, r, g, b, a,
      0.5, -0.5, r, g, b, a,
      -0.5, 0.5, r, g, b, a,
      0.5, 0.5, r, g, b, a
    ];

    indices = [
      0, 1, 2, 3
    ];
  }

  function triangle() {
    vertices = [
      -0.5, -0.5, r, g, b, a,
      0.5, -0.5, r, g, b, a,
      -0.5, 0.5, r, g, b, a
    ];

    indices = [
      0, 1, 2
    ];
  }
</script>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment