Planetary atmospheres on Roblox

Introducing AtmosphereService

Hello my fellow Roblox developers, today I’m glad to announce that celestial atmospheres are no longer an issue on creating realistic planets or gas giants. On this guide we’ll walk you trough how AtmosphereService works and how you can implement this into your next game.


What is AtmosphereService?

As said AtmosphereService is a helpful tool when making atmospheres outside of the skybox, what that means is that you can apply atmospheres into other spherical objects.


The core system behind AtmosphereService

"Shell Texturing"

To modify and change the core of atmosphere its important to understand how it all works and the design choices made with the code, so lets go through it “all” together.

We know that on Roblox you can’t really have gradient spheres, so to begin we’ll think of the simples version of our problem.

If we would want to add a 2 dimensional atmosphere on a 2 dimensional globe the problem becomes much more simpler to solve, all we have to do is place a gradient circle behind the layer of the 2D globe. Now to step up in complexity let’s now imagine a 2D creature observing a sphere passing through their plane of existence. Since this creature can only see in 2D they see an infinitely small slice of the sphere, which for them is only a circle. This circle grows and shrinks as the ball rolls through their plane of existence.

Now how can this help in creating 3D gradient spheres? Well we could layer these observations from the creature, spacing each layer accordingly in the 3rd dimension. When a sufficient amount of layers have been added the result is a sphere. Since in Roblox this would not be a physical object but many GUI’s we can apply textures. Layering many textures to create a sense of 3D is often referred to “shell texturing”, a way many video games fake fur.


Generating Shadows

Basically the most important aspect of creating a good looking atmosphere is the shadows (not including the refraction of light). We’ll have to dig into some math and reconsider how shadows will work since it’s not plausible to add a 3D shadow to a 2D object, but what’s there to expect than just math math math!

To darken any GUI what we would normally do is change the RGB values, but what we need is to darken a portion of the GUI. What we need is a UIGradient. If we apply a UI gradient to the gradient circles the resulting output is an atmosphere with half of it covered in shadow.

But BillboardGUI’s (the 2D layers) always face towards the camera, which means that the shadows follow along. What we need is a dynamic shadow system.

To make a “3D” shadow from UIGradients, we’ll utilise the offset variable for the layers. If we apply an offset to the UIGradient there the z variable is the offset, we get a 45° degree shadow. And if we were to multiply that by a tan function we get an amazing shadow for the rotation of the Y axis.

now all that’s left is to solve what rotation offset we need the UIGradient to have. Compared to calculating the offset, the solution is relatively straight forward, just use atan2 to calculate on which direction it should look at.


How does AtmosphereService look

:eyes: pretty good I would say, could be better.



Implementing AtmosphereService into your game

To implement this groundbreaking feature to your game follow these two steps, if you can:

  1. add this model into your game and place everything where needed.
  2. make a new script or local script and try adding an atmosphere. Its important to know what all variables do
  3. if any problems arise you can just message down below! I’ll answer some day.
Instancing Atmosphere

note: the provided code only works in the client

local AtmosphereService = require(game:GetService("ReplicatedStorage").AtmosphereService) -- Gets module script responsible for AtmosphereService

local Atmosphere = AtmosphereService.NewAtmosphere(
	game.Workspace:WaitForChild("Earth"), -- Parent of the atmosphere
	40, -- The radius of the atmosphere
	500, -- The #Layers that represent the atmosphere (recommended value is 500) 
	.4, -- Transparency of the atmosphere
	Color3.fromRGB(182, 194, 249), -- Color of the atmosphere
	Color3.fromRGB(185, 255, 233) -- Transition color (from in light to shadow)
)

game:GetService("RunService").RenderStepped:Connect(function()
	AtmosphereService.UpdateAtmosphere(Atmosphere) -- Crutial for generating the shadows
end)

I wish you the best of luck with your game. As said feel free to discuss ideas in the comments, maybe even show what cinematic masterpieces you created with it!

22 Likes


I get this when I click the link

2 Likes

oh no. looks like I forgot to do something. l’ll fix this as fast as possible

1 Like

I think I fixed it, thank you for telling me about that!

2 Likes

Got me interested so decided to give it a try


For me, the atmosphere looks nothing like the screenshots you provided, am I doing something wrong?
Code:

local replicatedStorage = game:GetService("ReplicatedStorage")
local atmosphereService = require(replicatedStorage.AtmosphereService)

local thisAtmos = atmosphereService.NewAtmosphere(workspace.Earth, 18, 500, 500, Color3.fromRGB(116, 211, 255), Color3.fromRGB(0, 0, 0))

while task.wait() do
	atmosphereService.UpdateAtmosphere(thisAtmos)
end
1 Like

hmmm, it looks correct but lets try with this code:

local AtmosphereService = require(game:GetService("ReplicatedStorage").AtmosphereService) -- Gets module script responsible for AtmosphereService

local Atmosphere = AtmosphereService.NewAtmosphere(game.Workspace:WaitForChild("Earth"), 40, 400, .4, Color3.fromRGB(182, 194, 249), Color3.fromRGB(185, 255, 233)) -- Instances a new atmosphere

game:GetService("RunService").RenderStepped:Connect(function()
	AtmosphereService.UpdateAtmosphere(Atmosphere) -- Crutial for generating the shadows
end)

If this doesn’t work there must have been a problem when implementing the AtmosphereService, hope this helps

2 Likes

That did the trick, thanks! I’m definitely using this in a space game I’m making

Keep up the great work!

2 Likes

can you supply a .rbxl with a working planet? I added the code at the bottom of this post to a local script and a model called Earth… and I do not see any change…

Hello! Looking from the provided code and image I suspect that your atmosphere is scaled to small, setting the right variables are crucial for this to work. Try to peek into the planet to see if you get a gradient ball. If so and it’s to small, you’ll have to change some values when adding the atmosphere.

Now I would like to explain what these values represent since it seems like this has been the root of most problems when implementing atmospheres.

The first variable requires the parent for the atmosphere
The second variable explains the size of the atmosphere
The third variable explains the amount of 2D layers should represent the gradient sphere
The fourth sets the transparency of the atmosphere
The fifth variable explains the color and the last variable explains what color the transition from bright to dark there shall be.

Hope this helps :+1:

1 Like

I’m not sure if it’s possible to make it work whenever I fly into the planet and the atmosphere changes when I’m inside the planet it’s should be unaffected on other player’s clients while I’m inside the planet in game?

1 Like

This a great idea! Mixing both the Roblox built in atmosphere to add to AtmosphereService to add to the sky,

To see if this works let’s address if client-side atmospheres are even possible, which they are!

From experiences client-side fog and sky along with client-side atmospheres can be made and from the creator hub guides: Atmospheric Effects | Documentation - Roblox Creator Hub I can’t seem to find clues on client based atmospheres being not supported.

My conclusion is that I will consider adding it in the future, maybe in some months. I have the 3 reasons down below

  1. Transitions from space to ground will be a pain to get correctly, my deepest fear will be fog as it may obscure other planets when looking up even on a planet with a thin atmosphere.

  2. New instancing features, in this case to know if the player is inside or outside the planets atmosphere with a gradient from 0 - 1 I have to make sure that two new variables replace only the one “size” controller. Those variables would be SurfaceRaduis and AtmosphereRadius.

  3. Atmosphere effects biggest problem is that the “gradient” on the sky from the atmosphere cannot start <0 on the y axis which is understandable for most games as they don’t need that extra flexibility. And in this case I will have to do some transition to fix that, which is then more of a pain to get correctly

3 Likes

The texture used for the atmosphere was not centered, causing the final result to be offset. Here is a fixed version of the texture used you can replace for both the decal and imageLabel texture:

1 Like

Ah! Thanks Burdy for the provided image! I will make sure to update the code as soon as possible! :wink:

99% made a difference! (also updated the code to remove some visual bugs)

The link for atmosphere service has now been updated.

1 Question is it a local script or a script that is normal for client.

The code that you instance and update the calculations for the atmosphere shall be made inside a local script.

Thank you for the information.
Keep the hype up!

1 Like