在计算机图形学、动画制作和数据处理领域,插值和平滑过渡是常见且重要的操作。在 C# 等编程语言中,开发者可以利用数学函数来实现这些功能,其中包括线性插值(Lerp)、平滑步进(Smoothstep)以及各种自定义的 shaping 函数
1:Lerp、Smoothstep 和 Shaping
1:Lerp
(Linear Interpolation)
使用场景:
- 动画: 用于在关键帧之间进行线性插值,使得物体或颜色平滑过渡。
- 游戏开发: 移动物体、角色的线性位移、缩放等。
- 数据插值: 在已知数据点之间插值,生成中间值。
using System;
public class Program {
public static void Main() {
float a = 0.0f;
float b = 1.0f;
float t = 0.5f; // 插值因子,范围一般为 [0, 1]
float result = Lerp(a, b, t);
Console.WriteLine(result); // 输出 0.5
}
// 线性插值函数
public static float Lerp(float a, float b, float t) {
return a + t * (b - a);
}
}
2:Smoothstep
使用场景:
- 纹理混合: 使得两种纹理之间的过渡更加平滑。
- 抗锯齿: 平滑边缘,减少锯齿效应。
- 渐变效果: 创建更自然的颜色或亮度渐变。
using System;
public class Program {
public static void Main() {
float edge0 = 0.0f;
float edge1 = 1.0f;
float x = 0.5f;
float result = Smoothstep(edge0, edge1, x);
Console.WriteLine(result); // 输出 0.5
}
// Smoothstep 函数
public static float Smoothstep(float edge0, float edge1, float x) {
x = Math.Clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
return x * x * (3 - 2 * x);
}
}
3:Shaping 函数
使用场景:
- 自定义插值: 根据具体需求定义曲线形状。
- 动画缓动: 实现非线性动画效果,如缓入缓出、弹性运动等。
- 信号处理: 调整信号的形状和特性。
using System;
public class Program {
public static void Main() {
float t = 0.5f;
float result = SineEaseInOut(t);
Console.WriteLine(result); // 输出 根据 t 的值而定
}
// SineEaseInOut 函数示例
public static float SineEaseInOut(float t) {
return -0.5f * (float)(Math.Cos(Math.PI * t) - 1.0f);
}
}
4:保持一致性(Handling Different Frame Rates)
在动画和插值中,帧率不同会影响运动的平滑度和速度。为了保持一致性,通常需要对插值进行时间依赖的调整。
时间依赖的插值
- 时间增量(Delta Time):
- 使用每帧的时间增量(delta time)来调整插值的速度,使得动画在不同帧率下保持一致。
float smoothstepWithDeltaTime(float edge0, float edge1, float x, float deltaTime) {
float speed = 0.1f; // 插值速度
x += deltaTime * speed;
x = std::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
return x * x * (3 - 2 * x);
}
2:自定义 Shaping 函数 有哪些曲线方式
1. Sine 函数曲线
1.SineEaseIn
- 描述: 缓入效果,开始时速度较慢,逐渐加快。
- 数学表达式: f(t)=−cos(t∗π2)+1f(t) = -\cos(t * \frac{\pi}{2}) + 1f(t)=−cos(t∗2π)+1
public static float SineEaseIn(float t) {
return 1.0f - (float)Math.Cos(t * Math.PI / 2.0);
}
2.SineEaseOut
- 描述: 缓出效果,开始时速度较快,逐渐减慢。
- 数学表达式: f(t)=sin(t∗π2)f(t) = \sin(t * \frac{\pi}{2})f(t)=sin(t∗2π)
public static float SineEaseOut(float t) {
return (float)Math.Sin(t * Math.PI / 2.0);
}
3.SineEaseInOut
- 描述: 缓入缓出效果,开始和结束时速度较慢,中间速度较快。
- 数学表达式: 组合 SineEaseIn 和 SineEaseOut
public static float SineEaseInOut(float t) {
return -0.5f * ((float)Math.Cos(Math.PI * t) - 1.0f);
}
2.Quadratic 函数曲线
1.QuadEaseIn
- 描述: 缓入效果,开始时速度较慢,逐渐加快。
- 数学表达式: f(t)=t∗tf(t) = t * tf(t)=t∗t
public static float SineEaseIn(float t) {
return 1.0f - (float)Math.Cos(t * Math.PI / 2.0);
}
2.QuadEaseOut
- 描述: 缓入效果,开始时速度较慢,逐渐加快。
- 数学表达式: f(t)=t∗tf(t) = t * tf(t)=t∗t
public static float QuadEaseOut(float t) {
return -t * (t - 2);
}
3.QuadEaseInOut
- 描述: 缓入缓出效果,开始和结束时速度较慢,中间速度较快。
- 数学表达式: 组合 QuadEaseIn 和 QuadEaseOut
public static float QuadEaseInOut(float t) {
return (t < 0.5f) ? 2.0f * t * t : -1.0f + (4.0f - 2.0f * t) * t;
}
3.Cubic 函数曲线
1.CubicEaseIn
- 描述: 缓入效果,开始时速度较慢,逐渐加快。
- 数学表达式: f(t)=t∗t∗tf(t) = t * t * tf(t)=t∗t∗t
public static float CubicEaseIn(float t) {
return t * t * t;
}
2.CubicEaseOut
- 描述: 缓出效果,开始时速度较快,逐渐减慢。
- 数学表达式: f(t)=(t−1)∗(t−1)∗(t−1)+1f(t) = (t - 1) * (t - 1) * (t - 1) + 1f(t)=(t−1)∗(t−1)∗(t−1)+1
public static float CubicEaseOut(float t) {
float temp = t - 1.0f;
return temp * temp * temp + 1.0f;
}
3.CubicEaseInOut
- 描述: 缓入缓出效果,开始和结束时速度较慢,中间速度较快。
- 数学表达式: 组合 CubicEaseIn 和 CubicEaseOut
public static float CubicEaseInOut(float t) {
return (t < 0.5f) ? 4.0f * t * t * t : (t - 1.0f) * (2.0f * t - 2.0f) * (2.0f * t - 2.0f) + 1.0f;
}
可以根据具体需求定义各种复杂的 shaping 函数,例如多项式、三角函数的组合或者其他非线性函数,以实现更复杂的动画效果或信号处理。在实际应用中,根据需求选择合适的 shaping 函数,可以显著提升动画的视觉效果和用户体验。
学习不易 记录一下