Unity昼夜变化效果

Unity动态昼夜变化Lightmap+天空盒

最近一直在对旧项目的场景进行重新烘焙,于是顺便做了个昼夜变化的效果。没有用实时光,而是用了Lightmap烘焙+天空盒。
上面的视频,前面一段是4个时间点的瞬间切换,后面一段是4个时间点的过渡切换效果。
简单分享一下思路:
1、需要的东西:场景烘焙lightmap,天空盒。

2、需要多少个时间点,就需要烘焙多少套lightmap和多少套天空盒。我这个例子是把一天的时间分为了早上、中午、傍晚、晚上,所以是需要4套lightmap和4个天空盒。

3、瞬间切换很简单,直接把想要的lightmap数组赋给LightmapSettings.lightmaps,把想要的skybox材质球赋予给RenderSettings.skybox就行了。

4、渐变过渡切换,就不能直接赋值给setting了,因为赋值的地方只有一个,不能做到过渡的效果。

5、lightmap的渐变过渡,我使用的方法是自己写shader实现lightmap叠加,取得当前MeshRenderer的Lightmap坐标,计算出lightmap的uv:
o.uvLM = v.uv2.xyunity_LightmapST.xy + unity_LightmapST.zw;
然后通过当前MeshRenderer的lightmapIndex,找到对应的Lightmap贴图,然后赋给材质球。
最后,在正常颜色上面叠加一层lightmap的颜色:
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 lm1 = DecodeLightmap (tex2D(_LightMap1,i.uvLM));
col.rgb
=lm1;
这样做完之后,我们就可以自己控制Lightmap的显示了。既然能支持一张lightmap,同理也就可以支持2张叠加了。然后在中间加多一个插值让他变化,就是很简单的事情了。

6、天空盒的渐变过渡,其实做法差不多。虽然RenderSettings.skybox只能设置一个材质球,但既然他是材质球,我们就可以想办法了。
Unity自带的skybox的shader,平常我们用到的最多的是6 Sided和Cubemap两种。出于在代码操作上赋值的方便,我觉得用Cubemap会好一些,毕竟只需要设置一次,6Sided要设置6张图。
于是我们就可以拿自带的Skybox/Cubemap做一个小修改,加多一个Cubemap贴图赋值,然后加多一个插值的变化值,然后给RenderSettings.skybox赋予我们的材质球,控制Cubemap的替换和插值就可以做到过滤效果了。

7、接下来考虑的是性能问题。天空盒的替换这个性能消耗不大,不过我还是做了2种shader,一种是单纯支持一个天空球的,一种是支持2个天空球切换的。当需要渐变过渡的时候,替换成支持2个的,做动画效果,等过渡完成后,改回只支持一个的,避免无谓的GPU计算第二个天空盒的采样。

8、Lightmap的性能问题,我同样也是做了2种shader,一种是支持单个lightmap的,一种是支持2个lightmap切换的。当平时没有渐变切换时,用只支持一个lightmap的,这时候的渲染压力其实和正常烘焙lightmap时理论上是一样的。当需要渐变时,替换shader,这一步可能会有一定的消耗。这要视乎场景里面需要这样操作的物体多不多。

我视频里面的场景,是我已经在线上运营的实际游戏的场景,有接近30万面和接近一千个物体对象,数量应该算比较多。不过从性能分析看,也就是在刚切换shader时读取材质球参数时会稍微飙到20多毫秒,其他时候都是

### 实现 Unity 中 UI 的昼夜变化效果 为了实现在 Unity 中的 UI 昼夜变化效果,可以采用一种高效且资源友好的方法。这种方法不仅能够节省内存空间,还能提供较为真实的光影过渡体验。 #### 使用渐变纹理模拟光照变化 通过创建两张不同色调的渐变纹理分别代表白天和夜晚的颜色分布,在运行时根据时间比例混合这两张图片来动态改变UI背景颜色[^2]: ```csharp using UnityEngine; using UnityEngine.UI; public class DayNightCycle : MonoBehaviour { public Image uiBackground; // 绑定到UI图像组件 public Texture2D dayTexture, nightTexture; // 白天和黑夜的渐变纹理 private float timeOfDay = 0f; // 时间范围从0(午夜)至1(正午) void Update() { // 更新一天中的时间进度 (此处仅为示例逻辑) timeOfDay += Time.deltaTime / 86400f % 1f; Color[] colorsDay = GetColorsFromTexture(dayTexture); Color[] colorsNight = GetColorsFromTexture(nightTexture); int width = Mathf.Max(colorsDay.Length, colorsNight.Length); for(int i=0;i<width;i++) { float ratio = Mathf.Lerp(timeOfDay * 2, (timeOfDay + 0.5f) * 2, i/(float)(width-1)); ratio = Mathf.Clamp(ratio, 0, 1); uiBackground.color = Color.Lerp(colorsDay[i%colorsDay.Length], colorsNight[i%colorsNight.Length], ratio); } } Color[] GetColorsFromTexture(Texture2D texture){ return texture.GetPixels(); } } ``` 此脚本将两个纹理文件作为输入参数,并基于当前游戏世界的时间计算出合适的色彩混合比率应用于UI元素上。需要注意的是这段代码只是一个概念性的实现框架,实际应用中可能还需要调整细节以适应具体项目需求。 另外,对于更高级的需求,比如希望加入云层移动或者其他环境因素的影响,则可以通过编写自定义着色器(shader)进一步增强视觉表现力。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值