#0
make sure this green box is fully visible
Instructions:
  1. Ideally, use Chrome on desktop
  2. Calibrate browser zoom level with ctrl+scroll or ctrl +/-
  3. Refresh the page (important)
Controls:
  • W/S = previous/next slide
  • A/D = previous/next step, for slides with steps/animations
    • The step indicator will be in the bottom left
make sure this green box is fully visible
#1
What is lerp smoothing?
#2

Lerp smoothing:
a technique to make something smoothly follow something else

a // the position of an object
b // the position of a different object, to follow

// runs once every frame
update(){
	a = lerp(a,b,0.01); // using lerp
	a += (b-a)*0.01;    // without lerp
}

Move a 1% closer to b

#3
#4
#5
However
it's broken
#6
🎮 i maed a game
#7
24 fps vs 120 fps
#8
Framerate Dependence
when behavior depends on framerate
#9
Linear Motion
speed = 0.01;
update(){
	a += speed;
}
Increase by 0.01, once every frame
#10
  1. The code a += speed runs once every frame
  2. So, the speed it reads, has to be in
  3. But, we want to specify speed in
Goal: Find conversion factor to convert
#11
Dimensional Analysis
#12
update(){
	a += speed * dt;
}
#13
Linear Motion
moveToward( a, b, speed, dt ){
	v = b-a;
	stepDist = speed*dt;
	if(stepDist >= abs(v))
		return b; // prevents overshoot
	return a + sign(v)*stepDist;
}
#14
Linear vs Lerp smoothing
#15
Lerp
Linear Interpolation
where
is the start valueis the end valueis a fraction or a percentage, usually between 0 and 1
#16
Linear Interpolation
#17
Lerp Smoothing
Lerp smoothing has non-linear behavior!
#18
Lerp Smoothing
#19
Zeno's Paradox
Zeno of Elea, 490 – 430 BC
"it is impossible to traverse an infinite number of things in a finite time"
#20
Zeno's Paradox
a = 1
a = lerp(a,2,0.5)
f(0) = 1
f(1) = 1.5
f(2) = 1.75
f(3) = 1.875
f(4) = 1.9375
f(5) = 1.96875
f(6) = 1.984375
f(7) = 1.9921875
f(8) = 1.99609375
f(9) = 1.998046875
f(10) = 1.9990234375
f(11) = 1.99951171875
f(12) = 1.999755859375
f(13) = 1.9998779296875
f(14) = 1.99993896484375
f(15) = 1.999969482421875
f(16) = 1.9999847412109375
f(17) = 1.9999923706054688
f(18) = 1.9999961853027344
f(19) = 1.9999980926513672
f(20) = 1.9999990463256836
f(21) = 1.9999995231628418
f(22) = 1.999999761581421
f(23) = 1.9999998807907104
f(24) = 1.9999999403953552
f(25) = 1.9999999701976776
f(26) = 1.9999999850988388
f(27) = 1.9999999925494194
f(28) = 1.9999999962747097
f(29) = 1.9999999981373549
f(30) = 1.9999999990686774
f(31) = 1.9999999995343387
f(32) = 1.9999999997671694
f(33) = 1.9999999998835847
f(34) = 1.9999999999417923
f(35) = 1.9999999999708962
f(36) = 1.999999999985448
f(37) = 1.999999999992724
f(38) = 1.999999999996362
f(39) = 1.999999999998181
f(40) = 1.9999999999990905
f(41) = 1.9999999999995453
f(42) = 1.9999999999997726
f(43) = 1.9999999999998863
f(44) = 1.9999999999999432
f(45) = 1.9999999999999716
f(46) = 1.9999999999999858
f(47) = 1.999999999999993
f(48) = 1.9999999999999964
f(49) = 1.9999999999999982
f(50) = 1.9999999999999991
f(51) = 1.9999999999999996
f(52) = 1.9999999999999998
f(53) = 2
Zeno failed to consider:IEEE 754-2019 64-bit binary floating-point format
#21
#22
24 fps vs 120 fps over time
#23
What shape is this?
#24
Finding Continuity
Linear Motion: a += dt*speed Lerp Smoothing: a = lerp(a,b,F)
#25
Identifying the Curve
  • parabola
  • polynomial
  • hyperbola
  • exponential
  • power function
  • trigonometric
#26
Finding Continuity
#27
Recursion
#28
Finding Continuity
🎉
#29
#30
a = lerp(a,b,F)

This is still framerate dependent (bad)

(we just found its continuous function over time )

#31
#32
is the fraction to move after one frame
is the fraction to move after one second?
long story short: no - we can't just multiply by 😔
#33
#34
Remainder
Goal: Express in terms of
is the fraction traversed at
is the fraction remaining at
#35
#36
#37
#38
Return to code
a = ???
#39
The bad one
a = (a-b)*(1-F)+b
a = lerp(a,b,F)
#40
The good one
a = (a-b)*pow(r,dt)+b
a = lerp(a,b,1-pow(r,dt))
#41
Does it work?
#42
10/20/30/.../110/120 fps

use
#43
this is not half-life :(
#44
Decay
update(){
	if( rnd < 0.03 )
		dot = false;
}

#45
#46

#47
Summary
code per frame
a = lerp(a,b,F)
a = b+(a-b)*pow(remainder,dt)
a = b+(a-b)*exp2(-dt/halfLife)
a = b+(a-b)*exp(-decay*dt)
#48
anyway just do this
// Exponential decay function
expDecay(a, b, decay, dt){
	return b+(a-b)*exp(-decay*dt);
}

// Exponential decay constant
// useful range approx. 1 to 25, from slow to fast
decay = 16;
update(){
	a = expDecay(a, b, decay, Time.deltaTime);
}
#49
thanks~
🌐cat.gay blog coming soon!
✉️[email protected]
acegikmo.substack.com
youtube.com/acegikmo
patreon.com/acegikmo
@FreyaHolmer
#50
Differential calculus
Autonomous first-order differential equation
#51
Spring Physics
#52
How this was made

..with an embarrassing amount of custom JavaScript/HTML/CSS, but also:

Plugins/Assets
KaTeXconverts to HTML elements
Sarabunmain text font, by Suppakit Chalermlarp
CormorantTitle Font by Christian Thalmann
Material SymbolsSymbol font by Google play_arrowpausereplay

Build Pipeline
jsdomto parse/edit HTML during build
node.jsto run js locally on build
rollupshoves all js into one file (for single-file export)
tsxto execute typescript in node
TypeScriptto make javascript bearable
Visual Studio CodeIDE/build environment
web-resource-inlinerinlines external/online files (for single-file export)