您需要 登录 才可以下载或查看,没有账号?注册
x
制作一个风格化程序化天空球Shader 作者 Minions Art
is creating Game Art Tips and Astro Kat, a Catventure game!
Making a Stylized Skybox Shader
Hey everyone,
In this post I'm going to show you how I made my stylized skybox
To begin with, I wanted it to have a few properties:
- Customisable colors
- Different settings for night and day
- Noise-based clouds so I don't have to hand-draw them for different scenes
I think it worked out pretty well
Sun
Starting with a new Unlit Shader , the first thing to add is a sun that follows the directional light.
Unity stores the direction of the directional light in _WorldSpaceLightPos0.
Just like in the worldposition radius shader tutorials, we create a circle using distance between the target and the current position.
Since it's a skybox, instead of the vertex-position, use the uv position.
float sun = distance(i.uv.xyz, _WorldSpaceLightPos0);
float sunDisc = 1 - saturate(sun / _SunRadius);
With the position calculated, create a circle by dividing by a radius, then inverting the value.
Moon
I want the moon to appear on the opposite side of the sun for a nice day-night cycle look.
So the only difference from the sun's code, is that the _WorldSpaceLightPos0 is negative.
float moon = distance(i.uv.xyz, -_WorldSpaceLightPos0);
float moonDisc = 1 - (moon / _MoonRadius);
The moon disc opposite the sun
float crescentMoon = distance(float3(i.uv.x + _MoonOffset, i.uv.yz), -_WorldSpaceLightPos0);
float crescentMoonDisc = 1-(crescentMoon / _MoonRadius);
newMoonDisc = moonDisc - crescenMoonDisc;
Add a crescent look by subtracting another moon-sphere with a slight offset on the UV
Sliding the negative moon infront
Gradient Sky
It's all looking a bit bleak so let's add some color
float3 gradientDay = lerp(_DayBottomColor, _DayTopColor, saturate(i.uv.y));
Lerp a gradient of 2 colors over the UV vertical axis, saturate it so we don't get negative values in our colors.
This gradient works for the day, but when night comes another set of colors should show up.
float3 gradientNight = lerp(_NightBottomColor, _NightTopColor, saturate(i.uv.y));
float3 skyGradients = lerp(gradientNight, gradientDay, saturate(_WorldSpaceLightPos0.y_));
Create a second gradient for night colors, then lerp these two together with the Y value of the WorldSpaceLightPos.
Horizon Color
First get the horizon
float horizon = abs(i.uv.y) ;
Using Abs to mirror, and the UV.Y , a horizon line becomes visible (but should be inverted for this effect)
float horizonGlow = saturate((1 - horizon) * saturate(_WorldSpaceLightPos0.y));
float4 horizonGlowDay = horizonGlow * _HorizonColorDay;
The sunset/sunrise color should only show up on the horizon, and when the sun is near the horizon
Stars
Stars disappear when the sun is up
We need some stars in the night sky! First create a UV space.
Noise texture on the sky UV
float2 skyUV = i.worldPos.xz / i.worldPos.y;
float3 stars = tex2D(_Stars, skyUV - _Time.x);
stars *= 1 - saturate(_WorldSpaceLightPos0.y);
By dividing the World Position xz by the y, we get a UV space that looks like it lays flat against the sky.
Project a star texture on this UV, then multiply it by the inverted light direction to make sure it only shows up at night.
Moving Clouds
Finally add the noise based clouds
Using the same UV as the stars, we're going to scroll a few noise textures over eachother to create the illusion of a moving mass
float baseNoise = tex2D(_BaseNoise, (skyUV - scrollSpeed) * _Scale);
float noise1 = tex2D(_Distort, ((skyUV + baseNoise)- scrollSpeed) * _Scale);
float noise2 = tex2D(_SecNoise, ((skyUV + noise1 ) - scrollSpeed) * _Scale);
Project the noise textures over the sky uv, adding the new noise to distort the uv
float finalNoise = saturate(noise1 * noise2) * saturate(i.worldPos.y);
Multiply them together, saturate to keep the values between 0 and 1, then multiply by the saturated world position Y so it only shows up on the sky.
The result looks pretty stormy, like moving clouds
float clouds = saturate(smoothstep(_CloudCutoff, _CloudCutoff + _Fuzziness, finalNoise));
To still see the sky through the clouds, make a smoothstep through the final noise
float4 cloudsColored = lerp(_CloudColorDayEdge, _CloudColorDayMain , clouds) * clouds;
Add some color by lerping two colors over the clouds value, multiply by the clouds to cut them and see the sky.
Do the same for night colours, then lerp these together just like the sky gradient, using the Directional Light Y value
float cloudsNegative = 1 - clouds;
Finish up by multiplying the sun/moon, and sky gradients with the inverted value of the clouds, so you can colour the clouds, and the clouds can block the sun/moon.
Then add all the components together
Shader Code (With a few extra options): PasteBin Link
(Image)Material Settings for skybox in the top gif
Note: If you are in Gamma colouspace these settings will be too bright , so you'll need to tweak them, they are made for Linear colorspace
Noise Textures:
Base Noise
Distort
Secondary Noise
Have fun!
|