Beryllium.ShapingFunctions 1.6.0

Prefix Reserved
dotnet add package Beryllium.ShapingFunctions --version 1.6.0
                    
NuGet\Install-Package Beryllium.ShapingFunctions -Version 1.6.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Beryllium.ShapingFunctions" Version="1.6.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Beryllium.ShapingFunctions" Version="1.6.0" />
                    
Directory.Packages.props
<PackageReference Include="Beryllium.ShapingFunctions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Beryllium.ShapingFunctions --version 1.6.0
                    
#r "nuget: Beryllium.ShapingFunctions, 1.6.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Beryllium.ShapingFunctions@1.6.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Beryllium.ShapingFunctions&version=1.6.0
                    
Install as a Cake Addin
#tool nuget:?package=Beryllium.ShapingFunctions&version=1.6.0
                    
Install as a Cake Tool

BerylliumShapingFunctions

A collection of 44 shaping (easing) functions for .NET — the curves used to drive animation, interpolation, and signal shaping. Every function maps an input to an output; inputs are clamped to the [0, 1] range before evaluation. Every curve starts at exactly 0 and ends at exactly 1, whatever its parameters, so an animation always lands on its end values; in between, most functions stay within [0, 1] (a few, such as Back and Elastic, intentionally overshoot).

Install

dotnet add package BerylliumShapingFunctions

Quick start

using Beryllium.ShapingFunctions;

// Create a function by its identifier.
BaseShapingFunction ease = ShapingFunctionFactory.Create(ShapingFunctionId.CubicEaseInOut);

float y = ease.CalculateOutput(0.25f);   // -> shaped value

// Sample a whole curve.
for (int i = 0; i <= 10; i++)
{
    float x = i / 10f;
    Console.WriteLine($"{x:0.0} -> {ease.CalculateOutput(x):0.000}");
}

CalculateOutput is a pure function of its input: calling it repeatedly with the same input (and the same parameters) always returns the same value and never mutates the object.

Parametric functions

Some functions expose tunable parameters through interfaces. Set the parameters, then call CalculateOutput. Parameter values are clamped to their valid range internally (the integer order N to at least 1, its default); assigning NaN throws ArgumentOutOfRangeException.

Parameters range over [0, 1], with one exception: outside the two Béziers the curve divides by A, so A is kept within [0.00001, 0.99999]. Parameters start at the bottom of their range, which makes both Béziers straight lines until they are configured.

var bezier = ShapingFunctionFactory.Create(ShapingFunctionId.BezierCubic);

if (bezier is IFourParameters p)   // BezierCubic takes A, B, C, D (control points)
{
    p.A = 0.25f;
    p.B = 0.10f;
    p.C = 0.25f;
    p.D = 1.00f;
}

float y = bezier.CalculateOutput(0.5f);

Parameter interfaces are hierarchical — ITwoParameters : IOneParameter, and so on:

Interface Adds parameter
IOneParameter A
ITwoParameters B
IThreeParameters C
IFourParameters D
INOrder N (integer order)

You can discover a function's shape at runtime without knowing its concrete type:

var fn = ShapingFunctionFactory.Create(id);

ShapingFunctionId       fnId       = fn.Id;               // the id it was created from
ShapingFunctionCategory category   = fn.Category;         // the category the catalog lists it under
bool                    parametric = fn.Parametric;       // true if it has any tunable parameters (A–D or N)
int                     paramCount = fn.ParameterCount;   // 0..4 (how many of A, B, C, D it uses)
bool                    hasOrder   = fn.HasVariableOrder; // true if it implements INOrder (settable N)
int?                    order      = fn.Order;            // fixed polynomial degree, when applicable
string                  name       = fn.Name;             // human-readable name

Browsing the catalog

Functions are grouped into categories. Use ShapingFunctionCatalog to enumerate them — handy for building a picker UI:

foreach (ShapingFunctionCategory category in ShapingFunctionCatalog.GetCategories())
{
    Console.WriteLine(category);
    foreach (ShapingFunctionId id in ShapingFunctionCatalog.GetFunctions(category))
        Console.WriteLine($"    {id}");
}

ShapingFunctionFactory.Create and ShapingFunctionCatalog.GetFunctions throw ArgumentOutOfRangeException for Custom (see Custom functions) and for values that are not defined.

Categories and functions are always returned in the same stable, curated order, and the ShapingFunctionId / ShapingFunctionCategory enum values are explicit and never renumbered — they are safe to persist in settings or save files.

Available functions

Category Functions
Back BackEaseIn, BackEaseInOut, BackEaseOut
Bezier BezierCubic (4 params), BezierQuadratic (2 params)
Bounce BounceEaseIn, BounceEaseInOut, BounceEaseOut
Circular CircularDoubleSeat (1), CircularDoubleSigmoid (1), CircularEaseIn, CircularEaseInOut, CircularEaseOut
Elastic ElasticEaseIn, ElasticEaseInOut, ElasticEaseOut
Elliptical EllipticalDoubleSeat (2), EllipticalDoubleSigmoid (2)
Exponential ExponentialDoubleSeat (1), ExponentialEaseIn, ExponentialEaseInOut, ExponentialEaseOut, LogisticSigmoid (1)
Linear Linear
Quadratic QuadraticEaseIn, QuadraticEaseInOut, QuadraticEaseOut, QuadraticThroughAGivenPoint (2)
Cubic CubicDoubleSeat (2), CubicEaseIn, CubicEaseInOut, CubicEaseOut
Quartic QuarticEaseIn, QuarticEaseInOut, QuarticEaseOut
Quintic QuinticEaseIn, QuinticEaseInOut, QuinticEaseOut
Hexic BlinnWyvillCosineApproximation
NOrder DoubleOddPolynomialSeat (2 params + N), DoublePolynomialSigmoid (N)
Sine SineEaseIn, SineEaseInOut, SineEaseOut

Custom functions

Derive from BaseShapingFunction, pass a name (and, optionally, a fixed polynomial degree) to its constructor, and implement CalculateCore, which receives the input already clamped to [0, 1]:

public sealed class SmoothStep : BaseShapingFunction
{
    public SmoothStep()
        : base("Smooth Step", 3)
    {
    }

    protected override float CalculateCore(float input)
    {
        return input * input * (3.0f - 2.0f * input);
    }
}

A custom function's Id and Category are ShapingFunctionId.Custom and ShapingFunctionCategory.Custom; the other ids are reserved for the library's own functions, so each of them always names a function the factory can create. The factory and the catalog know only the library's own functions, so Custom cannot be passed to ShapingFunctionFactory.Create and never appears in the catalog; to save and restore a custom function, persist an identifier of your own.

To make a custom function tunable, implement the parameter interfaces — ParameterCount, Parametric, and HasVariableOrder follow from them — and clamp values in the setters with the protected ClampParameter helper, which also rejects NaN.

Building and testing

dotnet test ShapingFunctions.sln

The tests check every curve against a double-precision implementation of its published formula (easings.net, Golan Levin's shaping functions, the Bernstein form of the Béziers) and hold every function to the guarantees above — exact end points, range, monotonicity, parameter clamping — across its parameter space.

Changelog

1.6.0

  • Breaking: the BaseShapingFunction(id, category, name, order) constructor is now private protected, reserving the built-in ids for the library's own functions. Custom functions use the new BaseShapingFunction(name, order) constructor instead; their Id and Category are the new ShapingFunctionId.Custom and ShapingFunctionCategory.Custom members (both -1).
  • Code that lists functions with Enum.GetValues now also sees Custom, which the factory rejects; the catalog lists only creatable functions.
  • Every function now returns exactly 0 at input 0 and exactly 1 at input 1, for any parameters. BezierCubic and EllipticalDoubleSigmoid could miss 1 by an ULP or two.
  • BezierQuadratic computes its discriminant without cancellation: for A close to 1 the end of the curve was off by up to 2e-4 (as high as 1.0002).
  • QuadraticThroughAGivenPoint is evaluated without cancellation: for A close to 0 or 1 it ended up to 6e-5 below 1 and could dip just before the end.

1.5.5

  • Every function exposes its Id and Category, and the BaseShapingFunction constructor takes them: (id, category, name, order).

1.5.0

A breaking release for code written against 1.2 or earlier:

  • The assembly is now Beryllium.ShapingFunctions.dll (was ShapingFunctions.dll); the package id, namespace, and public type names are unchanged.
  • CalculateOutput is no longer virtual — it clamps the input to [0, 1] and delegates to the new protected abstract float CalculateCore(float input). Custom functions override CalculateCore and pass their name/order to the BaseShapingFunction constructor.
  • The intermediate base classes (LinearBase … HexicBase, NOrderBase, TranscendentalBase, and the Parametric* tree) were removed; derive from BaseShapingFunction directly. Name, Order, and Parametric are now read-only.
  • N defaults to 1 and is clamped to at least 1; assigning NaN to any parameter throws ArgumentOutOfRangeException instead of being stored.
  • Several curves return slightly different (more accurate) values: BezierCubic uses a robust solver (no more NaN or start-of-curve error), BezierQuadratic is exact near A = 0.5, and LogisticSigmoid is computed in double precision.

License

MIT — see LICENSE.txt.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Beryllium.ShapingFunctions:

Package Downloads
Beryllium.Audio

Beryllium engine audio manager

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.6.0 104 9/26/2026