Unity程序化天空盒开发记录

前言

想着做好看的场景 好看的天空是第一步 首先来做一个程序化动态天空盒

由于笔者自己还是初学者 所以在制作过程中也做了很多参考 部分自己编写的效果并不那么完备 也有设计不周全的部分在 后期改进可以二编

找个基础

首先拿到unity内置的Procedure skybox查看一下实现原理 

https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/DefaultResourcesExtra/Skybox-Procedural.shader

可以看到在官方给出的源码中 已经包括大气的散射和太阳的绘制 这是一个很好的开始 可以该基础上进行改动

首先看到在shader中存在三种模式 没有太阳、简单的太阳、高质量太阳 既然目标是好看的天空 直接选取_SUNDISK_HIGH_QUALITY相关代码

  #pragma multi_compile_local _SUNDISK_NONE _SUNDISK_SIMPLE _SUNDISK_HIGH_QUALITY

展示一下官方给的天空盒效果 

天空的颜色(白天)

天空盒颜色的绘制大体分为两部分 即天空和地面  在这个shader里面可以看到具体的颜色计算在vert函数中进行 而在frag函数中lerp一下划定天空和地面的范围(通过天空盒的法线方向)

//vert

OUT.groundColor = _Exposure * (cIn + COLOR_2_LINEAR(_GroundColor) * cOut);

OUT.skyColor    = _Exposure * (cIn * getRayleighPhase(_WorldSpaceLightPos0.xyz, -eyeRay));

//frag

col = lerp(IN.skyColor, IN.groundColor, saturate(y));//天空和地面的颜色范围控制

在对官方天空盒进行调参时发现了改变天空颜色时出现了类似黎明/黄昏的效果(注意参数栏中的颜色)

所以直接定义了一个参数a来控制

float a=1-abs(dot(_WorldSpaceLightPos0.xyz,float3(0,1,0)));

可以看到a的作用是光线越接近水平 a越接近于1 也就是模拟出了黄昏/黎明的效果
天空的颜色(夜晚)

在原shader中当y轴光线方向向上即夜晚时整个天空和地面是不接收光照的 但这明显不符合现实 为了让夜晚的天空不是一片纯黑 需要引入“月光”的照明

这里仿照白天的颜色渲染调整参数即可(注意 大气厚度和地面颜色是通用的)

加上一个太阳

太阳直接采用官方代码的写法就可以了

//太阳范围的定义
half calcSunAttenuation(half3 lightPos, half3 ray,half SizeConvergence,half size){
    half focusedEyeCos = pow(saturate(dot(lightPos, ray)), SizeConvergence);//兰伯特...穿个马甲我就不认识你了吗
    return getMiePhase(-focusedEyeCos, focusedEyeCos * focusedEyeCos,size);}
//ray
 half3 ray = normalize(IN.vertex.xyz);//法线方向的反方向

一通看发现 这不就是个兰伯特吗 也是遇上老熟人了

当然还要记得乘上太阳的颜色

OUT.sunColor = kHDSundiskIntensityFactor * saturate(cOut) * _LightColor0.xyz / lightColorIntensity; 

注意这里太阳的颜色并不是用户传入的 而是通过计算得出的 

加上一个月亮

月亮其实是最后写的 那个贴图的uv想想就头疼

【Unity URP】Unity Procedural Skybox Shader - Sand and Foam - FlowingCrescent's Blog

参照的是这位大佬的写法

//shader
float2 moonUV =mul(float3(-IN.texcoord.x,-IN.texcoord.y,IN.texcoord.z),_LToW)*9;
moonUV+=float2(0.5,0.5);
half3 moonCol=tex2D(_MoonTex,moonUV).rgb;

//C#
material.SetMatrix("_LToW",this.transform.worldToLocalMatrix);

找了个月亮贴图一采样还挺像那么回事

这里一定要注意了 找的这个贴图模式记得改成clamp 边框不能有白边

看时间长了总感觉不对味 感觉月亮扁扁的 没有“皎洁”的感觉 (月亮长这样 估计没有嫦娥奔月的故事了)

于是又给加了一圈柔光 这下高兴了:

这么多的星星!

做星星又开始找参考了 又说实时生成噪声的 有说SD拿个噪声图色阶处理一下遮罩的

我都试了...放在电脑上效果都很奇怪 这个实时生成的“星星”静态很不错 但是一旦视角动起来会剧烈闪动 sd做的图放到unity里面能看到有一部分的星星并不是完美的小圆点 而是矩形的(应该是我的噪声图不好加上分辨率的问题)

做了一下午 最后决定ps手点了 然后放到SD里面tilling一下也是张不错的星星遮罩

星星扰动的噪声图给放到了star图的g通道 减少采样开销

最后的效果(uv流动稍微快了点 这样看的清楚)

漂亮的银河

银河希望的效果是在深夜时出现,黎明之前就要全部消失 利用方向光的角度进行控制

half b=smoothstep(0.6,1,max(0,dot(_WorldSpaceLightPos0.xyz,float3(0,-1,0))));

银河的噪声扰动还没做 这里就是放了一张贴图(后续扰动补上)

云朵(卷云+积云)

云朵的制作思路参考这位大佬

风格化的动态天空球 – WalkingFat

做了两层云相对慢速旋转 最终效果还不错

最终效果

需要改进的地方 慢慢填坑吧

添加镜头光晕

星河扰动

云的出现以及消散(SDF)

depthfade

月相的变化

日月与地平线的depthfade

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值