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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vshaders/ease

v0.2.0

Published

Easing curves and motion-shaping functions as pure WGSL modules for vgpu shaders

Downloads

257

Readme

@vshaders/ease

Easing curves and motion-shaping functions as pure WGSL modules for vgpu shaders:

import { easeOutElastic } from "@vshaders/ease/easing";
import { linearToSrgb3 } from "@vgpu/wgsl-std/color";

struct Uniforms { resolution: vec2f, time: f32 }
@group(0) @binding(0) var<uniform> uniforms: Uniforms;

@fragment fn main(@builtin(position) position: vec4f) -> @location(0) vec4f {
  let uv = position.xy / uniforms.resolution - vec2f(0.5);
  let pop = easeOutElastic(clamp(fract(uniforms.time * 0.5) * 2.0, 0.0, 1.0));
  let radius = 0.35 * pop;                              // ring pops in, wobbles, settles
  let ring = 1.0 - smoothstep(0.0, 0.02, abs(length(uv) - radius));
  return vec4f(linearToSrgb3(vec3f(ring)), 1.0);
}

Every module is pure WGSL — functions and constants only, no bindings, no entry points — so vgpu's resolver can prune whatever you don't import. Easing curves remap animation progress: feed them a t that advances linearly and get back a t that accelerates, overshoots, rings, or bounces.

@vshaders/ease/easing

The standard easing set as popularized by Robert Penner: ten curve families, each in three variants. All 30 functions share the signature (t: f32) -> f32 and map progress to eased progress with f(0) = 0 and f(1) = 1:

| Family | In | Out | InOut | | --- | --- | --- | --- | | quad | easeInQuad | easeOutQuad | easeInOutQuad | | cubic | easeInCubic | easeOutCubic | easeInOutCubic | | quart | easeInQuart | easeOutQuart | easeInOutQuart | | quint | easeInQuint | easeOutQuint | easeInOutQuint | | sine | easeInSine | easeOutSine | easeInOutSine | | expo | easeInExpo | easeOutExpo | easeInOutExpo | | circ | easeInCirc | easeOutCirc | easeInOutCirc | | back | easeInBack | easeOutBack | easeInOutBack | | elastic | easeInElastic | easeOutElastic | easeInOutElastic | | bounce | easeInBounce | easeOutBounce | easeInOutBounce |

  • t is expected in [0, 1] and is NOT clamped. Out-of-range inputs extrapolate the curve — clamp first (clamp01 from @vgpu/wgsl-std/math) if your driver can leave the range. Outputs are not clamped either: back, elastic, and the InOut bounce midpoints intentionally leave [0, 1] (back overshoots ~10%, elastic rings up to ~±37%).
  • Endpoints are exact. expo and elastic guard their exponential edge cases, so easeInExpo(0) == 0, easeOutExpo(1) == 1, easeInElastic(0) == 0, easeOutElastic(1) == 1 (and the InOut variants at both ends) hold precisely rather than to within 2^-10.
  • No NaNs from the domain edges. circ keeps its square roots real for out-of-range t, and polynomial powers are written as products rather than pow() (which WGSL leaves undefined for negative bases).
  • The back and elastic shape constants are named consts in the module (backOvershoot = 1.70158, elasticFrequency = tau / 3, …) with comments deriving them.

@vshaders/ease/shape

Motion-shaping helpers that don't fit the fixed-endpoint easing mold:

  • smootherstep(edge0: f32, edge1: f32, value: f32) -> f32 — Ken Perlin's quintic step 6t⁵ − 15t⁴ + 10t³: like smoothstep but with zero second derivative at both edges, so chained motion has no curvature kink. value is clamped to the edge interval; reversed edges (edge0 > edge1) fall from 1 to 0; a zero-width edge (edge0 == edge1) degrades to a hard step instead of dividing by zero.
  • almostIdentity(value: f32, threshold: f32, floorValue: f32) -> f32 — the identity for value >= threshold; below the threshold, the unique cubic that starts flat at floorValue and joins the identity at threshold with matching value and slope. Use it to keep a length or radius from reaching zero without a visible seam. value is expected >= 0 and floorValue <= threshold; a non-positive threshold returns the input unchanged.
  • springResponse(t: f32, damping: f32, frequency: f32) -> f32 — the unit-step response of a second-order system: starts at 0 with zero velocity and settles to 1. t is elapsed time (expected >= 0, not normalized — the curve settles asymptotically); frequency is the undamped natural frequency in radians per unit of t (expected > 0); damping is the damping ratio: 0 oscillates forever, values below 1 overshoot and ring, 1 is the no-overshoot limit. Negative damping is clamped to 0, and damping >= 1 degrades to the critically-damped response (the exact ζ = 1 curve) rather than the slower overdamped form.
import { springResponse } from "@vshaders/ease/shape";

// Inside a fragment shader with the usual Uniforms { resolution, time }:
// a bar that springs to a new width every second — overshoots, rings, settles.
let sinceHop = fract(uniforms.time);
let goal = select(0.25, 0.75, fract(uniforms.time / 2.0) < 0.5); // alternates each second
let width = mix(1.0 - goal, goal, springResponse(sinceHop, 0.35, 18.0));
let bar = step(position.x / uniforms.resolution.x, width);

Provenance

The easing curve formulas are the standard set popularized by Robert Penner ("Motion, Tweening, and Easing", Programming Macromedia Flash MX, 2001; the equations are BSD-licensed and the closed forms are elementary math). smootherstep is Ken Perlin's quintic interpolant ("Improving Noise", SIGGRAPH 2002). almostIdentity is derived here as the unique cubic satisfying four Hermite boundary constraints, a construction popularized by Inigo Quilez. springResponse is the textbook step response of an underdamped second-order system from control theory. All WGSL in this package is an original implementation, with edge-case guards (exponential endpoints, zero-width edges, non-positive thresholds, damping >= 1) in the argument ranges the math leaves undefined.

Verifying

npx vgpu check path/to/your-entry-shader.wgsl

resolves the import graph, validates the composed shader, and prints its reflection.

License

MIT