Fri
19
Sep 2025
This is a guest post from my friend Łukasz Izdebski Ph.D.
It’s been a while since my last guest post on Adam’s blog, but I’m back with something short and practical—think of it as an epilogue to this earlier post on Bézier curves in animation. The last post focused on the theory and mathematics behind Bézier curves. What it lacked was a practical perspective—an opportunity to see the implementation in action. I wanted to share with you a simple library that I have created. Its purpose is to directly represent cubic Bézier Curves as Easing Functions.
The library is designed with C++20 and newer standards in mind, taking advantage of modern language features for clarity and performance. If needed, support for earlier versions of C++ can be added to ensure broader compatibility.
EasingCubicBezier<T>. This class handles the interpolation of parameters used in the keyframe method. The interpolation of parameters follows the same principles as standard Bézier curve evaluation.evaluate function with a parameter t, which should lie between x0 (the X coordinate of the first control point, representing the start time of the frame) and x3 (the X coordinate of the fourth control point, representing the end time). As presented in previous blog post, the EasingCubicBezier character as a easing function depends solely on the X coordinates of the control points.
The tests were prepared for a single, fixed value of the Y coordinates of the Bézier curve control points (their value does not affect the interpolation performance in any way), and for a set of 256 different variants of the X coordinates of the control points.
The aim was to cover as wide a range of control point locations as possible (in particular, the two inner points).
Performance measurements were carried out using the Google Benchmark framework, ensuring reliable and consistent results. Further details and test results are available in the library repository.
The new approach using EasingCubicBezier<T> has been benchmarked against two commonly used methods in game engines and graphics applications. Both of these alternatives rely on solving cubic polynomial equations, either through algebraic solutions or numerical techniques.
In the case of numerical methods, a critical factor is the choice of the initial starting point. This selection plays a major role in determining the algorithm’s convergence speed and stability.
The following tests compared 5 different algorithms:
0.5 (because the X coordinates of the curve were previously normalised to the interval [0, 1]).t, where t is the input parameter for which the Bézier curve interpolation is being evaluated.The chart and the table below presents the benchmark results using a box plot, highlighting the distribution and variability of each algorithm’s performance in PRECISE mode with AVX2 extensions turned On.
| Algorithm | Min | Q1 | Median | Q3 | Max | Average | Std dev |
|---|---|---|---|---|---|---|---|
| Easing Cubic Bezier | 1562.5 | 21875.0 | 32812.5 | 32812.5 | 39062.5 | 28991.7 | 7803.5 |
| Numeric Solution 1 | 7812.5 | 17187.5 | 23437.5 | 53515.6 | 150000.0 | 40856.9 | 32900.5 |
| Numeric Solution 2 | 4687.5 | 15625.0 | 21093.8 | 52343.8 | 173438.0 | 37292.5 | 31220.9 |
| Original Blender | 40625.0 | 54687.5 | 56250.0 | 56250.0 | 60937.5 | 55096.4 | 2659.2 |
| Optimised Blender | 12500.0 | 40625.0 | 42187.5 | 43750.0 | 45312.5 | 41003.4 | 5931.3 |
The chart and the table below presents the benchmark results using a box plot, highlighting the distribution and variability of each algorithm’s performance in FAST mode mode with AVX2 extensions turned On.
| Algorithm | Min | Q1 | Median | Q3 | Max | Average | Std dev |
|---|---|---|---|---|---|---|---|
| Easing Cubic Bezier | 3125.0 | 15625.0 | 21875.0 | 23437.5 | 23437.5 | 19714.4 | 4838.2 |
| Numeric Solution 1 | 7812.5 | 17187.5 | 23437.5 | 59375.0 | 331250.0 | 42059.3 | 37539.5 |
| Numeric Solution 2 | 4687.5 | 15625.0 | 20312.5 | 48437.5 | 156250.0 | 36926.3 | 31357.5 |
| Original Blender | 32812.5 | 44921.9 | 50000.0 | 50000.0 | 50000.0 | 47418.2 | 3817.4 |
| Optimised Blender | 12500.0 | 35937.5 | 42187.5 | 42187.5 | 43750.0 | 39953.6 | 5554.2 |
The table below summarizes the key conclusions drawn from the benchmark tests.
| Algorithm | Performance | Variation | Conclusions |
|---|---|---|---|
| Easing Cubic Bezier | Very stable and consistently low execution time | Minimal | Most predictable and effective in typical use cases |
| Numeric Solution 1 | Highly variable — ranging from excellent to extremely slow | Huge, with many outliers | Efficient in some cases, but unstable and prone to severe slowdowns |
| Numeric Solution 2 | Similar to Numeric Solution 1, but with more symmetrical behavior | Large, but less extreme | More balanced overall, though still susceptible to performance issues |
| Original Blender | High execution time | Very small | Stable and predictable; useful when consistency is more important than speed |
| Optimised Blender | Moderate execution time | Small | A good compromise between speed and stability |
By representing Bézier curves explicitly in just 28 bytes (float) or 56 bytes (double) using the proposed method, this approach delivers both speed and stability—making it ideal for real-time animation systems. By storing the curve in this form, runtime execution becomes straightforward: it directly interpolates parameter values without the need to solve cubic polynomial equations.This eliminates the overhead typically associated with solving cubic polynomials during runtime.
The cost of determining the interpolating function corresponding to a given Bézier curve is deferred to the construction of an EasingCubicBezier
This is just the beginning of my journey with easing functions. I am working on another solution, whose main goal will be maximum performance in runtime, while maintaining flexibility comparable to that offered by cubic Bézier curves.
Stay tuned!
Comments | #math #rendering Share