【UE】Gerstner Waves 水体模拟 5 :完善水体光学 【高光、粗糙度、折射、斯涅尔窗】

在这里插入图片描述

开始准备制作水线效果,那基本就意味着相机一定会贴近水面,并入水下。

一旦观察距离足够近,很多在远景里还能糊弄过去的问题都会立刻暴露出来。
所以这篇文章的目标很明确:
在不依赖硬件光追的前提下,尽可能把单层水在近景和水下视角中的关键光学表现补完整。


一、 基础物理原理

在开始动手之前,我们先回顾一下水体渲染中涉及的基本光学原理:

  • 折射(Refraction): 光线从一种介质斜射入另一种介质时,由于传播速度的改变,会导致传播方向发生偏折。
    现象

  • 光路可逆原理: 在光学中,光路是不区分发射端和接收端的。对于光子而言,从 A 点发射到 B 点接收,其自身经历的时间间隔为零(以光速传播)。在光子的参考系中,发射和接收是瞬时发生的。既然没有“流逝的时间”,也就没有所谓的“前进”或“后退”(费马原理)。因此,光线从 A B → \overrightarrow{AB} AB 还是 B A → \overrightarrow{BA} BA 传播,在时空几何上是完全等价的,我们在计算时不需要对二者做区分。


二、 水面折射(IOR)的实现与修正

在开始阅读前,这里有一个更新的文章:
我在这篇《【UE】[暗黑Shader] 基于 Lumen Surface Cache 实现物理正确的折射 (0成本、不使用光追和屏幕空间)》的文章中,实现了一个使用暗黑Shader实现的折射。

1. 屏幕空间效果的局限性

在不使用硬件光线追踪(Ray Tracing),仅依靠屏幕空间数据的情况下,想要实现完美的折射效果是非常困难的。因此,我们需要提前约法三章,做一些假设和限制:

  • 首先,我们假设水体的整体密度是均匀的

不礼貌的形式:
在这里插入图片描述

  • 其次,我们不考虑倾斜视角下的 屈光 效果。
屈光现象动态 GIF真实照片中的视深关系
折射路径动态焦散视深关系

2. 开启折射效果

在材质的细节面板中勾选 “像素法线偏移”(Pixel Normal Offset)。在不使用光追的情况下,这是实现折射效果最理想的选择(如果使用光追,则直接使用折射率 / IOR)。
在这里插入图片描述

以正常水体为例,其折射率(IOR)约为 1.33
在这里插入图片描述

直接应用后,我们可以看到水体与物体交界处的效果很差,存在明显的断层:
在这里插入图片描述

为了消除这种视觉上的断层,我们需要将靠近交界处的折射率平滑过渡到 1.0(即无折射状态)。

3. 修正折射:基于深度的过渡

在真实情况下,水越浅,光线被折射偏移的距离就越短。
我们可以使用 SceneDepth - PixelDepth 来获取水面到水底的视线方向距离,并将其作为过渡的 Mask。

M a s k = saturate ( SceneDepth − PixelDepth FadeDistance ) Mask = \text{saturate}\left(\frac{\text{SceneDepth} - \text{PixelDepth}}{\text{FadeDistance}}\right) Mask=saturate(FadeDistanceSceneDepthPixelDepth)
在这里插入图片描述
在这里插入图片描述

注意: 单层水(Single Layer Water)使用的是不透明材质,因此常规的 SceneDepth 无法获取到水下的深度。幸运的是,Epic 考虑到了这一点,专门提供了一个 Scene Depth Without Water 节点供我们使用:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

修正后,交界处的效果自然多了:
在这里插入图片描述

4. 修正折射:基于距离的缩放

在使用“像素法线偏移”时,法线提供的偏移量是基于屏幕像素或百分比计算的。当相机拉远时,模型在屏幕上占用的像素减少。如果偏移量不随距离缩减,远处的折射效果看起来会比近处更“剧烈”或更“突兀”。

注意看黄线的范围,折射偏移距离并未随距离变远而缩短:

近距离中距离远距离
近距离中距离远距离

在这里插入图片描述

为了解决这个问题,我们可以用相机到水面的距离(即 PixelDepth)来缩放偏移量:
在这里插入图片描述
当镜头远离时,通过 ReferenceDistance 限制最大偏移量,防止折射扩散到不合理的范围:
在这里插入图片描述

5. 修正折射:合并计算优化

经过上述步骤,我们引入了两个手动的抽象变量。为了更易于控制,我们希望定义一个基于像素单位的值(例如:希望水岸线始终保持 200 个像素的平滑过渡带)。
在这里插入图片描述
利用垂直方向的投影关系,我们可以保证折射过渡带的像素厚度在视觉上保持恒定。
在这里插入图片描述


三、 高光(Specular)与粗糙度(Roughness)的设定

1. 高光参数:0.255

基于折射率计算,水面的高光值可设定为 0.255。这个数值参考了 Epic 官方文档
在这里插入图片描述

该值的计算基于菲涅耳方程,描述了光线在两种介质交界处的反射和折射行为。以空气和水为例,公式如下:

S p e c u l a r = ( ( I O R − I O R a i r ) / ( I O R + I O R a i r ) ) 2 0.08 Specular = \frac{((IOR - IOR_{air}) / (IOR + IOR_{air}))^2}{0.08} Specular=0.08((IORIORair)/(IOR+IORair))2

  • I O R IOR IOR 水的折射率(测量值约为 1.33)。
  • I O R a i r IOR_{air} IORair 空气的折射率(约为 1.0)。如果你制作的是水下物体的材质,这里的 1.0 应该替换为水的折射率 1.33。
  • 0.08: 这是 Epic 设定的一个缩放因子。设定这个因子的目的是为了使折射率为 1.5 的常见电介质,其对应的 Specular 值恰好为 0.5。

拓展:
光是一种电磁波。当光线照射到物体表面时,本质上是电磁波与物体内部电子的相互作用。

  1. 电介质 (Dielectric / 非金属):内部没有自由电子(绝缘体)。当光照射到水、木头、塑料等电介质时,光线可以穿透表面进入内部,发生散射和吸收。最终重新透射出来的光形成了 BaseColor (漫反射)。同时,表面只会发生微弱的反射(约 2% ~ 8%),这就是我们用 IOR 计算出的 Specular (F0)。
  2. 导体 (Conductor / 金属):内部充满自由电子。当光照射到金属上时,电磁波会被自由电子构成的“等离子体海洋”强烈反弹,光线完全无法穿透表面。因此,纯金属没有漫反射(物理上 BaseColor 为纯黑)。金属的颜色完全来自于极高强度的表面镜面反射(Specular/F0 通常高达 50% ~ 100%,且带有颜色,例如黄金反射黄光)。
制作函数 MF_IOR_To_Specular

虽然可以手填0.255,不过我们还是制作一个IOR计算,因为后续所有处于水下的材质都需要用它计算水下正确的高光
在这里插入图片描述
在这里插入图片描述

例如一个在水下的1.5 IOR 的材质(默认1.5)
在这里插入图片描述
假设一半在水下,就这样的效果
在这里插入图片描述

在这里插入图片描述

2. 粗糙度参数:0.02

理论上,在分子层面上由于液体表面张力的作用,水面是绝对光滑的,粗糙度应为 0。我们将粗糙度设定为 0.02,是为了模拟微风引起的极其细碎的毛细波

在图形学中,粗糙度(Roughness)和法线(Normal)在物理意义上是等价的,区别仅在于尺度:

  • 宏观尺度 = 模型顶点起伏
  • 中观尺度 = 法线贴图
  • 微观尺度 = 粗糙度参数

粗糙度可以理解为在统计学上宏观描述这些“亚像素级(Sub-pixel)法线起伏”的参数。

优化技巧: 如果你需要制作 LOD(Level of Detail)来过渡远近海面,或者模拟从海面拉升到高空(如飞机或卫星视角)的效果,可以将波浪的细节表达从法线平滑过渡到粗糙度,这样可以有效避免远处高光走样和闪烁的问题。


四、 水下视觉效果的构建

当相机潜入水下并向上看时,默认情况下,颜色、折射和反射都会出现错误。

这是因为系统使用的是“单层水”(Single Layer Water)着色模型。官方自带的水体系统在水下会使用后期处理材质来模拟水面,因为它将水面捕获为了纹理。这种逻辑仅适用于“相机在空气中看向水面”。
如果按照我们目前 “双面单层水” 的做法,材质会错误地认为这是一个表面朝下的海面,并在其上方执行散射和吸收计算。
为了不将无限的水面捕获为有限分辨率的循环贴图,我们将通过材质逻辑来手动修复这个问题。

首先,将水下的折射率暂时恢复为 1,并将法线也恢复为原始计算的法线(不再乘以 TwoSidedSign 进行反转)。
在这里插入图片描述
在这里插入图片描述

检查水面和水底的反射,确保均显示正常:
在这里插入图片描述
在这里插入图片描述

1. 斯涅尔窗(Snell’s Window)的实现

接下来,我们需要区分水上和水下的透明度,使水面保持透明,而水下呈现不透明的全反射状态
在这里插入图片描述
此时水下是全反射的,我们将在此基础上为向上的视角开启一个“斯涅尔窗”。

1.1 斯涅尔窗的物理原理

当我们身处水下并以一定角度仰望水面时,是看不到水面上方物体的,看到的是水下物体的全反射倒影
在这里插入图片描述

游过泳的人会知道,在水中向上看无法看到完整的天空。这种光学现象被称为斯涅尔窗

斯涅尔窗是指:水下观察者仰望水面时,由于光线的折射,水面上方 180 度的半球视野被压缩成了一个顶角约 97 度(临界角约 48.6 度)的圆形透光“天窗”。当视线超过这个临界角度时,就会发生全反射,水面像镜子一样映射出水底的景象。
在这里插入图片描述

垂直向上看水下实际照片
图1图2

这种临界点的转折非常剧烈,几乎是瞬间从折射变为全反射:
在这里插入图片描述

在平静的水面下,斯涅尔窗的边界异常清晰。黄线内是透光的窗口区域,线外则是池底的反射:
在这里插入图片描述

1.2 斯涅尔窗的材质计算

斯涅尔窗的数学公式如下:
M a s k = { 1 , ∣ N ⃗ ⋅ V ⃗ ∣ ≤ 1 − ( 1 I O R ) 2 0 , ∣ N ⃗ ⋅ V ⃗ ∣ > 1 − ( 1 I O R ) 2 Mask = \begin{cases} 1, & |\vec{N} \cdot \vec{V}| \le \sqrt{1 - \left(\frac{1}{IOR}\right)^2} \\ 0, & |\vec{N} \cdot \vec{V}| > \sqrt{1 - \left(\frac{1}{IOR}\right)^2} \end{cases} Mask= 1,0,N V 1(IOR1)2 N V >1(IOR1)2

转换为 Shader 代码:

return step(1, sqrt(1.0 - pow(dot(normal, view), 2)) * ior);

在材质中使用 If 节点(不连接 ==If 节点性能消耗很低),为水下部分叠加斯涅尔窗的效果:
在这里插入图片描述

最终效果如下,非常接近真实的物理现象:
在这里插入图片描述
在这里插入图片描述

2. 水下折射的处理

在水下,光线是从水进入空气,介质的关系发生了反转:
在这里插入图片描述

因为 180 度的半球视野被压缩到了 97 度的天窗内,折射变形会非常剧烈。
在不使用光追折射的情况下,屏幕空间折射无法完美处理这种极端的变形,不可避免地会产生画面断层。
为了改善这一点,我们可以适当提高空气的 IOR 值,使其接近 1.33,从而平缓水下向上的折射效果。
在这里插入图片描述

3. 水下单层水参数的修正

不能继续假装没看到天是深蓝的了。
由于我们使用了双面材质,引擎会把本不该参与水下处理的空气侧,也按倒挂水面的逻辑去处理。

因此,我们需要将单层水的参数区分为水上和水下两套逻辑:
在这里插入图片描述
在这里插入图片描述

提示: 如果在水下往上看时天空是黑色的,请确保场景中有一个物理天球模型作为背景,而不仅仅依靠大气的 SkyAtmosphere

最终的水下动态效果:
在这里插入图片描述


五、水下扭曲、模糊

别想了,这俩效果是虚构出来、以讹传讹的。

大多数游戏里常见的“水下扭曲”和“水下模糊”,并不是水体本身天然具有的视觉特征,而是长期被误用、并逐渐被默认成“水下感”的虚构表现。
在这里插入图片描述

1. 扭曲并不是典型的水下现象

很多作品会在进入水下后立刻给画面叠加大幅度的屏幕扭曲,仿佛整个世界都在抖动、变形。但严格来说,这种效果的原始意图,其实更接近于:

  • 镜头刚刚穿出水面时,镜片上残留水滴造成的畸变

换句话说,它更像是 “镜头上的水” ,而不是 “在水里看世界”

从物理上说,水在常温常压下几乎不可压缩,密度也非常稳定,因此折射率不会发生剧烈波动。只要水体成分均匀、温度和压力变化不极端,它就不会凭空制造出那种大范围、剧烈起伏的动态扭曲。

  • 0℃ 到 100℃ 的范围内,水的 IOR 变化也依然非常有限,基本不会脱离 1.33 这个量级。
    -
  • 如果环境真的出现了足以引发明显折射率剧变的情况,那通常已经进入了更复杂的物理状态,比如固、液、气三相转化。
    在这里插入图片描述

当然,也存在另一种特殊情况:水体成分发生明显变化
例如 盐度分层悬浮颗粒 浓度差异等,确实可能造成局部折射扰动。
但在本文一开始我们就已经约定:假设水体的整体密度均匀,因此这里不讨论 盐度分层 这类极罕见特殊环境。
至于 悬浮颗粒 浓度,扭曲效果可以做在颗粒的粒子效果上。

2. 模糊也不是水的“固有属性”

再说“模糊”。

很多水下后处理会故意把整个画面糊掉,仿佛只要进入水下,视觉就应该立刻失焦。但实际上,这种效果的来源通常也不是“水本身”,而更像是在模拟:

  • 摄像机从空气进入水中时,焦平面突然改变,镜头系统需要重新自动对焦。

因此,这种模糊更接近于摄像机系统的反应,而不是水体本身的渲染属性。

3. 什么时候可以用?

给整个画面无差别地加上重度扭曲和高斯模糊,那么它更像是一种被行业讹传讹而沿用的视觉惯例,而不是可信的水下物理表现。

除非你明确知道自己在干什么,否则别硬塞这两个效果。

清晰的水下:
在这里插入图片描述
由颗粒产生的浑浊:
在这里插入图片描述


总结

在这里插入图片描述在这里插入图片描述

这一节文章的做法,很多并不是引擎原生支持的“标准水下路径”,而是一种基于双面单层水的人工修正。

下一篇开始制作 后期 材质,实现水线和水下雾。

内容概要:本文围绕直驱式永磁同步电机(PMSM)的矢量控制策略开展系统性研究,基于Simulink平台构建了完整的闭环仿真型,深入探讨了电机在矢量控制下的动态响应特性与控制性能。研究内容涵盖了矢量控制的核心理论与关键技术块,包括Clarke与Park坐标变换、转子磁场定向控制(FOC)、SVPWM调制算法、双闭环PI控制器(电流环与速度环)的设计与参数整定。通过仿真验证了系统在启动、突加负载及变速工况下的稳定性、抗干扰能力与动态调节精度,有效实现了对电机转矩与转速的精确控制。该型不仅有助于深化对PMSM控制机理的理解,也为高性能电机驱动系统的算法开发与工程化应用提供了可靠的仿真验证平台。; 适合人群:具备自动控制原理、电机学基础及Simulink仿真能力的电气工程、自动化、新能源等相关专业的高年级本科生、研究生以及从事电机驱动开发的初级科研人员与工程师。; 使用场景及目标:①作为高校课程设计、毕业设计或科研项目中PMSM控制系统的学习案例,用于掌握矢量控制算法的实现流程与块化设计方法;②帮助研究人员理解各控制环节间的耦合关系,通过调整PI参数优化系统性能,并为进一步研究无传感器控制、弱磁扩速、先进非线性控制策略等高级课题奠定基础; 阅读建议:建议结合经典电机控制教材同步学习,重点剖析各功能块的信号流向与数学原理,亲自动手搭建仿真型,通过改变运行条件和控制器参数观察系统响应变化,从而深入掌握矢量控制系统的动态特性和调试技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UTwelve

感谢您请我喝咖啡!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值