【程序化天空盒】过程记录01:日月 天空渐变 大气散射

news2024/11/28 8:31:17

1 日月 SunAndMoon

昼夜的话肯定少不了太阳和月亮,太阳和月亮实现的道理是一样的,只不过是月亮比太阳多了一个需要控制月牙程度(or添加贴图)的细节~

1.1 Sun

太阳的话很简单,直接在shader里实现一个太阳跟随平行光旋转而旋转的样子就行。实现这个效果需要用到Unity内置变量_WorldSpaceLightPos0获取当前平行光的方向,不要被这个参数名字“lightPos”迷惑了,它实际上就是一个归一化的vector(w=0)。接着用Unity内置的distance函数计算当前uv坐标(i.uv.xyz)到上面那个的距离。

如何理解这个“距离”呢?——我们再来复习一遍图形学基础吧:学习齐次坐标时讲到“点与向量的区别”时,例如vector(a, b, c, 0)和point(a, b, c, 1),我们可以把vector看作这个point挪向无穷远处位置。行,那么我们再来看看这个distance计算出来的结果的几何意义是不是就十分简单了——uv坐标越靠近,代表离这个无穷远处的点越近,于是结果越小。

  • 我们需要的是一个实心圆(模拟“日月”),如果只将distance的结果与_SunColor相乘并作为片元着色器的结果输出,主要代码及效果如下:
float sun = distance(i.uv.xyz, _WorldSpaceLightPos0);
...
fixed4 col = sun * _SunColor;

  • 场景中越靠近远处的“太阳”位置越黑,想要实现一个实心圆就很简单了,补充后代码及效果如下:
float sun = distance(i.uv.xyz, _WorldSpaceLightPos0);
float sunDis = 1 - sun / _sunRadius;
...
fixed4 col = sunDis * _SunColor;

 为了实现控制最大化,加入了_sunRadius参数以控制“太阳”的大小,选择除法的原因也很简单——太阳越大意味着白色部分越大,意味着disatance()函数计算结果的权重更加分散,所以是除法。

  • 到了这一步你会发现,上图还是缺点什么!

【第一】边界有些模糊,我们想实现的效果是轮廓明显的“日月”,这是因为边界的sunDis数值不够大,导致_sunColor相乘混合的颜色“淡”。如何处理?——简单,直接乘上个合适的倍数就行!

【第二】原有的网格不见了,给人一种黑色“笼罩”整个天空盒的错觉。看到这里你似乎会觉得疑惑:“网格不见了”啥意思?我来举个例子,下面是我将sunDis值分别设置为1,0,-1的效果:

2和3看似都是黑色,其实还是有差别的,他会掩盖网格。而且这个sunDis系数最后是跟类型为Color的_SunColor变量相乘,参考光照计算模型,这里理应将该系数也限制在(0, 1),这里用saturate()就行!

考虑了以上两点后最终的代码:

float sun = distance(i.uv.xyz, _WorldSpaceLightPos0);
float sunDis = saturate((1 - sun / _sunRadius) * 50);
...
fixed4 col = sunDis * _SunColor;

最终效果:

1.2 Moon 

太阳做完了,到了月亮部分,它俩一个在光的正方向(太阳)一个在反方向(月亮),这个不难理解吧!所以,关于跟随平行光方向的部分,设置跟Sun一样,只是多了一个负号。

这里我计划实现两种月亮的方法,一种是贴上一个真实的月亮图片,另一个是做一个简单的可以控制的月牙形状。

第一种:月牙

另外,由于月亮是有月牙的~就用两个圆相减的形式做出月牙的效果,相减效果采用给uv.x一个偏移值_CrescentOffset的方法实现的。同样,这里也需要注意只要涉及相减的需要给数值规范到(0, 1)才能确保效果的正确。

下面是月亮部分的代码:

//2.Add Moon
float moon = distance(i.uv.xyz, -_WorldSpaceLightPos0);
float moonDis = saturate((1 - moon / _MoonRadius) * 50);
float crescent = distance(float3(i.uv.x + _CrescentOffset, i.uv.yz), -_WorldSpaceLightPos0);
float crescentDis = saturate((1 - crescent / _MoonRadius) * 50);
moonDis = saturate(moonDis - crescentDis);
fixed4 moonN = moonDis * _MoonColor;

最终效果:

第二种:月亮贴图

贴图主要问题是解决UV坐标系变换问题,因为如果继续用原始的改变光照方向后月亮贴图会变形的问题,我们希望每个角度贴图形状都是圆圆的(参考日常生活中每个角度的月亮都是圆圆的),那么我们就需要一个建立一个4x4的坐标系变换矩阵去实现。

问题又来了:Unity自带的变换矩阵unity_WorldToLight对于平行光是行不通的,只适用于point/spot/烘焙光,所以这里我们需要自己脚本实现变换矩阵。这里我们不难想到shadowmap里也需要求得光源空间的变换矩阵,可以参考我记录的GAMES202作业1中CalcLightMVP()的实现过程去写出这个变换矩阵,还可以跟着这一篇用Unity实现Shadow Map的博客实现这个变换矩阵,道理都是相通的。

更方便的还可以用Unity自带的transform的worldToLocalMatrix获得当前对象的世界空间到local空间的变换矩阵,给场景中的平行光一个子Camera再获取一下这个变换矩阵就行(后面会补充完整脚本内容和shader部分的内容,这里就先放一个效果)。

效果如下,加上了一点后面会做的渐变天空效果:

2 天空主体色 Gradient Sky

1.0版本

完成了日月交替的部分只能说才实现了一小部分,而且天空很单调,为了实现更加酷炫的效果,加点渐变天空颜色。说起渐变,要用上lerp()了!分别给白天天空和晚上天空赋予颜色——基于UV坐标的y 轴值来做天空颜色的渐变,记住还是需要saturate()!最后根据uv坐标(i.uv.y)判断何时昼夜交替。

// 3.gradient sky
fixed3 gradientDay = lerp(_DayBottomColor, _DayTopColor, saturate(i.uv.y));
fixed3 gradientNight = lerp(_NightBottomColor, _NightTopColor, saturate(i.uv.y));
fixed3 gradientSky = lerp(gradientNight, gradientDay, saturate(_WorldSpaceLightPos0.y));

2.0版本

上面的渐变天空简单的lerp做的,很枯燥。参考程序化天空盒实现昼夜变换,我们也来这位大佬的构思思路,做一次分析(毕竟是作品集,所有过程自己实现一遍最好啦!),也天空变化归纳了出来:

参考他提出的思路,地平线渐变用worldPos.y控制,但天空的主体颜色用光方的z和y共同控制,关于天空主体色我的理解:

(纠正一下,感觉早晨不是supper blue而是一种偏绿色的蓝色?颜色可以自行调整的)

即从早晨开始,早晨(非常蓝)-->中午(正常蓝)-->傍晚(紫色)-->深夜(深蓝色),其中,y控制着白天和晚上,z控制白天三种颜色变换、晚上三种颜色交替

白天:

上述思路对应的理解代码为,

// 早午过渡
col = lerp(morningCol, noonCol, smoothstep(0,0.5,z));
// 再把上面的当作午的,进行午傍晚过渡
lerp(col, nightfallCol, smoothstep(0.5,1,z));

同理晚上:

// 早晚过渡
col = lerp(morningCol, nightCol, smoothstep(0,0.5,z));
// 再把上面的当作晚的,进行晚和傍晚的过渡
lerp(col, nightfallCol, smoothstep(0.5,1,z));

再优化一下:我想要清晨和傍晚的颜色持续的少一点,白天的天蓝色维持的久一点,这样就需要更改参数,索性直接多给两个参数,来调节一天内清晨和傍晚的持续时间,最终关于天空颜色早晚变化的参数如下:

3 地平线渐变

跟参考文章不太一样的是,我把渐变天空分为两个部分:半天空渐变色+范围变化的Bloom,虽然这样比较麻烦(叠加了三层orz),但原神有些画面它就是三种颜色叠加的效果,例如下图傍晚的天空:

原神的傍晚天空

索性直接拆成三块做。 

3.1 半天空渐变

半天空渐变色有4种颜色,4个颜色变化的时间刚好跟天空主题渐变色对应,

1 晚上:深蓝色+淡色地平线

早晨:浅蓝色+淡色地平线

中午:天蓝色+浅蓝地平线

傍晚:紫色+淡黄色地平线

由于这个是跟主色叠加,是不是应该在天空主体渐变的基础上修改,达到天空主色渐变的感觉:

好,说做就做,以早晨为例,还需要能控制渐变程度等,最后的参数如下:

整个天空颜色很接近了(斗胆),现在就差地平线附近的Bloom。

3.2 范围变化的Bloom

(做了一下午了,起来活动一下继续,orz,,)

再继续观察:

早->午:红色(小)-->黄色(大)-->白色(小)

傍晚->晚上:黄色(大)-->橙黄色(超大)-->黄色(小)

(补充:既然节点4Mie散射开始,那我们把大部分白色的Bloom都交给Mie散射,假设整个发光到节点4就宣告结束。) 

【空缺了一部分思路,这里做得比较着急没有记录,放个对比图吧之后补充】

日出日落配上天空颜色变化:

emmm配色什么的感觉挺脏的,然后bloom那里需要给参数调整的,做的时候随便选的,先继续进行下面的步骤,最后再优化。 

接下来是加上云、和星空银河,放在下一篇文章吧。

我上面实现渐变天空选择的颜色还是照抄参考里的配色。但是!我认为一个优秀的天空盒,配色一定是要有讲究的!配色的实现方法打算参考这篇文章里提到的将配色数据做成数组形式,像动画关键帧那样呈现出来的方法。

3 大气散射

做的时候没有记录过程,作品搞完后会回来补上。

参考

这里是我搜刮遍了各种网站找到的实现动态天空盒的文章,自己在做的过程中也参考了很多,这里罗列出来希望对看到这篇文章的你有所帮助:

风格化的动态天空球 – WalkingFat

Unity日夜循环天空球(Procedural Skybox) - 知乎

Making a Stylized Skybox Shader

Unity 卡通渲染 程序化天空盒 - 知乎

【unity URP】昼夜循环天空球 - 知乎

程序化天空盒实现昼夜变换 - 知乎 (zhihu.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/335742.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu18.04中安装Pycharm2023

下载安装包访问 Jetbrains官方网站 下载 Linux的安装包点击 Download 后下载文件名为 pycharm-community-2022.3.2.tar.gz解压安装启动终端,cd Downloads 进入Downloads目录(默认下载路径)解压压缩包 tar -xzvf pycharm-community-2020.2.2.t…

【Nacos】Nacos配置中心客户端启动源码分析

SpringCloud项目启动过程中会解析bootstrop.properties、bootstrap.yaml配置文件,启动父容器,在子容器启动过程中会加入PropertySourceBootstrapConfiguration来读取配置中心的配置。 PropertySourceBootstrapConfiguration#initialize PropertySource…

实现复选框全选和全不选的切换

今天,复看了一下JS的菜鸟教程,发现评论里面都是精华呀!! 看到函数这一节,发现就复选框的全选和全不选功能展开了讨论。我感觉挺有意思的,尝试实现了一下。 1. 全选、全不选,两个按钮&#xff…

CentOS8联网部署Ceph-Quincy集群

文章目录1.环境准备1.1 关闭selinux1.2 关闭防火墙1.3 配置免密1.4 设置yum源1.5 安装依赖1.6 设置时间同步1.7 安装docker2.安装Ceph2.1 安装cephadm2.2 部署ceph集群2.3 集群添加节点2.4 部署MON2.5 部署OSD2.6 部署MGR2.7 集群状态3.问题3.1 failed to retrieve runc versio…

腾讯云对象存储+企业网盘 打通数据链“最后一公里

对云厂商和企业用户来说,随着数据规模的快速增长,企业除了对存储功能和性能的要求不断增加,也越来越注重数据分发的效率。在传统数据分发的过程中,数据管理员往往需要先在存储桶下载对应的客户方案/交付资料,再使用微信…

【前言】嵌入式系统简介

随手拍拍💁‍♂️📷 日期: 2022.12.01 地点: 杭州 介绍: 2022.11.30下午两点时,杭州下了一场特别大的雪。隔天的12月路过食堂时,边上的井盖上发现了这个小雪人。此时边上的雪已经融化殆尽,只有这个雪人依旧维持着原状⛄…

【FLASH存储器系列十九】固态硬盘掉电后如何恢复掉电前状态?

掉电分两种,一种是正常掉电,另一种是异常掉电。不管是哪种原因导致的掉电,我们都希望,重新上电后,SSD都需要能从掉电中恢复过来,继续正常工作。正常掉电恢复,这个好理解,主机通知SSD…

Linux(centOS7)虚拟机中配置 vim

👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

数据库实践LAB大纲 05 JDBC 连接

概述 Java DataBase Connectivity,Java 数据库连接 执行SQL的Java API 为多种关系型数据提供统一访问 FUNCTION 建立与数据库的连接向数据库发送 SQL 语句处理从数据库返回的结果 四种常见JDBC驱动程序 JDBC-ODBC Bridge drivernative-API, partly Java driver…

LeetCode题目笔记——1.两数之和

文章目录题目描述题目难度——简单方法一:暴力代码/Python方法二:哈希表代码/Python代码/C总结题目描述 这道题可以说是力扣的入坑题了,很经典,好像还是面试的经典题。 给定一个整数数组 nums 和一个整数目标值 target&#xff0c…

Zookeeper技术认知

目录概念理解工作原理文件系统通知系统zookeeper在kakfa中的作用概念理解 Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的Apache项目。 工作原理 Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题&…

Android IO 框架 Okio 的实现原理,到底哪里 OK?

本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问。 前言 大家好,我是小彭。 今天,我们来讨论一个 Square 开源的 I/O 框架 Okio,我们最开始接触到 Okio 框架还是源于 Square 家的 OkHttp 网络…

C4--Vivado添加列表中不存在的FLash器件2023-02-10

以华邦SPI FLASH W25Q128JVEIQ为例进行说明。(其他Flash添加步骤一致) 1.本地vivado安装目录D:\Softwares\xlinx_tools\Vivado\2020.2\data\xicom下,找到xicom_cfgmem_part_table.csv文件,这个表与vivado hardware manager中的器…

pixhawk2.4.8-APM固件-MP地面站配置过程记录

目录一、硬件准备二、APM固件、MP地面站下载三、地面站配置1 刷固件2 机架选择3 加速度计校准4 指南针校准5 遥控器校准6 飞行模式7 紧急断电&无头模式8 基础参数设置9 电流计校准10 电调校准11 起飞前检查(每一项都非常重要)12 飞行经验四、遇到的问…

同步线程

↵ 由于这节内容资料比较少,所以以下内容总结自Qt官方文献,在文章最后会给出相应链接。 线程的目的是允许并行运行,但有时线程必须停止等待其他线程。例如,如果两个线程尝试访问同一个变量,这样的话结果是未定义的。强…

【0基础学爬虫】爬虫基础之爬虫的基本介绍

大数据时代,各行各业对数据采集的需求日益增多,网络爬虫的运用也更为广泛,越来越多的人开始学习网络爬虫这项技术,K哥爬虫此前已经推出不少爬虫进阶、逆向相关文章,为实现从易到难全方位覆盖,特设【0基础学…

Jmeter in Linux - 在Linux系统使用Jmeter的坑

Jmeter in Linux - 在Linux系统使用Jmeter的坑Jmeter in Linux系列目录:o.a.j.JMeter: Error in NonGUIDriver起因错误分析:解决方案:解析日志没有展示请求和响应信息起因解决方案:注意Jmeter in Linux系列目录: 【如…

ChatGPT 爆火!谷歌、微软、百度纷纷下场?

近日,智能聊天机器人ChatGPT的爆火引发了国内外网友的热烈讨论,上线两个月后,用户数量达到1亿。2月8日下午,巨大的访问量让系统一度崩溃。 服务重新开放后,我向ChatGPT询问了如何快速扩容,它显然是知道云端…

CSS从入门到精通专栏简介

先让我们来欣赏几个精美的网站: Matt Brett - Freelance Web Designer and WordPress Expert ‎2022 Year in Review • Letterboxd NIO蔚来汽车官方网站 小米官网 Silk – Interactive Generative Art 大屏数据可视化 你是否也有过这样的“烦恼”: * …

(C00034)基于Springboot+html前后端分离技术的宿舍管理系统-有文档

基于Springboothtml技术的宿舍管理系统-有文档项目简介项目获取开发环境项目技术运行截图项目简介 基于Springboothtml的前后端分离技术的宿舍管理系统项目为了方便对学生宿舍进行管理而设计,分为后勤、宿管、学生三种用户,后勤对整体宿舍进行管理、宿管…