制作一个风格化程序化天空球Shader-24小时实时
TA图形学渲染引擎Shader材质球 9075 3
实名

通过了实名认证的内容创造者

发布于 2020-10-19 17:55:39

您需要 登录 才可以下载或查看,没有账号?注册

x
制作一个风格化程序化天空球Shader                              
                                                                                                                    作者 Minions Art                        
   image.png

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
1.gif


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!






评分

参与人数 3元素币 +22 活跃度 +53 展开 理由
lzf123qw + 15 【喜欢】看到这么好的帖如同回到初恋的年代!
胖纸Jeremy... + 22 + 22 这就很棒!!!
微凉. + 16 【给力】阅贴无数,楼主最强!

查看全部评分

本帖被以下画板推荐:

还没有设置签名!您可以在此展示你的链接,或者个人主页!
使用道具 <
ABC05  发表于 2020-11-18 08:57:51  
2#
谢谢分享
回复 收起回复
使用道具
digua139  发表于 2021-4-8 09:41:05  
3#
这次来看看东西好不好
回复 收起回复
使用道具
呜啦啦  发表于 2021-6-10 17:25:44  
4#
有没有哪位大佬整理一下啊
回复 收起回复
使用道具
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表