Hey everyone,
So I have been tinkering around with a dynamic procedural skybox shader that supports a Day/Night cycle with moving Sun, Moon and stars and it is finally at a point worth showing off I think.
So what I came up with is a shader that does most of the work, and then a small helper MonoBehavior to manage in game “Time” and update the shader with a few tidbits of info. There are no in game objects for any of this besides Two Directional Lights, and a GameObject with the TimeManager MonoBehavior on it.
TimeManager Monobehavior Features:
- Adjust how many real time minutes equate to one in-game hour.
- Adjust how many in-game hours are in an in-game day.
- Adjust how many in-game days are in an in-game month.
- Adjust how many in-game months are in an in game year.
- Adjust Starting location of Sun, and Moon.
- Adjust Rotation of sun and moon on all three axis using curves editor.
- Ability to adjust in-game Time Scale (useful for when testing)
Shader Features:
- Single Pass
- Sun, Moon & moon are procedural generated off properties you set on the shader.
- Customize Moon & Sun Size, Color, Highlight Color, and Glow and a distortion texture
- Solar Eclipses! The sun passes behind the moon and darkens and blacks out the moon.
- Separately Enable or Disable rendering of the sun or moon. Uses shader Keywords to use optimized shaders.
- Uses the main Directional Light for sun orientation (information already available in shader), and a secondary Directional light for the moons orientation (passed to shader).
- MonoBehavior script to control rotation of sun and moon lights as well as update shader with the current time and position of the moon, that is it! Everything else is calculated in the shader.
- Procedural Stars - Stars locations are generated by some quasi-random noise and move through the sky over time. You are able to set the color of the stars as well as the speed in which they move across the night sky.
- 4 Distinct time periods (Dawn, Day, Dusk, Night) Each with its own customizeable Horizon and Sky colors. The color of the sky is interpolated between these values based on the time of day (a property settable on the shader)
- Completely custom Inspector for the shader that makes setting up your skybox quick and intuitive.
- Custom inspector features “Fast” and “Slow” preview modes where it simulates a 24 hour period updating the skybox in the scene view. (Does not currently move sun or moon)
Here is a little video I made of it in action. Sorry the quality of the video isn’t the best, just started using OBS Studio and Blender for video editing so I’m still getting the hang of it…
Time is scaled by a factor of 100 in the video as it would normally take a while for a full 24 hour cycle otherwise.
Screenshot of custom Inspector for shader
Screen Shots of shader in action. WARNING: large images
Some of the additional things I am considering doing, or just need to figure out how to do are
- Adjustable height range for the gradient in each of the 4 time segments. Currently the gradient stretches from horizon to 25% of the way to the top. This is actually pretty much done I would just need to add 4 more variables to shader.
- Based on the position of the sun I would like to add a “glow” to a given edge of the moon, especially during eclipses. Im pretty sure this is possible but i haven’t not tried to wrap my head around the math yet, everything else so far has been pretty easy.
- Add some sort of smoothed distortion to the height of the gradient so its not so “perfect”. Fairly simple just need to add a Texture to represent some noise… could use existing sun or moon texture but there is no guarantee of “smoothness” of the noise.
- Add a “fog/cloudy” effect that scrolls around the skybox… you know those nights when its not really cloudy but there is that just fine hazy cloudy-ness that’s barely perceptible. This one is super simple to do, the only issue im having currently is units UV mapping for the default skybox stretches really really really bad from the horizon to about 25-35 % of the way up.
- Customizeable spiral Nebula type effects in the night sky…Again pretty sure this is possible, I’m just unsure of the math…I’m pretty sure it simple a distance function like i have for the sun to give the radius of the overall circle the galaxy is in, then another function to tell if a given pixel is part of the spiral or not… any ideas on the math here?
- Shooting stars, comets, other dynamic celestial objects
- Optimize the code some more… It already functions amazingly fast but I want to add a lot more and I think I can move some of the stuff of the code to the vertex function instead and let it interpolate from there without to much quality loss, but I also think I read somewhere depending on hardware there is a limited number of interpolaters for transferring data.
- Dawn and Dusk gradients should only be used in the direction of the sun is rising or setting from. Currently it uses it all the way around. This shouldn’t be to bad to add either, simply need to constrain the gradient to a radius around the sun.
- Custom Inspector for monoBehavior. This is in the works which is why there is no screen shot yet.
So there you have it so far, im sure there are things I’m forgetting to mention but hopefully you all have question or comments.
Thanks for checking out my post.