Parallax backgrounds for Paper2D

January 28, 2021
Parallax backgrounds for Paper2D

One of the most sought-after effects when building a 2D game is conveying a sense of depth even when the camera is orthographic and everything looks flat. In such an environment, a motion of the camera of 200px, for example, translates into a motion of 200px for each element on screen, regardless of the distance from the camera. This is a stark difference from perspective cameras which, much more naturally, display a much slower movement for items far away from them.

Many people suggest to just use a very far away perspective camera with a strong zoom, to mimick the parallel orthographic look, but allowing all depth-based effects to still function. Unfortunately, this introduces other problems that orthographic cameras simply don't have to deal with.

For my game, I devised a simple method to handle background elements automatically, without complex camera calculations or precise texture placements. The best part is that the whole logic runs in a shader, and with only UV manipulations to boot! (Next time I won't have the UE4 mannequin in the demo, I swear.)

Keep in mind that the effect works for the XZ plane. If your game is played on another plane you'll have some re-wiring to do.

The secret passage obscuring tilemap

This is the whole material. As you can see, there is not much to it, but it can be expanded upon. I'll explain the two main blocks in detail:

The secret passage obscuring tilemap

This is the most important part. In this section we take into account the world position of the rendered pixel (absolute world position) and the position of the camera (view position), adjusted by the background position in world space (BG_center parameter). When I subtract the second value from the first, I'm basically telling the material I want to render what's at position (0,0,0) the whole time, like nothing moved at all.

However, when I introduce the BG_distance parameter, I'm reducing the distance the camera travelled by a fraction. With this method, I can increase or reduce the supposed distance of the background to fake a reduced or increased motion for the texture, respectively.

For example, a background that has distance 0 will multiply the camera position by 0, and it won't move. It will look exactly like it's at the same distance of your tilemap, or the player. But if the distance is 4, the camera will be factored in for 4/5 of its distance from the origin, effectively causing the background to follow it. If your character walks for 200px, the background behind it will move only for 160px, as if it were somewhat far in the distance.

The BG_offset parameter on top is used to offset the final position of the background, mostly when I need it higher or lower, depending on the tilemap it's used with or the position of the camera in a particular room

The last node is just needed to flip the UVs, because the world has the Z coordinate pointing up, but the UVs have the Y coordinate pointing down.

The secret passage obscuring tilemap

After the positioning is done, we can manipulate the UVs further to achieve a variety of effects. In this example I'm preventing vertical or horizontal tiling using two parameters. I don't want the trees to be repeated vertically, so the shader will just repeat the edge pixel. The resulting UVs are then plugged into the texture sampler.

The secret passage obscuring tilemap

This is the setup for the scene from the video above. I made two instances of the material with different distances (0.5 for the archs and columns and 4 for the trees) and applied them to two thin boxes behind my tilemap.

Running the game and moving the player around produces the effect above.

Of course, the background in Nexatli are much more complex, because they can scroll on their own like clouds in the wind or they can be recolored to suit my needs, but this is a good starting point for any game using an orthographic camera.