diff --git a/src/p_slopes.c b/src/p_slopes.c
index ffbfef2d300f5c2645b54c7dc62fa8c9dc8668b5..7c700d73681f15e4e4ca26c76376acb6494b83bc 100644
--- a/src/p_slopes.c
+++ b/src/p_slopes.c
@@ -22,6 +22,7 @@
 #include "r_main.h"
 #include "p_maputl.h"
 #include "w_wad.h"
+#include "r_fps.h"
 
 pslope_t *slopelist = NULL;
 UINT16 slopecount = 0;
@@ -200,6 +201,9 @@ static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, l
 	th->type = type;
 
 	P_AddThinker(THINK_DYNSLOPE, &th->thinker);
+
+	// interpolation
+	R_CreateInterpolator_DynSlope(&th->thinker, slope);
 }
 
 
diff --git a/src/r_fps.c b/src/r_fps.c
index 5c0c8f6df853bfe3f3ad749b17edf09fdacfe293..732052eacbbe8836ce4140324ed091357d6ac32a 100644
--- a/src/r_fps.c
+++ b/src/r_fps.c
@@ -93,6 +93,22 @@ static angle_t R_LerpAngle(angle_t from, angle_t to, fixed_t frac)
 	return from + FixedMul(frac, to - from);
 }
 
+static vector2_t *R_LerpVector2(const vector2_t *from, const vector2_t *to, fixed_t frac, vector2_t *out)
+{
+	FV2_SubEx(to, from, out);
+	FV2_MulEx(out, frac, out);
+	FV2_AddEx(from, out, out);
+	return out;
+}
+
+static vector3_t *R_LerpVector3(const vector3_t *from, const vector3_t *to, fixed_t frac, vector3_t *out)
+{
+	FV3_SubEx(to, from, out);
+	FV3_MulEx(out, frac, out);
+	FV3_AddEx(from, out, out);
+	return out;
+}
+
 // recalc necessary stuff for mouseaiming
 // slopes are already calculated for the full possible view (which is 4*viewheight).
 // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out)
@@ -364,6 +380,20 @@ void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj)
 	interp->polyobj.oldcy = interp->polyobj.bakcy = polyobj->centerPt.y;
 }
 
+void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope)
+{
+	levelinterpolator_t *interp = CreateInterpolator(LVLINTERP_DynSlope, thinker);
+	interp->dynslope.slope = slope;
+
+	FV3_Copy(&interp->dynslope.oldo, &slope->o);
+	FV3_Copy(&interp->dynslope.bako, &slope->o);
+
+	FV2_Copy(&interp->dynslope.oldd, &slope->d);
+	FV2_Copy(&interp->dynslope.bakd, &slope->d);
+
+	interp->dynslope.oldzdelta = interp->dynslope.bakzdelta = slope->zdelta;
+}
+
 void R_InitializeLevelInterpolators(void)
 {
 	levelinterpolators_len = 0;
@@ -406,6 +436,15 @@ static void UpdateLevelInterpolatorState(levelinterpolator_t *interp)
 		interp->polyobj.bakcx = interp->polyobj.polyobj->centerPt.x;
 		interp->polyobj.bakcy = interp->polyobj.polyobj->centerPt.y;
 		break;
+	case LVLINTERP_DynSlope:
+		FV3_Copy(&interp->dynslope.oldo, &interp->dynslope.bako);
+		FV2_Copy(&interp->dynslope.oldd, &interp->dynslope.bakd);
+		interp->dynslope.oldzdelta = interp->dynslope.bakzdelta;
+
+		FV3_Copy(&interp->dynslope.bako, &interp->dynslope.slope->o);
+		FV2_Copy(&interp->dynslope.bakd, &interp->dynslope.slope->d);
+		interp->dynslope.bakzdelta = interp->dynslope.slope->zdelta;
+		break;
 	}
 }
 
@@ -484,6 +523,11 @@ void R_ApplyLevelInterpolators(fixed_t frac)
 			interp->polyobj.polyobj->centerPt.x = R_LerpFixed(interp->polyobj.oldcx, interp->polyobj.bakcx, frac);
 			interp->polyobj.polyobj->centerPt.y = R_LerpFixed(interp->polyobj.oldcy, interp->polyobj.bakcy, frac);
 			break;
+		case LVLINTERP_DynSlope:
+			R_LerpVector3(&interp->dynslope.oldo, &interp->dynslope.bako, frac, &interp->dynslope.slope->o);
+			R_LerpVector2(&interp->dynslope.oldd, &interp->dynslope.bakd, frac, &interp->dynslope.slope->d);
+			interp->dynslope.slope->zdelta = R_LerpFixed(interp->dynslope.oldzdelta, interp->dynslope.bakzdelta, frac);
+			break;
 		}
 	}
 }
@@ -533,6 +577,11 @@ void R_RestoreLevelInterpolators(void)
 			interp->polyobj.polyobj->centerPt.x = interp->polyobj.bakcx;
 			interp->polyobj.polyobj->centerPt.y = interp->polyobj.bakcy;
 			break;
+		case LVLINTERP_DynSlope:
+			FV3_Copy(&interp->dynslope.slope->o, &interp->dynslope.bako);
+			FV2_Copy(&interp->dynslope.slope->d, &interp->dynslope.bakd);
+			interp->dynslope.slope->zdelta = interp->dynslope.bakzdelta;
+			break;
 		}
 	}
 }
diff --git a/src/r_fps.h b/src/r_fps.h
index ec85a1f35fafa5c7ee96eeb24f28279bd0d1c00b..8ce2f3c26d5fdac64190f5bea9e1130ca03c0814 100644
--- a/src/r_fps.h
+++ b/src/r_fps.h
@@ -66,6 +66,7 @@ typedef enum {
 	LVLINTERP_SectorScroll,
 	LVLINTERP_SideScroll,
 	LVLINTERP_Polyobj,
+	LVLINTERP_DynSlope,
 } levelinterpolator_type_e;
 
 // Tagged union of a level interpolator
@@ -95,6 +96,12 @@ typedef struct levelinterpolator_s {
 			size_t vertices_size;
 			fixed_t oldcx, oldcy, bakcx, bakcy;
 		} polyobj;
+		struct {
+			pslope_t *slope;
+			vector3_t oldo, bako;
+			vector2_t oldd, bakd;
+			fixed_t oldzdelta, bakzdelta;
+		} dynslope;
 	};
 } levelinterpolator_t;
 
@@ -119,6 +126,7 @@ void R_CreateInterpolator_SectorPlane(thinker_t *thinker, sector_t *sector, bool
 void R_CreateInterpolator_SectorScroll(thinker_t *thinker, sector_t *sector, boolean ceiling);
 void R_CreateInterpolator_SideScroll(thinker_t *thinker, side_t *side);
 void R_CreateInterpolator_Polyobj(thinker_t *thinker, polyobj_t *polyobj);
+void R_CreateInterpolator_DynSlope(thinker_t *thinker, pslope_t *slope);
 
 // Initialize level interpolators after a level change
 void R_InitializeLevelInterpolators(void);