Day and night cycle skybox shader graph in Unity

Hello everyone, welcome back.

Recently, I have received a comment on one of my video about day and night cycle, and I have taken that opportunity to do the same. So a big shout out to @ecogaming6084 for the idea, You are breathe-taking.



Intro

For this I am using Unity version 2022.2 but it will work on any Unity LTS versions. I have a project in URP. And I am going to use the Skybox shader from Stars shader post.

Then I have the post processing volume with modules Bloom and Tone mapping with the mode Aces.

Now with that out of the way let's get started.

Okay so in our skybox shader let's make some adjustments first.

Let me delete all these Add nodes. Now we have our stars, sky color, our horizon and our ground.



Make a night sky

Let me make some room here and I will duplicate our sky color's Multiply node.

Let's create another Color property for night sky, call it NightSkyColor, Give some default value, drag it in and we will feed it here.

Okay so we have our night sky and our day sky here. Now stars can be seen during night so let's add our stars to our night sky.

Let's also add our horizon and ground part together.

We have our night sky with stars and our day sky, and we want to blend between these two, so let's create a Lerp node.

Lerp stands for linear interpolation, so it will smoothly interpolates between inputs A and B depending on this time input or T.

Take our day sky and feed it into first value A, take our night sky and feed it into B.

Now this T input has a valid range from 0 to 1. If we feed 0 it will take values from input A, if we feed 1 it will take values from B, if we feed 0.5 it will take 50% values from A and 50% from B, if we feed 0.3 it will take 30% values from A and 70% from B and so on.

Finally let's add Lerp and Add node together, then take our Add node's output and feed it into Base color block.



Control day and night with direcitional light

Now we can control day and night with this Input T. I want to control the day and night based on our directional light.

To do that, we will use the directional light's direction and do a dot product operation with our world's up axis. So if our light's direction is parallel to our world's up it will return 1, if our light's direction is perpendicular to our world's up it will return 0, and if our light's direction is opposite to our world's up it will return -1.

Now to get our directional light's direction we could use Main light direction node, but there is a catch. It only seems to work on lit shaders and our skybox is unlit.

So to get the direction we will create a Vector3 property, call it MainLightDirection, then we will feed the direction via script so we don't need to set it as Exposed, so I will just uncheck it.

Then let's create a small script, Let's call it GetMainLightDirection. Attach it to our directional light.

using UnityEngine;

[ExecuteInEditMode]
public class GetMainLightDirection : MonoBehaviour{
[SerializeField] private Material skyboxMaterial;

private void Update() {
skyboxMaterial.
SetVector("_MainLightDirection", transform.forward);
}
}

That's it, save our script.

Let's drag our skybox material into material slot.

Now we have our MainLightDirection, drag it in, then take its output and feed it into Dot product node.

And the world's up is always going to be 0, 1, 0. Now this Dot product node can output value from -1 to 1 but our input T accepts values from 0 to 1.

So let's take our Dot product node's output and feed it into Remap node, Remap node will remap these values, which has original min max from -1 to 1 and remaps them to 0 to 1.

Then take our Remap node's output and feed it into this input T.



Now we can have day and night by rotating our directional light.

Add a sun

It still feels a bit off so let's add a sun.

For that let's use our MainLightDirection, let's also create a View direction node, it will give us normalized direction from our fragment or face to camera.

Then we will take these two and feed it into Dot product node. As discussed it will return values from -1 to 1. We will take its output and feed it into Arccosine node.

Arccosine node is the inverse of Cosine operation for example Cosine(90) = 0 then the Arccosine(0) = 90, so basically it returns angle but in radians.

Then we will create a float property, call it SunSize, give a default value of 0.2, drag it in and we will feed it into Step node.

Step node returns 1 if our input is greater than or equal to this edge otherwise it returns 0.

We will take our Arccosine node's output and feed it into this Edge.



Okay so in the Step node we have our sun, let's create a Color property for our sun color, call it SunColor, Set the mode HDR, give a default value, drag it in.

We will multiply our SunColor with our sun, then I want our sun to exist only in the sky part so we will take the sky part Power node's output and feed it into another Multiply node, then we will feed this Multiply into it.



Now sun only shine during day time so let's add our sun with our day sky. Then take its output and feed it into Lerp node's input A.

That's it save our shader, it will look something like this in the end.


Trouble following along? Check out this video!

Thank you so much for reading!

Comments

  1. This blog post provides a detailed guide on creating a day and night cycle using Skybox Shader Graph in game development. Learn how to achieve dynamic lighting and atmospheric changes to enhance your game's visual appeal and immersion. If you want to know about React native app development tips and tricks, Here you can get valuable information.

    ReplyDelete

Post a Comment