定向光和天空盒

光照设计:识别场景所需的光源是照明设计和实施的关键初始步骤。

一般游戏设计中最常使用的四种光照:

  • 自然采光: 通常是太阳或月亮。
  • 动态照明: 模仿场景中特定的真实光源——例如路灯或汽车前灯。
  • 关键照明: 这是一种没有可识别光源的光,用于照亮场景中的焦点对象(类似于舞台上的聚光灯效果)。
  • 环境光(在 Unity 中也称为漫反射环境光):整个场景环境漫反射光照,不确定来自某个具体光源。

在室外场景中,可以使用 定向光 Directional Light 和 天空盒 Sky Box 快速营造出场景环境和气氛,甚至是昼夜转换效果,简单而重要,是构建室外场景需要首先考虑的两个关键元素。

1. 定向光 Directional Light

定向光对于在场景中创建诸如阳光之类的效果很有用。在许多方面都像太阳一样,定向光可以被认为是无限远的遥远光源。

特点:

  • 会随着场景创建被自动加入;
  • 位置、远近不影响效果;
  • 旋转定向光,可以产生昼夜转换效果;
  • 如果选择天空盒作为环境光源,环境光将根据其颜色发生变化。
  • Lighting 窗口中 Environment - Sun Source ,默认值为 None ,则假定场景中最亮的定向光代表太阳。当Skybox 材质是 Procedural Skybox 时, 也可以指定任意定向光对象为太阳。

2. 天空盒

2.1 天空背景 Sky

Unity 中可以使用天空盒设置天空背景,天空背景会在摄像机在第一帧之前渲染。

用途:

  1. 这种类型的背景极大地有利于 3D 游戏和应用程序,因为它提供了深度感并使环境看起来比实际大得多。
  2. 天空本身可以包含任何东西,例如云、山、建筑物和其他无法到达的物体,以创造遥远的三维环境的错觉。
  3. 场景中的环境光 Ambient lighting 也是由天空背景产生。

2.2 天空盒 Sky Box

Unity 中的天空背景是使用一种称为天空盒的特殊材质创建的。

天空盒是在每个面上具有不同纹理的立方体。

当您使用天空盒渲染天空时,Unity 基本上将您的场景放置在天空盒立方体内。

Unity 首先渲染立方体,因此天空渲染在场景中其他任何物体的后面。

注意:

  • 高清渲染管线 (HDRP)不支持天空盒材质,而是包含多个天空生成解决方案。
  • HDRP 包括它自己的使用Volume 系统的天空解决方案。每个体积都可以包含一个覆盖来指定要绘制的天空类型。每个摄影机在影响它的每个体积的天空设置之间进行插值并绘制结果

使用天空盒步骤:

  1. 创建天空盒材质;
  2. 将天空盒材质应用到 Lighting-Environment-SkyBox Material 上;
  3. 配置其他相关属性

注意:

  • 天空盒的变化可能会更加戏剧化,但也不要忘记调整您的定向光配置。对Color属性的微小更改可能会对场景的气氛产生微妙但有效的影响。

2.3 SkyBox Shaders

Unity 中,可以将专门的 天空盒着色器 SkyBox Shader,应用到创建天空盒的

SkyBox Shaders 共有四种,可以分为两大类:

  1. 使用纹理 Textured:

    • 6 Sided 六面:
      从六个单独的纹理生成天空盒。每个纹理代表沿特定世界轴的天空视图。为了说明这一点,想想场景就像在一个立方体里面。每个纹理代表立方体的一个内部面,所有六个组合起来创建一个无缝的环境。

    • Cubemap 立方体贴图:
      从单个Cubemap Asset生成天空盒。
    • Panoramic 全景:
      将单个 Texture 球形包裹在场景

  2. 不使用纹理:
    • Procedural 程序生成:
      不需要任何输入纹理,而是纯粹从材质中设置的属性生成天空盒

3. 昼夜更替效果实现

3.1 创建时间显示UI

  • 打开 TutorialScene_Lighting_Indoor 场景
  • 在场景中加入 Text-TextMeshPro,并将其定位到右上角,宽高设置为:200*50,字体设置为45
  • 场景中创建空对象,添加下面脚本作为组件
public class TimeController : MonoBehaviour
{[SerializeField]private float timeMultiplier;[SerializeField]private float startHour;[SerializeField]private TextMeshProUGUI timeText;private DateTime currentTime;[SerializeField]private float sunriseHour;[SerializeField]private float sunsetHour;void Start(){currentTime = DateTime.Now.Date + TimeSpan.FromHours(startHour);sunriseTime = TimeSpan.FromHours(sunriseHour);sunsetTime = TimeSpan.FromHours(sunsetHour); }void Update(){UpdateTimeOfDay();}private void UpdateTimeOfDay(){ currentTime = currentTime.AddSeconds(Time.deltaTime*timeMultiplier);if (timeText != null) { timeText.text = currentTime.ToString("HH:mm");}}
}

3.2 让定向光随时间旋转

为代码添加定向光随时间旋转功能:

public class TimeController : MonoBehaviour
{[SerializeField]private float timeMultiplier;[SerializeField]private float startHour;[SerializeField]private TextMeshProUGUI timeText;private DateTime currentTime;[SerializeField]private Light sunLight;[SerializeField]private float sunriseHour;[SerializeField]private float sunsetHour;private TimeSpan sunriseTime;private TimeSpan sunsetTime;void Start(){currentTime = DateTime.Now.Date + TimeSpan.FromHours(startHour);sunriseTime = TimeSpan.FromHours(sunriseHour);sunsetTime = TimeSpan.FromHours(sunsetHour); }// Update is called once per framevoid Update(){UpdateTimeOfDay();RotateSunLight();}private void UpdateTimeOfDay(){ currentTime = currentTime.AddSeconds(Time.deltaTime*timeMultiplier);if (timeText != null) { timeText.text = currentTime.ToString("HH:mm");}}private void RotateSunLight() {float sunLightRotation;if (currentTime.TimeOfDay > sunriseTime && currentTime.TimeOfDay < sunsetTime){TimeSpan sunriseToSunsetDuration = CalculateTimeDifference(sunriseTime, sunsetTime);TimeSpan timSinceSunrise = CalculateTimeDifference(sunriseTime, currentTime.TimeOfDay);double percentage = timSinceSunrise.TotalMinutes / sunriseToSunsetDuration.TotalMinutes;sunLightRotation = Mathf.Lerp(0, 180, (float)percentage);}else{TimeSpan sunsetToSunriseDuration  = CalculateTimeDifference(sunsetTime, sunriseTime);TimeSpan timeSinceSunset = CalculateTimeDifference(sunsetTime, currentTime.TimeOfDay);double percentage = timeSinceSunset.TotalMinutes / sunsetToSunriseDuration.TotalMinutes;sunLightRotation = Mathf.Lerp(180,360,(float)percentage);}sunLight.transform.rotation=Quaternion.AngleAxis(sunLightRotation,Vector3.right);}private TimeSpan CalculateTimeDifference(TimeSpan fromTime, TimeSpan toTime){ TimeSpan diff = toTime - fromTime;if (diff.TotalSeconds < 0) {diff += TimeSpan.FromHours(24);}return diff;}
}

3.3 自动打开关闭路灯

  • 场景中添加路灯预制件,并为其光源子对象添加 tag :StreetLampLight
  • 更改代码如下,增加自动开关路灯功能
public class TimeController : MonoBehaviour
{[SerializeField]private bool streetLampLightEnabled;[SerializeField]private float timeMultiplier;[SerializeField]private float startHour;[SerializeField]private TextMeshProUGUI timeText;private DateTime currentTime;[SerializeField]private Light sunLight;[SerializeField]private float sunriseHour;[SerializeField]private float sunsetHour;private TimeSpan sunriseTime;private TimeSpan sunsetTime;void Start(){currentTime = DateTime.Now.Date + TimeSpan.FromHours(startHour);sunriseTime = TimeSpan.FromHours(sunriseHour);sunsetTime = TimeSpan.FromHours(sunsetHour); }// Update is called once per framevoid Update(){UpdateTimeOfDay();RotateSunLight();}private void UpdateTimeOfDay(){ currentTime = currentTime.AddSeconds(Time.deltaTime*timeMultiplier);if (timeText != null) { timeText.text = currentTime.ToString("HH:mm");}}private void RotateSunLight() {float sunLightRotation;if (currentTime.TimeOfDay > sunriseTime && currentTime.TimeOfDay < sunsetTime){TimeSpan sunriseToSunsetDuration = CalculateTimeDifference(sunriseTime, sunsetTime);TimeSpan timSinceSunrise = CalculateTimeDifference(sunriseTime, currentTime.TimeOfDay);double percentage = timSinceSunrise.TotalMinutes / sunriseToSunsetDuration.TotalMinutes;sunLightRotation = Mathf.Lerp(0, 180, (float)percentage);if (streetLampLightEnabled) {GameObject[] streetLamps = GameObject.FindGameObjectsWithTag("StreetLampLight");foreach (GameObject streetLamp in streetLamps) {Light streetLampLight = streetLamp.GetComponent<Light>();if (streetLampLight != null){streetLampLight.enabled = false;}}}}else{TimeSpan sunsetToSunriseDuration  = CalculateTimeDifference(sunsetTime, sunriseTime);TimeSpan timeSinceSunset = CalculateTimeDifference(sunsetTime, currentTime.TimeOfDay);double percentage = timeSinceSunset.TotalMinutes / sunsetToSunriseDuration.TotalMinutes;sunLightRotation = Mathf.Lerp(180,360,(float)percentage);if (streetLampLightEnabled){GameObject[] streetLamps = GameObject.FindGameObjectsWithTag("StreetLampLight");foreach (GameObject streetLamp in streetLamps){Light streetLampLight = streetLamp.GetComponent<Light>();if (streetLampLight != null){streetLampLight.enabled = true;}}}}sunLight.transform.rotation=Quaternion.AngleAxis(sunLightRotation,Vector3.right);}private TimeSpan CalculateTimeDifference(TimeSpan fromTime, TimeSpan toTime){ TimeSpan diff = toTime - fromTime;if (diff.TotalSeconds < 0) {diff += TimeSpan.FromHours(24);}return diff;}}

//获取灯光组件
                    //还得在孩子身上获取,不然获取不到
                    Light streetLampLight = streetLamp.GetComponentInChildren<Light>();

参考资料:

  • CC Lighting 官方教程
  • 天空 Unity 官方文档
  • youtube - Unity 3D 场景昼夜转换
  • youtube - Unity 3D 场景昼夜转换
  • youtube - Unity 2D 场景昼夜转换

定向光和天空盒(个人笔记)相关推荐

  1. Vulkan开发实战详解 学习笔记 - 环境光 散射光 镜面光 定向光

    环境光 添加LightManagerLightManager类,此类的主要功能为管理光照的相关参数.首先给出此类的声明,具体代码如下: #ifndef VULKANEXBASE_LIGHTMANAGE ...

  2. Opengl-阴影(分为定向光的和点光源的)

    前言 我们模拟了光照,发现真的很厉害,加上天空盒子,再加上反射感觉很逼真,但是看着看着你会发现..不对,没影子.是的,光和影分不开的,有光的地方就会有影子,这才是真实的道理.怎么模拟影子呢?这就要用到 ...

  3. OpenGL定向光的投影阴影

    OpenGL定向光的投影阴影 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include "GL/ ...

  4. 基于结构光的三维测量学习笔记

    基于结构光的三维测量学习笔记 1.几种比较成熟的方法 1.1飞行时间发 原理:通过直接测量光传播的时间,确定物体的面型.发射脉冲信号,接受发射回的光,计算距离. 精度:毫米级 优点:原理简单,可避免阴 ...

  5. qt opengl 环境光、散射光、高光、定向光与每片无渲染

    球是学习光照的很好参照物,也是因为如此上一篇更新了一个球的文章.这章利用上一章的成果,学习opengl中的各种光照效果以及在每片元渲染.本章主要介绍在qt中如何实现这些,将这些效果集成到qt的开发生态 ...

  6. run命令 uboot_华为光猫HG8245H救砖笔记⑥逆向UBoot恢复海思命令行

    前文中虽然成功的运行了UBoot,但是因为内核损坏,依然无法正常启动.想要用UBoot刷写Flash,就必须进入UBoot的命令行模式,一般UBoot在引导过程中,会有短暂的时间让用户按下某些指定的按 ...

  7. UE4 如何根据定向光朝向、和自定义修改天空颜色的技巧

    1.新建关卡,并拖放一个天空到关卡中.BP_Sky_Sphere 是引擎自带的天空. 2.添加定向光源 3.将定向光源绑定到天空 4.根据太阳朝向修改天空颜色 5.根据太阳朝向更改天空颜色复选框,我们 ...

  8. UE风格化场景练习笔记Day1

    今天要开启一个新项目,学习UE风格化场景的全流程制作,预计工作周期是一个月,开一个学习笔记记录一下我的进度和遇到的问题,方便之后回顾知识点和总结心得,同时也给初学者们提供一个全流程的学习教程. 在这个 ...

  9. Unity-技术美术 199-208

    199 - 光照简介 Demo项目资源:迅雷云盘 提取码:7ca4 视频系列地址:白熊游戏-chutianbo的个人空间-白熊游戏-chutianbo个人主页-哔哩哔哩视频 Unity 技术美术入门系 ...

最新文章

  1. 来看看BAT在AR领域的布局,你给打几分?
  2. 价值1.4万元的课程讲义开源,fast.ai发布新书源代码,登GitHub趋势榜第一
  3. cmos 和 bios中断大全
  4. 【Network Security!】认识进程与端口
  5. 有勇气的牛排 --- 安卓
  6. 用 Arthas “庖丁解牛”
  7. How org unit id and type is determined in Genil
  8. 相比学习好的学生,老师最喜欢努力认真学习的学生
  9. 网络采集库NCrawler
  10. 二十五、MongoDB 索引 和 explain 的使用
  11. ftk学习记(消息框篇)
  12. OpenResty(nginx)操作mysql的初步应用
  13. ARP欺骗***技术及防护
  14. Leetcode 刷题笔记(三十) ——动态规划篇之子序列问题:回文
  15. 华为ensp模拟器 三层交换机
  16. 30天自制操作系统第一天
  17. 0316复利和单利计算更新4
  18. 百度ai智能写作工具-百度ai自动写文章
  19. Android 源码结构分析
  20. 易语言路由器服务器,无线路由器一键设置工具,制作过程,成品。

热门文章

  1. scala:查询圆周率pi
  2. 《监控视频异常检测: 综述》王志国, 章毓晋笔记
  3. c++简易病毒(附代码)
  4. Docker 拉取镜像及标签 pull | tag
  5. python绝对方向角度值_哪个选项是turtle绘图中角度坐标系的绝对0度方向?
  6. Hexo博客配置SSL证书
  7. 基于虚拟仪器的电磁阀综合特性系统设计
  8. 韩国 naver web网页版第三方登录 naver网页登录
  9. 北京工业大学2019年第八届暑期科技夏令营全记录 (计算机专业)
  10. 模拟弹子台球--java多线程应用