-
Notifications
You must be signed in to change notification settings - Fork 411
3D Skybox
This demo showcases how Camera Stacking can be used to draw a 3-Dimensional Skybox which is used to improve visual fidelity of the unreachable areas of a scene.
- Can be found at
_CompletedDemos/3DSkybox/3DSkybox.unity
- Uses Camera Stacking which is part of the URP Package
- Different cameras for creating the illusion of grand scale
A 3D Skybox is a miniature "subscene" residing outside the bounds of the playable area. It is rendered behind the playable area to create the illusion that the game world is much larger than it actually is. Compared to only having a 2D skybox, the elements in the 3D skybox have the advantage of being rendered in real time and can therefore contain animations, particles etc.
The scene has one player camera, and one camera for each 3D skybox. In the common case, a single 3D skybox is enough to achieve the desired effect. In the space scene example however, since distances are so big, an additional camera has been created to render a 3D skybox with objects that are very far away (stars). This gives three cameras. One for rendering the player, one for rendering the planets, and one for rendering both the stars and a 2D skybox:
The camera stack list on the base camera determines the order which the overlay cameras should be rendered in (top to buttom). This intuitively means that the skybox furthest away should be the base camera, and that the planets and player should be drawn on top as overlay cameras. This is however not ideal for performance as any stars blocked by a planet, or planets blocked by the player, will be drawn regardless. Therefore, we would like to be able to draw the closer objects first. This is achieved by having a different render pipeline for each camera. Each render pipeline will override the stencil buffer such that the overlaying camera does not draw on top of what is already there.
The player camera render type is set to Base
and is assigned the 3dSkyBox_Ship
render pipeline. The background will be drawn by another camera and should be set to Uninitialized
. The stack is set up such that planets are drawn after the ship, and the stars are drawn last:
The render pipeline is setup to write "1" into the stencil buffer:
-
Default Layer Mask
is set to ignore theSkybox
layer as it will be drawn later. -
Stencil
is overridden to contain a value of 1 in pixels where the ship has been drawn. This is used to determine where the planet camera should draw planets.
The planet camera render type is set to Overlay
and is assigned the 3dSkyBox_Planet
render pipeline. Which overrides the stencil settings:
- Tests whether stencil buffer value is equal to zero
- This will discard pixels already drawn by the player camera.
- Inverts the stencil value
- This will mark the newly drawn planets with non-zero stencil values.
The star camera render type is also set to Overlay
and is assigned the 3dSkyBox_StarBox
render pipeline. The render pipeline overrides the stencil settings and also draws a sky box:
- Tests whether the stencil buffer value is equal to zero
- The previous two cameras ensured non-zero values on pixels that should not be overdrawn.
- The
SkyboxRenderFeature
simply adds aDrawSkyboxPass
to the pipeline at theAfterRenderingOpaques
event.
When the player flies around in the space ship, the planets and stars will stand still since their cameras aren't rotating with the player. This can be solved using a simple script which will be put on the skybox cameras. The script will have a reference to the player camera and, each frame, make sure that their rotations align:
transform.rotation = playerCam.rotation
Since the position of the skybox cameras is not changing, no parallax will be visible in the skybox when the player moves. To solve this we get the start position of the skybox camera in start()
and keep it. Using a float variable proportionality
we set the position of the camera each frame to be startPos + playerCam.position * proportionality
. The lower the proportionality
the less that skybox camera moves and the bigger the skybox will seem. In the space example the proportionality
is 0 for the star camera and 0.0002 for the planet camera. This means that the stars will seem infinitely far away, and the planets will seem 5000 times larger than they actually are in the scene. If a non-zero proportionality is used, it is important to have boundaries for the playable area. Otherwise the player will be able to move up close to (and through) the sky box, breaking the illusion.
In the picture the closer planet is being clipped by the near clipping plane of the planet skybox camera because the player has been allowed to freely move too close to it.