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

@smoovy/webgl

v1.2.9

Published

Easier WebGL animations for websites

Downloads

389

Readme

@smoovy/webgl

Version Size

Small and flexible WebGL library with only the absolute basics: Camera, Mesh (incl. Plane), Shaders, Textures, Uniforms.

Installation

yarn add @smoovy/webgl

or

npm install --save @smoovy/webgl

Usage

Import the WebGL class as usual:

import { WebGL } from '@smoovy/webgl';

Create a context

const webgl = new WebGL();

Meshes

This adds a plane in the center of the screen and manipulates it

const plane = webgl.plane({
  x: 0,
  y: 0,
  width: 1,
  height: 1,
  originX: 0.5,
  originY: 0.5,
  density: 10
});

// move plane
plane.x = 2;
plane.y = 2;
plane.z = 5;

// resize plane
plane.width = .5;
plane.height = .5;

// change origin
plane.originX = 0;
plane.originY = 0;

Camera

A default perspective camera will be created automatically. You can access it via wegbl.renderer.camera. You can create mutliple cameras like this:

const camera1 = webgl.camera({ fov: 30});
const camera2 = webgl.camera({ fov: 30, near: .5, far: 50 });

Assign a camera to a mesh

Meshes will fallback to the default camera. You can overwrite it with the camera option:

webgl.plane({ ..., camera: camera1 });
webgl.plane({ ..., camera: camera2 });

Uniforms

Uniforms are availbale on all meshes through the uniforms property.

const plane = webgl.plane({
  ...,
  uniforms: {
    u_color: [ 0, 1, 0, 1 ] // make it red
  }
});

// change color to red
plane.uniforms.u_color[0] = 1;
plane.uniforms.u_color[1] = 0;

Uniform type detection

Types are mostly autodetected, but can be forced in cases of ambiguity (e.g. mat2 and vec4)

const plane = webgl.plane({
  ...,
  uniforms: {
    // automatically converted to vec4
    // not defined in uniformTypes
    u_mat2: [0, 1, 2, 3]
  },
  uniformTypes: {
    // force mat2 type on `u_mat2` uniform
    u_mat2: 'm2'
  }
});

Optional uniforms

If WebGL can't find a uniform you'll get a warning in the console. To prevent this you can mark the uniform as optional and prevent warnings/errors.

const plane = webgl.plane({
  ...,
  uniformOptionals: {
    // ignore warning and errros
    // if not defined in mesh
    u_color: true
  }
});

Shaders

If no shaders are defined it will fall back to the default shader. You can override the default shader like this:

const plane = webgl.plane({
  ...,
  vertex: `#version 300 es
    in vec4 a_position;
    uniform mat4 u_proj;
    uniform mat4 u_view;
    uniform mat4 u_model;

    void main() {
      gl_Position = u_proj * u_view * u_model * a_position;
    }`,
  fragment: `#version 300 es
    precision mediump float;

    out vec4 fragColor;
    uniform vec4 u_color;

    void main() {
      fragColor = u_color;
    }`
});

Textures

Image and video textures are supported out-of-the-box. and can be created like this:

webgl.image({ src: '/path/to/image.jpg' });
webgl.video({ src: '/path/to/video.mp4' });

// extended configuration
webgl.image({
  unpackFlip: false,
  minFilter: webgl.ctx.LINEAR,
  wrapS: webgl.ctx.CLAMP_TO_EDGE,
  wrapT: webgl.ctx.CLAMP_TO_EDGE,
})

Attach to meshes

You can just pass the texture to the mesh via texture:

const plane = webgl.plane({
  ...,
  textures: webgl.image({ src: '/path/to/image.jpg' })
});

This will be named to u_texture in the fragment shader.

You can attach multiple textures to one mesh like this:

const plane = webgl.plane({
  ...,
  textures: {
    base: webgl.image({ src: '/path/to/image.jpg' }),
    depth: webgl.image({ src: '/path/to/depth.png' })
  }
});

All textures will be prefixed with u_texture_. So base will be u_texture_base for example.

Preloading image textures

Preloading textures can be done by either creating the texture, which will immediately load it or preload the image first like this:

import { TextureMediaLoader } from '@smoovy/webgl';

TextureMediaLoader.load('/path/to/image.jpg');

This will load the image into the media cache and used when a texture requests it.

Screen Coordinate Mapping

Usually coordinates (x,y) and sizes of meshes are provided in clips space coordinates. You can use screen on meshes to map screen coordinats (px) to clip space coordinates automatically.

const plane = webgl.plane({
  x: 500,
  y: 500,
  width: 100,
  height: 100,

  // this will convert x, y, width and height to
  // clip space before passing them to the shader
  // program. It'll render a 100x100px square at
  // the position (500, 500).
  screen: true
});

// all following transformations will be
// converted as well automatically
plane.x = 100;
plane.y = 100;
plane.width = 300;
plane.height = 300;

Important: The z-coordinate will not be converted to px values and will always be in clip space

Manually convert values

Converting the coordinates happens through the camera. With these methods you can convert px to clip space coordinates and sizes

camera.ch(100) // -> 100px height to clip space
camera.cw(100) // -> 100px width to clip space
camera.cx(100) // -> 100px on the x-axis
camera.cy(100) // -> 100px on the y-axis

Scrolling

With this method you can basically apply "scrolling" by moving the camera with this conversion like this:

window.onscroll = () => {
  camera.x = camera.cw(window.scrollX);
  camera.y = camera.ch(window.scrollY);
};

License

See the LICENSE file for license rights and limitations (MIT).