TWGL

A Tiny WebGL helper Library

README

TWGL: A Tiny WebGL helper Library
[rhymes with wiggle]
=====================================================
Build Status

This library's sole purpose is to make using the WebGL API less verbose.

TL;DR


If you want to get stuff done use three.js. If you want
to do stuff low-level with WebGL consider using TWGL.

The tiniest example


Not including the shaders (which is a simple quad shader) here's the entire code

  1. ``` html
  2. <canvas id="c"></canvas>
  3. <script src="../dist/5.x/twgl-full.min.js"></script>
  4. <script>
  5.   const gl = document.getElementById("c").getContext("webgl");
  6.   const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
  7.   const arrays = {
  8.     position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
  9.   };
  10.   const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
  11.   function render(time) {
  12.     twgl.resizeCanvasToDisplaySize(gl.canvas);
  13.     gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  14.     const uniforms = {
  15.       time: time * 0.001,
  16.       resolution: [gl.canvas.width, gl.canvas.height],
  17.     };
  18.     gl.useProgram(programInfo.program);
  19.     twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  20.     twgl.setUniforms(programInfo, uniforms);
  21.     twgl.drawBufferInfo(gl, bufferInfo);
  22.     requestAnimationFrame(render);
  23.   }
  24.   requestAnimationFrame(render);
  25. </script>
  26. ```


Why? What? How?


WebGL is a very verbose API. Setting up shaders, buffers, attributes and uniforms
takes a lot of code. A simple lit cube in WebGL might easily take over 60 calls into WebGL.

At its core there's really only a few main functions

  twgl.createProgramInfo compiles a shader and creates setters for attribs and uniforms
  twgl.createBufferInfoFromArrays creates buffers and attribute settings
  twgl.setBuffersAndAttributes binds buffers and sets attributes
  twgl.setUniforms sets the uniforms
  twgl.createTextures creates textures of various sorts
  twgl.createFramebufferInfo creates a framebuffer and attachments.

There's a few extra helpers and lower-level functions if you need them but those 6 functions are the core of TWGL.

Compare the TWGL vs WebGL code for a point lit cube.

Compiling a Shader and looking up locations


TWGL

  1. ``` js
  2. const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
  3. ```

WebGL

  1. ``` js
  2. // Note: I'm conceding that you'll likely already have the 30 lines of
  3. // code for compiling GLSL
  4. const program = twgl.createProgramFromScripts(gl, ["vs", "fs"]);

  5. const u_lightWorldPosLoc = gl.getUniformLocation(program, "u_lightWorldPos");
  6. const u_lightColorLoc = gl.getUniformLocation(program, "u_lightColor");
  7. const u_ambientLoc = gl.getUniformLocation(program, "u_ambient");
  8. const u_specularLoc = gl.getUniformLocation(program, "u_specular");
  9. const u_shininessLoc = gl.getUniformLocation(program, "u_shininess");
  10. const u_specularFactorLoc = gl.getUniformLocation(program, "u_specularFactor");
  11. const u_diffuseLoc = gl.getUniformLocation(program, "u_diffuse");
  12. const u_worldLoc = gl.getUniformLocation(program, "u_world");
  13. const u_worldInverseTransposeLoc = gl.getUniformLocation(program, "u_worldInverseTranspose");
  14. const u_worldViewProjectionLoc = gl.getUniformLocation(program, "u_worldViewProjection");
  15. const u_viewInverseLoc = gl.getUniformLocation(program, "u_viewInverse");

  16. const positionLoc = gl.getAttribLocation(program, "a_position");
  17. const normalLoc = gl.getAttribLocation(program, "a_normal");
  18. const texcoordLoc = gl.getAttribLocation(program, "a_texcoord");
  19. ```

Creating Buffers for a Cube


TWGL

  1. ``` js
  2. const arrays = {
  3.   position: [1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,1,1,-1,1,1,-1,-1,1,1,-1,1,-1,1,-1,1,1,-1,1,-1,-1,-1,-1,-1],
  4.   normal:   [1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1],
  5.   texcoord: [1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1],
  6.   indices:  [0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23],
  7. };
  8. const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
  9. ```

WebGL
  1. ``` js
  2. const positions = [1,1,-1,1,1,1,1,-1,1,1,-1,-1,-1,1,1,-1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,1,1,1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,1,1,-1,1,1,-1,-1,1,1,-1,1,-1,1,-1,1,1,-1,1,-1,-1,-1,-1,-1];
  3. const normals   = [1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,-1,0,0,-1,0,0,-1,0,0,-1];
  4. const texcoords = [1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1];
  5. const indices   = [0,1,2,0,2,3,4,5,6,4,6,7,8,9,10,8,10,11,12,13,14,12,14,15,16,17,18,16,18,19,20,21,22,20,22,23];

  6. const positionBuffer = gl.createBuffer();
  7. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  8. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
  9. const normalBuffer = gl.createBuffer();
  10. gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
  11. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
  12. const texcoordBuffer = gl.createBuffer();
  13. gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  14. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
  15. const indicesBuffer = gl.createBuffer();
  16. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
  17. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
  18. ```

Setting Attributes and Indices for a Cube


TWGL

  1. ``` js
  2. twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  3. ```

WebGL

  1. ``` js
  2. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  3. gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
  4. gl.enableVertexAttribArray(positionLoc);
  5. gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
  6. gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
  7. gl.enableVertexAttribArray(normalLoc);
  8. gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  9. gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
  10. gl.enableVertexAttribArray(texcoordLoc);
  11. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
  12. ```

Setting Uniforms for a Lit Cube


TWGL

  1. ``` js
  2. // At Init time
  3. const uniforms = {
  4.   u_lightWorldPos: [1, 8, -10],
  5.   u_lightColor: [1, 0.8, 0.8, 1],
  6.   u_ambient: [0, 0, 0, 1],
  7.   u_specular: [1, 1, 1, 1],
  8.   u_shininess: 50,
  9.   u_specularFactor: 1,
  10.   u_diffuse: tex,
  11. };

  12. // At render time
  13. uniforms.u_viewInverse = camera;
  14. uniforms.u_world = world;
  15. uniforms.u_worldInverseTranspose = m4.transpose(m4.inverse(world));
  16. uniforms.u_worldViewProjection = m4.multiply(viewProjection, world);

  17. twgl.setUniforms(programInfo, uniforms);
  18. ```

WebGL

  1. ``` js
  2. // At Init time
  3. const u_lightWorldPos = [1, 8, -10];
  4. const u_lightColor = [1, 0.8, 0.8, 1];
  5. const u_ambient = [0, 0, 0, 1];
  6. const u_specular = [1, 1, 1, 1];
  7. const u_shininess = 50;
  8. const u_specularFactor = 1;
  9. const u_diffuse = 0;

  10. // At render time
  11. gl.uniform3fv(u_lightWorldPosLoc, u_lightWorldPos);
  12. gl.uniform4fv(u_lightColorLoc, u_lightColor);
  13. gl.uniform4fv(u_ambientLoc, u_ambient);
  14. gl.uniform4fv(u_specularLoc, u_specular);
  15. gl.uniform1f(u_shininessLoc, u_shininess);
  16. gl.uniform1f(u_specularFactorLoc, u_specularFactor);
  17. gl.uniform1i(u_diffuseLoc, u_diffuse);
  18. gl.uniformMatrix4fv(u_viewInverseLoc, false, camera);
  19. gl.uniformMatrix4fv(u_worldLoc, false, world);
  20. gl.uniformMatrix4fv(u_worldInverseTransposeLoc, false, m4.transpose(m4.inverse(world)));
  21. gl.uniformMatrix4fv(u_worldViewProjectionLoc, false, m4.multiply(viewProjection, world));
  22. ```

Loading / Setting up textures


TWGL

  1. ``` js
  2. const textures = twgl.createTextures(gl, {
  3.   // a power of 2 image
  4.   hftIcon: { src: "images/hft-icon-16.png", mag: gl.NEAREST },
  5.   // a non-power of 2 image
  6.   clover: { src: "images/clover.jpg" },
  7.   // From a canvas
  8.   fromCanvas: { src: ctx.canvas },
  9.   // A cubemap from 6 images
  10.   yokohama: {
  11.     target: gl.TEXTURE_CUBE_MAP,
  12.     src: [
  13.       'images/yokohama/posx.jpg',
  14.       'images/yokohama/negx.jpg',
  15.       'images/yokohama/posy.jpg',
  16.       'images/yokohama/negy.jpg',
  17.       'images/yokohama/posz.jpg',
  18.       'images/yokohama/negz.jpg',
  19.     ],
  20.   },
  21.   // A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)
  22.   goldengate: {
  23.     target: gl.TEXTURE_CUBE_MAP,
  24.     src: 'images/goldengate.jpg',
  25.   },
  26.   // A 2x2 pixel texture from a JavaScript array
  27.   checker: {
  28.     mag: gl.NEAREST,
  29.     min: gl.LINEAR,
  30.     src: [
  31.       255,255,255,255,
  32.       192,192,192,255,
  33.       192,192,192,255,
  34.       255,255,255,255,
  35.     ],
  36.   },
  37.   // a 1x8 pixel texture from a typed array.
  38.   stripe: {
  39.     mag: gl.NEAREST,
  40.     min: gl.LINEAR,
  41.     format: gl.LUMINANCE,
  42.     src: new Uint8Array([
  43.       255,
  44.       128,
  45.       255,
  46.       128,
  47.       255,
  48.       128,
  49.       255,
  50.       128,
  51.     ]),
  52.     width: 1,
  53.   },
  54. });
  55. ```

WebGL

  1. ``` js
  2. // Let's assume I already loaded all the images

  3. // a power of 2 image
  4. const hftIconTex = gl.createTexture();
  5. gl.bindTexture(gl.TEXTURE_2D, tex);
  6. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, hftIconImg);
  7. gl.generateMipmaps(gl.TEXTURE_2D);
  8. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  9. // a non-power of 2 image
  10. const cloverTex = gl.createTexture();
  11. gl.bindTexture(gl.TEXTURE_2D, tex);
  12. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, hftIconImg);
  13. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  14. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  15. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  16. // From a canvas
  17. const cloverTex = gl.createTexture();
  18. gl.bindTexture(gl.TEXTURE_2D, tex);
  19. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
  20. gl.generateMipmaps(gl.TEXTURE_2D);
  21. // A cubemap from 6 images
  22. const yokohamaTex = gl.createTexture();
  23. gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
  24. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, posXImg);
  25. gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, negXImg);
  26. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, posYImg);
  27. gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, negYImg);
  28. gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, posZImg);
  29. gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, negZImg);
  30. gl.generateMipmaps(gl.TEXTURE_CUBE_MAP);
  31. // A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)
  32. const goldengateTex = gl.createTexture();
  33. gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
  34. const size = goldengate.width / 3;  // assume it's a 3x2 texture
  35. const slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1];
  36. const tempCtx = document.createElement("canvas").getContext("2d");
  37. tempCtx.canvas.width = size;
  38. tempCtx.canvas.height = size;
  39. for (let ii = 0; ii < 6; ++ii) {
  40.   const xOffset = slices[ii * 2 + 0] * size;
  41.   const yOffset = slices[ii * 2 + 1] * size;
  42.   tempCtx.drawImage(element, xOffset, yOffset, size, size, 0, 0, size, size);
  43.   gl.texImage2D(faces[ii], 0, format, format, type, tempCtx.canvas);
  44. }
  45. gl.generateMipmaps(gl.TEXTURE_CUBE_MAP);
  46. // A 2x2 pixel texture from a JavaScript array
  47. const checkerTex = gl.createTexture();
  48. gl.bindTexture(gl.TEXTURE_2D, tex);
  49. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
  50.     255,255,255,255,
  51.     192,192,192,255,
  52.     192,192,192,255,
  53.     255,255,255,255,
  54.   ]));
  55. gl.generateMipmaps(gl.TEXTURE_2D);
  56. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  57. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  58. // a 1x8 pixel texture from a typed array.
  59. const stripeTex = gl.createTexture();
  60. gl.bindTexture(gl.TEXTURE_2D, tex);
  61. gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
  62. gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 1, 8, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, new Uint8Array([
  63.     255,
  64.     128,
  65.     255,
  66.     128,
  67.     255,
  68.     128,
  69.     255,
  70.     128,
  71.   ]));
  72. gl.generateMipmaps(gl.TEXTURE_2D);
  73. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  74. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  75. ```

Creating Framebuffers and attachments


TWGL

  1. ``` js
  2. const attachments = [
  3.   { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE },
  4.   { format: DEPTH_STENCIL, },
  5. ];
  6. const fbi = twgl.createFramebufferInfo(gl, attachments);
  7. ```

WebGL

  1. ``` js
  2. const fb = gl.createFramebuffer(gl.FRAMEBUFFER);
  3. gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
  4. const tex = gl.createTexture();
  5. gl.bindTexture(gl.TEXTURE_2D, tex);
  6. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
  7. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  8. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  9. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  10. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
  11. const rb = gl.createRenderbuffer();
  12. gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
  13. gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, gl.drawingBufferWidth, gl.drawingBufferHeight);
  14. gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb);
  15. ```

Setting uniform and uniformblock structures and arrays


Given an array of GLSL structures like this

  1. ```glsl
  2. struct Light {
  3.   float intensity;
  4.   float shininess;
  5.   vec4 color;
  6. }
  7. uniform Light lights[2];
  8. ```

TWGL

  1. ``` js
  2. const progInfo = twgl.createProgramInfo(gl, [vs, fs]);
  3. ...
  4. twgl.setUniforms(progInfo, {
  5.   lights: [
  6.     { intensity: 5.0, shininess: 100, color: [1, 0, 0, 1] },
  7.     { intensity: 2.0, shininess:  50, color: [0, 0, 1, 1] },
  8.   ],
  9. });
  10. ```

WebGL

  1. ``` js
  2. // assuming we already compiled and linked the program
  3. const light0IntensityLoc = gl.getUniformLocation('lights[0].intensity');
  4. const light0ShininessLoc = gl.getUniformLocation('lights[0].shininess');
  5. const light0ColorLoc = gl.getUniformLocation('lights[0].color');
  6. const light1IntensityLoc = gl.getUniformLocation('lights[1].intensity');
  7. const light1ShininessLoc = gl.getUniformLocation('lights[1].shininess');
  8. const light1ColorLoc = gl.getUniformLocation('lights[1].color');
  9. ...
  10. gl.uniform1f(light0IntensityLoc, 5.0);
  11. gl.uniform1f(light0ShininessLoc, 100);
  12. gl.uniform4fv(light0ColorLoc, [1, 0, 0, 1]);
  13. gl.uniform1f(light1IntensityLoc, 2.0);
  14. gl.uniform1f(light1ShininessLoc, 50);
  15. gl.uniform4fv(light1ColorLoc, [0, 0, 1, 1]);
  16. ```

If you just want to set the 2nd light in TWGL you can do this

  1. ``` js
  2. const progInfo = twgl.createProgramInfo(gl, [vs, fs]);
  3. ...
  4. twgl.setUniforms(progInfo, {
  5.   'lights[1]': { intensity: 5.0, shininess: 100, color: [1, 0, 0, 1] },
  6. });
  7. ```

Compare



Examples


  tiny
  text
  tunnel

WebGL 2 Examples



OffscreenCanvas Example



ES6 module support



AMD support


  amd

CommonJS / Browserify support



Other Features


  Includes some optional 3d math functions (full version)

    You are welcome to use any math library as long as it stores matrices as flat Float32Array
    or JavaScript arrays.

  Includes some optional primitive generators (full version)

    planes, cubes, spheres, ... Just to help get started

Usage


See the examples. Otherwise there's a few different versions

  twgl-full.module.js the es6 module version
  twgl-full.min.js the minified full version
  twgl-full.js the concatenated full version
  twgl.min.js the minimum version (no 3d math, no primitives)
  twgl.js the concatenated minimum version (no 3d math, no primitives)

Download


  from github


  from bower

  1. ``` sh
  2.     bower install twgl.js
  3. ```

  from npm

  1. ``` sh
  2.     npm install twgl.js
  3. ```

    or

  1. ``` sh
  2.     npm install twgl-base.js
  3. ```

  from git

  1. ``` sh
  2.     git clone https://github.com/greggman/twgl.js.git
  3. ```

Rationale and other chit-chat


TWGL's is an attempt to make WebGL simpler by providing a few tiny helper functions
that make it much less verbose and remove the tedium. TWGL is NOT trying to help
with the complexity of managing shaders and writing GLSL. Nor is it a 3D library like
three.js. It's just trying to make WebGL less verbose.

TWGL can be considered a spiritual successor to TDL. Where
as TDL created several classes that wrapped WebGL, TWGL tries not to wrap anything. In fact
you can manually create nearly all TWGL data structures.

For example the function setAttributes takes an object of attributes.
In WebGL you might write code like this

  1. ``` js
  2. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  3. gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
  4. gl.enableVertexAttribArray(positionLoc);
  5. gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
  6. gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
  7. gl.enableVertexAttribArray(normalLoc);
  8. gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  9. gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
  10. gl.enableVertexAttribArray(texcoordLoc);
  11. gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
  12. gl.vertexAttribPointer(colorLoc, 4, gl.UNSIGNED_BYTE, true, 0, 0);
  13. gl.enableVertexAttribArray(colorLoc);
  14. ```

setAttributes is just the simplest code to do that for you.

  1. ``` js
  2. // make attributes for TWGL manually
  3. const attribs = {
  4.   a_position: { buffer: positionBuffer, size: 3, },
  5.   a_normal:   { buffer: normalBuffer,   size: 3, },
  6.   a_texcoord: { buffer: texcoordBuffer, size: 2, },
  7.   a_color:    { buffer: colorBuffer,    size: 4, type: gl.UNSIGNED_BYTE, normalize: true, },
  8. };
  9. twgl.setAttributes(attribSetters, attribs);
  10. ```

The point of the example above is TWGL is a thin wrapper. All it's doing is trying
to make common WebGL operations easier and less verbose. Feel free to mix it with raw WebGL.

API Docs



Want to learn WebGL?