npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

autumn-wgl

v1.4.1

Published

High(-er)-level WebGL components

Downloads

14

Readme

autumn-wgl

High(-er)-level WebGL components.

Using WebGL requires calling a lot of low-level functions with hard-to-remember names multiple times. So I made a library that's hopefully easier to keep straight. This ought to work with both WebGL 1 and 2.

Installation

npm i autumn-wgl

Basic Usage

In WebGL rendering, there are usually two phases: a "setup" phase, where where you compile your shader program and put all the required data onto video RAM, and a "render" phase, which actually does the drawing.

Setup phase

// Compile a shader program
const program = new WGLProgram(
  gl,            // WebGL rendering context
  vertex_src,    // vertex shader source code
  fragment_src,  // fragment shader source code
);

// Create a vertex buffer object (VBO)
const buffer = new WGLBuffer(
  gl,            // WebGL1 rendering context
  vertex_data,   // The vertex data as a Float32Array
  n_coords,      // The number of coordinates per vertex
  draw_mode      // e.g., gl.TRIANGLE_STRIP
);

// Set up texture data
const tex_coords = new WGLBuffer(gl, texcoord_data, n_coords, draw_mode);

const image_data = {
  format: data_format,               // e.g., gl.RGBA for an RGBA image
  type: data_type,                   // e.g., gl.UNSIGNED_BYTE for unsigned byte image data        
  image: image,                      // Image data as a typed array with the type corresponding to `data_type`
  width: image_width,                // Texture width in pixels
  height: image_height,              // Texture height in pixels
  mag_filter: magnification_filter   // e.g., gl.LINEAR
};

const texture = new WGLTexture(gl, image_data);

If you have a texture image rendered into a canvas element, you can create image_data like this

const image_data = {
  format: gl.RGBA,
  type: gl.UNSIGNED_BYTE,     
  image: canvas_element,             // HTML canvas element containing the image data
  mag_filter: magnification_filter   // e.g., gl.LINEAR
};

Additionally, for WebGL2, supply the internal format (e.g., gl.RGBA8) in format, and the correct format will be computed internally.

Render phase

// Use an already-compiled program object
program.use();

// Bind attributes to VBOs
program.bindAttributes({
  'a_attribute': buffer,     // The `a_attribute` variable in the shader program gets bound to the `buffer` VBO
  'a_texcoord': tex_coords,  // The `a_texcoord` variable in the shader program gets bound to the `tex_coords` VBO
});

// Set values for uniforms
program.setUniforms({
  'u_uniform': 42,          // The `u_uniform` variable (declared as a float) in the shader program gets set to 42
  'u_color': [0., 0., 0.],  // The `u_color` variable (declared as a vec3) in the shader program gets set to [0., 0., 0.]
});

// Bind samplers in the shader program to texture objects
program.bindTextures({
  'u_texture_sampler': texture,  // The `u_texture_sampler` variable (declared as a sampler2D) gets data from the object `texture`.
});

// Do the above four calls in one step
program.use(
  {'a_attribute': buffer, 'a_texcoord': tex_coords},
  {'u_uniform': 42, 'u_color': [0., 0., 0.]},
  {'u_texture_sampler': texture}
);

// Set the screen buffer as the render target (specifying what region with `lower_left_x`, `lower_left_y`, `width`, and `height`);
WGLFramebuffer.screen(gl).renderTo(lower_left_x, lower_left_y, width, height);

// Clear the screen buffer to black
WGLFramebuffer.screen(gl).clear([0., 0., 0., 1.]);

// Do the actual drawing
program.draw();

You might want to use WebGL's indexed vertices. This has some advantages when you have some duplicate vertices, as the duplicates don't need to be passed to VRAM, and the vertex shader doesn't need to be run on the duplicates. To do this:

// [In the setup phase] Create the index buffer object
const index_array = new Uint16Array([0, 1, 2, /* ... */, 0, 1, 2, /* ... */]);
const index_buffer = new WGLIndexBuffer(gl, index_array, gl.TRIANGLE_STRIP);

// [In the render phase] Add the index_buffer to the program.use() call.
program.use(
  {'a_attribute': buffer, 'a_texcoord': tex_coords},
  {'u_uniform': 42, 'u_color': [0., 0., 0.]},
  {'u_texture_sampler': texture},
  index_buffer
);

Advanced Usage

The WGLFramebuffer class represents a framebuffer for offscreen rendering. (As one might be able to guess, the screen buffer is also a WGLFramebuffer, so they share a lot of the same functions.)

// [In the setup phase] Create a framebuffer object
const fbo_image_data = {
  format: data_format,  // e.g., gl.RGBA for an RGBA image
  type: data_type,      // e.g., gl.UNSIGNED_BYTE for unsigned byte image data        
  image: null,          // null to declare space in video RAM, but not fill it with anything
  width: fbo_width,     // Framebuffer width in pixels
  height: fbo_height,   // Framebuffer height in pixels
};

const fbo_texture = new WGLTexture(gl, fbo_image_data);
const fbo = new WGLFramebuffer(gl, fbo_texture);

// [In the render phase] Set the frame buffer as the render target and clear to transparent
fbo.renderTo(0, 0, fbo_width, fbo_height);
fbo.clear([0., 0., 0., 0.]);

In some advanced rendering, you may want to run the same program several times, rendering to offscreen buffers on each pass. A common technique is to alternate between two framebuffers. Use the flipFlopBuffers() function to make this easier.

const doRender = (src, dest, ipass) => {
  // Do whatever rendering in this function. `src` is the source framebuffer for this pass, `dest` is the destination
  //  framebuffer for this pass, and `ipass` is the pass number (e.g., 0 for the 1st pass, 1 for the second pass, etc.)
};

flipFlopBuffers(
  n_passes,     // The number of render passes to do
  source_fb,    // The source framebuffer (set this to the second of your auxiliary framebuffer objects if the initial data aren't from a framebuffer)
  auxilary_fb,  // A length-2 tuple of framebuffer objects to alternate between on each rendering pass
  doRender      // Your function that does the rendering on each pass
);