diff --git a/src/camera.cpp b/src/camera.cpp
index 735a8d1e9558653a3b7cbbdb4f727e2b0cdda026..211ecfd70e6e79f3367b0dbca63cd5107e2cb632 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -67,6 +67,7 @@ Camera::Camera(scene::ISceneManager* smgr, MapDrawControl& draw_control,
 	m_view_bobbing_anim(0),
 	m_view_bobbing_state(0),
 	m_view_bobbing_speed(0),
+	m_view_bobbing_fall(0),
 
 	m_digging_anim(0),
 	m_digging_button(-1),
@@ -134,6 +135,13 @@ inline f32 my_modf(f32 x)
 
 void Camera::step(f32 dtime)
 {
+	if(m_view_bobbing_fall > 0)
+	{
+		m_view_bobbing_fall -= 3 * dtime;
+		if(m_view_bobbing_fall <= 0)
+			m_view_bobbing_fall = -1; // Mark the effect as finished
+	}
+
 	if (m_view_bobbing_state != 0)
 	{
 		//f32 offset = dtime * m_view_bobbing_speed * 0.035;
@@ -237,11 +245,28 @@ void Camera::update(LocalPlayer* player, f32 frametime, v2u32 screensize,
 	m_playernode->setRotation(v3f(0, -1 * player->getYaw(), 0));
 	m_playernode->updateAbsolutePosition();
 
-	//Get camera tilt timer (hurt animation)
+	// Get camera tilt timer (hurt animation)
 	float cameratilt = fabs(fabs(player->hurt_tilt_timer-0.75)-0.75);
 
+	// Fall bobbing animation
+	float fall_bobbing = 0;
+	if(player->camera_impact >= 1)
+	{
+		if(m_view_bobbing_fall == -1) // Effect took place and has finished
+			player->camera_impact = m_view_bobbing_fall = 0;
+		else if(m_view_bobbing_fall == 0) // Initialize effect
+			m_view_bobbing_fall = 1;
+
+		// Convert 0 -> 1 to 0 -> 1 -> 0
+		fall_bobbing = m_view_bobbing_fall < 0.5 ? m_view_bobbing_fall * 2 : -(m_view_bobbing_fall - 0.5) * 2 + 1;
+		// Smoothen and invert the above
+		fall_bobbing = sin(fall_bobbing * 0.5 * M_PI) * -1;
+		// Amplify according to the intensity of the impact
+		fall_bobbing *= (1 - rangelim(50 / player->camera_impact, 0, 1)) * 5;
+	}
+
 	// Set head node transformation
-	m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength,0));
+	m_headnode->setPosition(player->getEyeOffset()+v3f(0,cameratilt*-player->hurt_tilt_strength+fall_bobbing,0));
 	m_headnode->setRotation(v3f(player->getPitch(), 0, cameratilt*player->hurt_tilt_strength));
 	m_headnode->updateAbsolutePosition();
 
diff --git a/src/camera.h b/src/camera.h
index 989dcb71836e52ef3cd0224b2ceee86aef63a65f..0ed5c20d292096833afe890bdfb08f0fc4d302e1 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -166,6 +166,8 @@ class Camera
 	s32 m_view_bobbing_state;
 	// Speed of view bobbing animation
 	f32 m_view_bobbing_speed;
+	// Fall view bobbing
+	f32 m_view_bobbing_fall;
 
 	// Digging animation frame (0 <= m_digging_anim < 1)
 	f32 m_digging_anim;
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index 9c70c8b2f532a810a844a6db915208f12bbf32c9..6b7b0943cdc1a3ca6f7961a19fa061c14b8af021 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -329,6 +329,9 @@ void LocalPlayer::move(f32 dtime, ClientEnvironment *env, f32 pos_max_d,
 	if(!touching_ground_was && touching_ground){
 		MtEvent *e = new SimpleTriggerEvent("PlayerRegainGround");
 		m_gamedef->event()->put(e);
+
+		// Set camera impact value to be used for view bobbing
+		camera_impact = getSpeed().Y * -1;
 	}
 
 	{
diff --git a/src/localplayer.h b/src/localplayer.h
index 9ac2bc6828b3b3946287615516a0ca3e9c796db5..8c3041c04b4ac40172baa7ddf0dd204299eeb5cb 100644
--- a/src/localplayer.h
+++ b/src/localplayer.h
@@ -59,6 +59,8 @@ class LocalPlayer : public Player
 	float last_yaw;
 	unsigned int last_keyPressed;
 
+	float camera_impact;
+
 private:
 	// This is used for determining the sneaking range
 	v3s16 m_sneak_node;