• Stars
    star
    2,451
  • Rank 18,666 (Top 0.4 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 9 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Tiny WebGL helper Library

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

<canvas id="c"></canvas>
<script src="../dist/5.x/twgl-full.min.js"></script>
<script>
  const gl = document.getElementById("c").getContext("webgl");
  const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

  const arrays = {
    position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
  };
  const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

  function render(time) {
    twgl.resizeCanvasToDisplaySize(gl.canvas);
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

    const uniforms = {
      time: time * 0.001,
      resolution: [gl.canvas.width, gl.canvas.height],
    };

    gl.useProgram(programInfo.program);
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
    twgl.setUniforms(programInfo, uniforms);
    twgl.drawBufferInfo(gl, bufferInfo);

    requestAnimationFrame(render);
  }
  requestAnimationFrame(render);
</script>

And here it is live.

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

const programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

WebGL

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

const u_lightWorldPosLoc = gl.getUniformLocation(program, "u_lightWorldPos");
const u_lightColorLoc = gl.getUniformLocation(program, "u_lightColor");
const u_ambientLoc = gl.getUniformLocation(program, "u_ambient");
const u_specularLoc = gl.getUniformLocation(program, "u_specular");
const u_shininessLoc = gl.getUniformLocation(program, "u_shininess");
const u_specularFactorLoc = gl.getUniformLocation(program, "u_specularFactor");
const u_diffuseLoc = gl.getUniformLocation(program, "u_diffuse");
const u_worldLoc = gl.getUniformLocation(program, "u_world");
const u_worldInverseTransposeLoc = gl.getUniformLocation(program, "u_worldInverseTranspose");
const u_worldViewProjectionLoc = gl.getUniformLocation(program, "u_worldViewProjection");
const u_viewInverseLoc = gl.getUniformLocation(program, "u_viewInverse");

const positionLoc = gl.getAttribLocation(program, "a_position");
const normalLoc = gl.getAttribLocation(program, "a_normal");
const texcoordLoc = gl.getAttribLocation(program, "a_texcoord");

Creating Buffers for a Cube

TWGL

const arrays = {
  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],
  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],
  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],
  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],
};
const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

WebGL

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];
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];
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];
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];

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
const normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);
const texcoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texcoords), gl.STATIC_DRAW);
const indicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

Setting Attributes and Indices for a Cube

TWGL

twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);

WebGL

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texcoordLoc);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);

Setting Uniforms for a Lit Cube

TWGL

// At Init time
const uniforms = {
  u_lightWorldPos: [1, 8, -10],
  u_lightColor: [1, 0.8, 0.8, 1],
  u_ambient: [0, 0, 0, 1],
  u_specular: [1, 1, 1, 1],
  u_shininess: 50,
  u_specularFactor: 1,
  u_diffuse: tex,
};

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

twgl.setUniforms(programInfo, uniforms);

WebGL

// At Init time
const u_lightWorldPos = [1, 8, -10];
const u_lightColor = [1, 0.8, 0.8, 1];
const u_ambient = [0, 0, 0, 1];
const u_specular = [1, 1, 1, 1];
const u_shininess = 50;
const u_specularFactor = 1;
const u_diffuse = 0;

// At render time
gl.uniform3fv(u_lightWorldPosLoc, u_lightWorldPos);
gl.uniform4fv(u_lightColorLoc, u_lightColor);
gl.uniform4fv(u_ambientLoc, u_ambient);
gl.uniform4fv(u_specularLoc, u_specular);
gl.uniform1f(u_shininessLoc, u_shininess);
gl.uniform1f(u_specularFactorLoc, u_specularFactor);
gl.uniform1i(u_diffuseLoc, u_diffuse);
gl.uniformMatrix4fv(u_viewInverseLoc, false, camera);
gl.uniformMatrix4fv(u_worldLoc, false, world);
gl.uniformMatrix4fv(u_worldInverseTransposeLoc, false, m4.transpose(m4.inverse(world)));
gl.uniformMatrix4fv(u_worldViewProjectionLoc, false, m4.multiply(viewProjection, world));

Loading / Setting up textures

TWGL

const textures = twgl.createTextures(gl, {
  // a power of 2 image
  hftIcon: { src: "images/hft-icon-16.png", mag: gl.NEAREST },
  // a non-power of 2 image
  clover: { src: "images/clover.jpg" },
  // From a canvas
  fromCanvas: { src: ctx.canvas },
  // A cubemap from 6 images
  yokohama: {
    target: gl.TEXTURE_CUBE_MAP,
    src: [
      'images/yokohama/posx.jpg',
      'images/yokohama/negx.jpg',
      'images/yokohama/posy.jpg',
      'images/yokohama/negy.jpg',
      'images/yokohama/posz.jpg',
      'images/yokohama/negz.jpg',
    ],
  },
  // A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)
  goldengate: {
    target: gl.TEXTURE_CUBE_MAP,
    src: 'images/goldengate.jpg',
  },
  // A 2x2 pixel texture from a JavaScript array
  checker: {
    mag: gl.NEAREST,
    min: gl.LINEAR,
    src: [
      255,255,255,255,
      192,192,192,255,
      192,192,192,255,
      255,255,255,255,
    ],
  },
  // a 1x8 pixel texture from a typed array.
  stripe: {
    mag: gl.NEAREST,
    min: gl.LINEAR,
    format: gl.LUMINANCE,
    src: new Uint8Array([
      255,
      128,
      255,
      128,
      255,
      128,
      255,
      128,
    ]),
    width: 1,
  },
});

WebGL

// Let's assume I already loaded all the images

// a power of 2 image
const hftIconTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, hftIconImg);
gl.generateMipmaps(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
// a non-power of 2 image
const cloverTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, hftIconImg);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
// From a canvas
const cloverTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
gl.generateMipmaps(gl.TEXTURE_2D);
// A cubemap from 6 images
const yokohamaTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, posXImg);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, negXImg);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, posYImg);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, negYImg);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, posZImg);
gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, negZImg);
gl.generateMipmaps(gl.TEXTURE_CUBE_MAP);
// A cubemap from 1 image (can be 1x6, 2x3, 3x2, 6x1)
const goldengateTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex);
const size = goldengate.width / 3;  // assume it's a 3x2 texture
const slices = [0, 0, 1, 0, 2, 0, 0, 1, 1, 1, 2, 1];
const tempCtx = document.createElement("canvas").getContext("2d");
tempCtx.canvas.width = size;
tempCtx.canvas.height = size;
for (let ii = 0; ii < 6; ++ii) {
  const xOffset = slices[ii * 2 + 0] * size;
  const yOffset = slices[ii * 2 + 1] * size;
  tempCtx.drawImage(element, xOffset, yOffset, size, size, 0, 0, size, size);
  gl.texImage2D(faces[ii], 0, format, format, type, tempCtx.canvas);
}
gl.generateMipmaps(gl.TEXTURE_CUBE_MAP);
// A 2x2 pixel texture from a JavaScript array
const checkerTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
    255,255,255,255,
    192,192,192,255,
    192,192,192,255,
    255,255,255,255,
  ]));
gl.generateMipmaps(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
// a 1x8 pixel texture from a typed array.
const stripeTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 1, 8, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, new Uint8Array([
    255,
    128,
    255,
    128,
    255,
    128,
    255,
    128,
  ]));
gl.generateMipmaps(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

Creating Framebuffers and attachments

TWGL

const attachments = [
  { format: RGBA, type: UNSIGNED_BYTE, min: LINEAR, wrap: CLAMP_TO_EDGE },
  { format: DEPTH_STENCIL, },
];
const fbi = twgl.createFramebufferInfo(gl, attachments);

WebGL

const fb = gl.createFramebuffer(gl.FRAMEBUFFER);
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.drawingBufferWidth, gl.drawingBufferHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
const rb = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb);

Setting uniform and uniformblock structures and arrays

Given an array of GLSL structures like this

struct Light {
  float intensity;
  float shininess;
  vec4 color;
}
uniform Light lights[2];

TWGL

const progInfo = twgl.createProgramInfo(gl, [vs, fs]);
...
twgl.setUniforms(progInfo, {
  lights: [
    { intensity: 5.0, shininess: 100, color: [1, 0, 0, 1] },
    { intensity: 2.0, shininess:  50, color: [0, 0, 1, 1] },
  ],
});

WebGL

// assuming we already compiled and linked the program
const light0IntensityLoc = gl.getUniformLocation('lights[0].intensity');
const light0ShininessLoc = gl.getUniformLocation('lights[0].shininess');
const light0ColorLoc = gl.getUniformLocation('lights[0].color');
const light1IntensityLoc = gl.getUniformLocation('lights[1].intensity');
const light1ShininessLoc = gl.getUniformLocation('lights[1].shininess');
const light1ColorLoc = gl.getUniformLocation('lights[1].color');
...
gl.uniform1f(light0IntensityLoc, 5.0);
gl.uniform1f(light0ShininessLoc, 100);
gl.uniform4fv(light0ColorLoc, [1, 0, 0, 1]);
gl.uniform1f(light1IntensityLoc, 2.0);
gl.uniform1f(light1ShininessLoc, 50);
gl.uniform4fv(light1ColorLoc, [0, 0, 1, 1]);

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

const progInfo = twgl.createProgramInfo(gl, [vs, fs]);
...
twgl.setUniforms(progInfo, {
  'lights[1]': { intensity: 5.0, shininess: 100, color: [1, 0, 0, 1] },
});

Compare

TWGL example vs WebGL example

Examples

WebGL 2 Examples

OffscreenCanvas Example

ES6 module support

AMD support

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

    http://github.com/greggman/twgl.js

  • from bower

    bower install twgl.js
  • from npm

    npm install twgl.js

    or

    npm install twgl-base.js
  • from git

    git clone https://github.com/greggman/twgl.js.git

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

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
gl.vertexAttribPointer(texcoordLoc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texcoordLoc);
gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
gl.vertexAttribPointer(colorLoc, 4, gl.UNSIGNED_BYTE, true, 0, 0);
gl.enableVertexAttribArray(colorLoc);

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

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

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

API Docs are here.

Want to learn WebGL?

Try webglfundamentals.org

More Repositories

1

better-unity-webgl-template

A better default template for Unity WebGL
HTML
630
star
2

HappyFunTimes

A System for creating 10-100+ player local games
JavaScript
371
star
3

html5bytebeat

Bytebeats in HTML5
JavaScript
369
star
4

webgl-memory

A library to track webgl-memory
JavaScript
306
star
5

tdl

A low-level WebGL library
JavaScript
280
star
6

ffmpegserver.js

Receives canvas frames from browser to generate video on the server. Compatible with CCapture.js
JavaScript
267
star
7

servez

A simple web server for local web development.
JavaScript
258
star
8

hsva-unity

A Hue Saturation Value adjustment shader for Unity. Useful for making lots of character colors.
GLSL
202
star
9

webgl-lint

Checks your WebGL usage for common issues
JavaScript
160
star
10

wgpu-matrix

Fast WebGPU 3d math library
JavaScript
129
star
11

virtual-webgl

Virtualize WebGL Contexts
JavaScript
105
star
12

unzipit

Random access unzip library for JavaScript
JavaScript
100
star
13

unity-webgl-copy-and-paste

Support Copy and Paste in Unity WebGL
C#
90
star
14

doodles

Random JavaScript doodles
JavaScript
58
star
15

getuserimage-unity-webgl

How to ask the user for a photo in Unity-WebGL
C#
55
star
16

webgl-helpers

some tiny webgl scripts that might come in handy
JavaScript
54
star
17

webgpu-memory

Track your WebGPU memory usage
JavaScript
43
star
18

servez-cli

The cli version of servez
JavaScript
38
star
19

ImHUI

Experimental UI
TypeScript
34
star
20

webgl-capture

code to help make a reduced test case for WebGL by capturing the commands and generating a stand alone program
JavaScript
34
star
21

oes-vertex-array-object-polyfill

WebGL OES_vertex_array_object polyfill for GPUs/Drivers/Browsers that don't have it
JavaScript
33
star
22

hft-unity3d

Unity3D Libraries for HappyFunTimes
C#
31
star
23

requestanimationframe-fix.js

Fix for requestAnimationFrame with lots of elements
JavaScript
31
star
24

webgpu-utils

Some helpers for webgpu
JavaScript
30
star
25

youtube_chromecast_speed_hack

A way to play a youtube video on Chromecast with settable speed
HTML
28
star
26

pico-8-post-processing

post process pico-8
JavaScript
28
star
27

hft-tonde-iko

A Multi-Machine Platformer
JavaScript
24
star
28

react-split-it

A React Based Splitter
JavaScript
24
star
29

pixel-perfect.js

Display Image Pixel Perfect
HTML
22
star
30

gradient-editor

A Jquery based gradient editor
JavaScript
20
star
31

jsgist

A code playground that stores data as github gists
JavaScript
16
star
32

interval-timer

A Simple Interval Timer
JavaScript
16
star
33

html5-gamepad-test

HTML
15
star
34

webgpu-avoid-redundant-state-setting

Check for and avoid redundant state setting
JavaScript
15
star
35

webgl-canvas-2d

A minimal implementation of the canvas 2D API through WebGL
JavaScript
14
star
36

rockfall

Rockfall. A game where rocks fall
JavaScript
14
star
37

jsbenchit

A JavaScript benchmark static page website that uses gists to store benchmarks
JavaScript
14
star
38

fanfictionreader

Reads your fanfiction to you.
JavaScript
13
star
39

happyfuntimes.net

The HappyFunTimes.net code
JavaScript
10
star
40

dekapng

Make giant PNG files in the browser
TypeScript
10
star
41

hft-gamepad-api

Emulates the HTML5 Gamepad API using smartphones and HappyFunTimes
JavaScript
10
star
42

hft-boomboom

A happyfuntimes game with splosions
JavaScript
9
star
43

DeJson.NET

A simple serialization library from JSON to C# classes based on MiniJSON good for Unity3D
C#
9
star
44

oculus-anti-spy

Try top stop Facebook from spying on all Oculus Activity
JavaScript
8
star
45

uzip-module

An ES6 module version of UZIP.js
JavaScript
8
star
46

imageutils

A few image utils for in browser JavaScript
JavaScript
7
star
47

hft-unity-gamepad

A Generic HappyFunTimes Gamepad for Unity
JavaScript
7
star
48

MoPho-V

A Community Supported Movie and Photo Viewer
JavaScript
6
star
49

sharks-with-frickin-lasers

JavaScript
6
star
50

hft-clean

The simplest happyfuntimes example, no other scripts
JavaScript
6
star
51

webgpu-helpers

Small scripts useful when debugging or developing webgpu
JavaScript
6
star
52

octopus

JavaScript
5
star
53

audiostreamsource.js

Provides a streamed audio source for WebAudio across browsers
JavaScript
5
star
54

dump-all-the-shaders

A script you can add to dump all your shaders to the console.
JavaScript
4
star
55

epub-viewer

A simple epub viewer. Client side only
HTML
4
star
56

image-grid

A simple image-grid for displaying images um, in a grid in the browser
JavaScript
4
star
57

simple-new-tab-page

A simple new tab page extension
JavaScript
4
star
58

other-window-ipc

IPC between windows in Electron
JavaScript
4
star
59

macos-opengl-experiments

Simple OpenGL stuff on MacOS
Objective-C++
3
star
60

rest-url

Makes REST urls
JavaScript
3
star
61

aws-oauth-helper

An AWS Lambda function to handle the oauth client secret part of oauth
JavaScript
3
star
62

unity-load-mp3-at-runtime

example of loading mp3 at runtime
C#
3
star
63

soundcloud-audio-reactive-example

Soundcloud audio reactive example using new API
JavaScript
3
star
64

hft-unityvideofromunity

An example of sending WebCam video FROM unity to the controller (phones)
C#
3
star
65

muigui

baking
JavaScript
3
star
66

hft-syncthreejs

Shows syncing a three.js example across multiple machines using HappyFunTimes
JavaScript
3
star
67

fixallthetags

SO script to fix tags
JavaScript
3
star
68

hft-local

Run a HappyFunTimes game without HappyFunTimes (no networking .. sometimes good for demos)
JavaScript
3
star
69

screenshot-ftw

screenshot a window across OSes
C++
3
star
70

webgl-benchmarks

WebGL Benchmarks (NOT GPU BENCHMARKS!!!)
JavaScript
3
star
71

opengl-fundamentals

JavaScript
3
star
72

stackoverflow-getallanswers

Get all answers for a particular user (and all the questions for those answers)
Python
3
star
73

hft-unitysimple

The simplest Unity example for HappyFunTimes using C#
C#
3
star
74

jsgistrunner

JavaScript
2
star
75

fisheye-skybox-unity

Make a fisheye skybox shader in unity
ShaderLab
2
star
76

cssparse.net

CSS string to Unity3D Color parser
C#
2
star
77

u2b-ux

better youtube ux
JavaScript
2
star
78

hft-unity-character-select

A HappyFunTimes Unity example showing spawning different prefabs based on player character selection
C#
2
star
79

native-msg-box

Allows you to display a native MessageBox / Dialog from node.js
JavaScript
2
star
80

hft-simple

A simple example for HappyFunTimes
JavaScript
2
star
81

hft-jumpjump

The HappyFunTimes JumpJump Example Platformer
JavaScript
2
star
82

servez-lib

The server part of servez
JavaScript
2
star
83

check-all-the-errors

load all your pages, check for javascript errors
JavaScript
2
star
84

hft-unity-2-button-gamejam

A Unity HappyFunTimes Template for the Pico Pico Cafe 2 Button Gamejam
C#
2
star
85

hft-simple-no-electron

an example of using happyfuntimes without electron
JavaScript
2
star
86

eslint-plugin-one-variable-per-var

Enforce one variable declaration per var statement
JavaScript
2
star
87

ldcp

low dependencies cp for node
JavaScript
2
star
88

LUT-to-PNG

Convert a LUT or CUBE file to a PNG (for Unreal / Unity)
JavaScript
2
star
89

hft-powpow

A simple space shooter game for HappyFunTimes
JavaScript
1
star
90

hft-utils

Various JavaScript files shared among HappyFunTimes example games
JavaScript
1
star
91

vertexshaderart.org

vertexshaderart.org
1
star
92

hft-sync2d

Example showing syncing canvas 2d across machines using HappyFunTimes
JavaScript
1
star
93

dns-server

Automatically exported from code.google.com/p/dns-server
C++
1
star
94

bloom

look at the source
JavaScript
1
star
95

hft-unity-cardboard

Example of using HappyFunTimes with Unity and Google Cardbard
C#
1
star
96

webgpu-dev-extension

Explorational WebGPU Dev Extension
JavaScript
1
star
97

font-utils

Some font utils I wrote to generate fonts for gamemaker
C
1
star
98

jsbenchit-comments

just a point to host jsbenchit comments on another domain for security
HTML
1
star
99

hft-c

HappyFunTimes support for C / C++ based games
C++
1
star
100

hft-exe

HappyFunTimes executable creator
C
1
star