Skip to main content
Bounty Ended with 50 reputation awarded by Ryan Peschel
added 160 characters in body
Source Link
liggiorgio
  • 4.9k
  • 6
  • 26
  • 37

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.


EDIT

The external answer you included in your question refers to a piece of code which contains a comment:

// No need for the "if" - we'll practically never reach exactly 0 distance anyway.

This is an expected behaviour for two reasons:

  • Interpolation, from a mathematical perspective, converges to a constant value after an infinite number of steps. I mean an exact value convergence, which can never be reached after a finite number of steps: 100000000000000000000000000000000 lerping steps are a huge amount, yet still finite. However, convergence occurs on computers due to machine error caused by the limited number of bits used to represent individual values
  • Interpolation of a value towards another that changes over time (player is moving around) cannot really converge, since the target value changes more or less unpredictably each step

If you want to smooth your camera movement, you could fix its behaviour when it is close enough to the player, such as snapping its position to the player's if the distance is smaller than a value such that it prevents undesired visual effects.:

  • Snapping camera position to the player's if the distance is smaller than a value such that it prevents undesired visual effects
  • Taking explicit control of t, and change its value over time rather than over distance to make sure it equals 1, and best follow the player object

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.


EDIT

The external answer you included in your question refers to a piece of code which contains a comment:

// No need for the "if" - we'll practically never reach exactly 0 distance anyway.

This is an expected behaviour for two reasons:

  • Interpolation, from a mathematical perspective, converges to a constant value after an infinite number of steps. I mean an exact value convergence, which can never be reached after a finite number of steps: 100000000000000000000000000000000 lerping steps are a huge amount, yet still finite. However, convergence occurs on computers due to machine error caused by the limited number of bits used to represent individual values
  • Interpolation of a value towards another that changes over time (player is moving around) cannot really converge, since the target value changes more or less unpredictably each step

If you want to smooth your camera movement, you could fix its behaviour when it is close enough to the player, such as snapping its position to the player's if the distance is smaller than a value such that it prevents undesired visual effects.

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.


EDIT

The external answer you included in your question refers to a piece of code which contains a comment:

// No need for the "if" - we'll practically never reach exactly 0 distance anyway.

This is an expected behaviour for two reasons:

  • Interpolation, from a mathematical perspective, converges to a constant value after an infinite number of steps. I mean an exact value convergence, which can never be reached after a finite number of steps: 100000000000000000000000000000000 lerping steps are a huge amount, yet still finite. However, convergence occurs on computers due to machine error caused by the limited number of bits used to represent individual values
  • Interpolation of a value towards another that changes over time (player is moving around) cannot really converge, since the target value changes more or less unpredictably each step

If you want to smooth your camera movement, you could fix its behaviour when it is close enough to the player, such as:

  • Snapping camera position to the player's if the distance is smaller than a value such that it prevents undesired visual effects
  • Taking explicit control of t, and change its value over time rather than over distance to make sure it equals 1, and best follow the player object
Expanded the answer with additional considerations
Source Link
liggiorgio
  • 4.9k
  • 6
  • 26
  • 37

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.


EDIT

The external answer you included in your question refers to a piece of code which contains a comment:

// No need for the "if" - we'll practically never reach exactly 0 distance anyway.

This is an expected behaviour for two reasons:

  • Interpolation, from a mathematical perspective, converges to a constant value after an infinite number of steps. I mean an exact value convergence, which can never be reached after a finite number of steps: 100000000000000000000000000000000 lerping steps are a huge amount, yet still finite. However, convergence occurs on computers due to machine error caused by the limited number of bits used to represent individual values
  • Interpolation of a value towards another that changes over time (player is moving around) cannot really converge, since the target value changes more or less unpredictably each step

If you want to smooth your camera movement, you could fix its behaviour when it is close enough to the player, such as snapping its position to the player's if the distance is smaller than a value such that it prevents undesired visual effects.

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.


EDIT

The external answer you included in your question refers to a piece of code which contains a comment:

// No need for the "if" - we'll practically never reach exactly 0 distance anyway.

This is an expected behaviour for two reasons:

  • Interpolation, from a mathematical perspective, converges to a constant value after an infinite number of steps. I mean an exact value convergence, which can never be reached after a finite number of steps: 100000000000000000000000000000000 lerping steps are a huge amount, yet still finite. However, convergence occurs on computers due to machine error caused by the limited number of bits used to represent individual values
  • Interpolation of a value towards another that changes over time (player is moving around) cannot really converge, since the target value changes more or less unpredictably each step

If you want to smooth your camera movement, you could fix its behaviour when it is close enough to the player, such as snapping its position to the player's if the distance is smaller than a value such that it prevents undesired visual effects.

Source Link
liggiorgio
  • 4.9k
  • 6
  • 26
  • 37

The blurry visual artefacts you are experiencing may be caused by how the rendering stack treats floating-point numbers when it comes to drawing sprites: world positions are floating-point numbers, pixels on the screen are not.

As a (blind) attempt to solve this issue, I suggest to change your interpolation function from this:

function lerp(a, b, t) { return a + (b - a) * t; }

To this:

function lerp(a, b, t) { return (1 - t) * a + t * b; }

The latter version guarantees to return b when t = 1, whereas the former doesn't due to floating-point arithmetic error.

In your particular case, b is the player position which the camera is trying to reach; small decimal differences may lead to rounding errors when rendering on the screen, which is the alleged cause of your current issue.