【UE】Gerstner Waves 水体模拟 4 :[颜色构成阶段3、4] - 实现NAP+CDOM

前文

继续!

理论基础

Babin et al. (2003)

在海洋光学中,水体的总 吸收系数 a ( λ ) a(\lambda) a(λ) 和总 散射系数 b ( λ ) b(\lambda) b(λ) 遵循加性原则:

  • a ( λ ) = a w ( λ ) + a ϕ ( λ ) + a N A P ( λ ) + a C D O M ( λ ) a(\lambda) = a_w(\lambda) + a_{\phi}(\lambda) + a_{NAP}(\lambda) + a_{CDOM}(\lambda) a(λ)=aw(λ)+aϕ(λ)+aNAP(λ)+aCDOM(λ)
  • b ( λ ) = b w ( λ ) + b ϕ ( λ ) + b N A P ( λ ) b(\lambda) = b_w(\lambda) + b_{\phi}(\lambda) + b_{NAP}(\lambda) b(λ)=bw(λ)+bϕ(λ)+bNAP(λ) 👈(CDOM没有散射)

当前我们已经完成了前两项(纯水 w w w 与浮游植物 ϕ \phi ϕ),现在我们将补齐NAP(非藻类颗粒物/泥沙)CDOM(有色溶解有机物/黄化物质)


调研调研开始调研

我发现大家不爱看这部分,确实之前废话太多了。随性写的长了就很容易反复讲某些东西,用AI润色又一股AI味。

因此我这里一口气列举了选用的数据来源选用公式,然后把快乐连连看 则单独放到下面的章节。

并且在连连看的时候附上不那么繁琐的简单注释。


一、 NAP 与 CDOM 的物理光学建模

同样的,以下注明了100m的,即基于 100m 尺度计算,最终输出给 UE 时除以 10000 转换回 cm。

  • 文献多以m为单位
  • UE 单位为uu,1uu=1cm

1. NAP (非藻类颗粒物 / 泥沙)

NAP的"浊度"是缩短水下消光距离(Extinction)的主要因素。光线被泥沙颗粒高频弹射,很难深入水底,因此水体变得不透明且呈现极高的浑浊亮度。

1. 吸收模型

参考 Babin et al. (2003),NAP 的吸收模型遵循指数衰减公式:
a n a p ( λ ) = N A P ⋅ a n a p ∗ ( λ 0 ) ⋅ e − S n a p ( λ − λ 0 ) a_{nap}(\lambda) = NAP \cdot a^*{nap}(\lambda_0) \cdot e^{-S{nap}(\lambda - \lambda_0)} anap(λ)=NAP⋅anap∗(λ0)⋅e−Snap(λ−λ0)

  • 参考波长 λ 0 \lambda_0 λ0 :学术界标准取 440 nm 440 \text{ nm} 440 nm(蓝光)。
  • 光谱斜率 S n a p S_{nap} Snap :决定吸收曲线向红光衰减的速度。平均值为 0.0123 nm − 1 0.0123 \text{ nm}^{-1} 0.0123 nm−1
  • 质量特定吸收系数 a n a p ∗ ( 440 ) a^*_{nap}(440) anap∗(440) :这是决定泥沙颜色参数。Babin & Stramski (2004) 测量了全球不同矿物的 a ∗ a^* a∗ 值,以它为参考例如:
    • 高岭土 (Kaolinite) :吸收极低(约 0.01 m 2 / g 0.01 \text{ m}^2/\text{g} 0.01 m2/g),水体呈现高亮灰白色(如冰川融水)。
    • 富铁矿物 (如撒哈拉沙尘) :蓝光吸收极强(可达 0.12 + m 2 / g 0.12+ \text{ m}^2/\text{g} 0.12+ m2/g),水体呈现黄褐色/红褐色(如黄河水)。
    • 在 Shader 中,我们将此参数暴露为 NAP_Specific_Absorption_440nm,可以直接输入真实测定值,更改水体的地质特征。
2. 散射模型

矿物颗粒由于折射率( 1.15 ∼ 1.20 1.15 \sim 1.20 1.15∼1.20 相对于水)远高于藻类,且多为不透明实体,属于极其高效的米氏散射体。参考 Bowers and Binding (2006),泥沙的散射遵循幂律公式:
b n a p ( λ ) = N A P ⋅ b n a p ∗ ( λ 0 ) ⋅ ( λ 0 λ ) n b_{nap}(\lambda) = NAP \cdot b^*_{nap}(\lambda_0) \cdot \left(\frac{\lambda_0}{\lambda}\right)^n bnap(λ)=NAP⋅bnap∗(λ0)⋅(λλ0)n

在 550nm(绿光)处,其特定散射系数 b n a p ∗ b^*_{nap} bnap∗ 均值高达 0.51 m 2 / g 0.51 \text{ m}^2/\text{g} 0.51 m2/g。这意味着哪怕 1 立方米水中只有 1 克泥沙,也能产生极高的单次散射反照率。


2. CDOM (有色溶解有机物 / 黄化物质)

CDOM 通常来源于植物腐烂分解的腐殖酸和单宁酸。

1. 散射模型

无散射 :作为溶解在水中的有机大分子,CDOM 最核心的光学特性是散射贡献为零 ( b c d o m = 0 b_{cdom} = 0 bcdom=0)。就像水中的一层有色滤镜。

2. 吸收模型

根据 Bricaud et al. (1981) 的研究,CDOM 的吸收光谱同样遵循指数衰减,但对短波(蓝光)的吸收极其剧烈(光谱斜率约 0.014 nm − 1 0.014 \text{ nm}^{-1} 0.014 nm−1)。

当高浓度的 CDOM 配合 NAP 时,NAP 负责将光强力散射回水面,而 CDOM 在光线穿梭中将蓝光消耗殆尽。最终逃逸出水面的只剩饱满的黄红光。


二、 Delta-Eddington近似

在极高浓度下,物理算出的总衰减系数极大,且单颗泥沙的前向散射极强(相函数不对称因子 g ≈ 0.85 g \approx 0.85 g≈0.85)。此时,UE5 的 Single Layer Water 底层着色器会因为 *简化的单次散射 *而导致水体渲染成死黑。

看看被Epic大佬优化到极致的 SingleLayerWaterShading.usf

hlsl 复制代码
// 1. 光学厚度与透射率
const float3 OpticalDepth = ExtinctionCoeff * BehindWaterDeltaDepth;
float3 Transmittance = exp(-OpticalDepth);

// 2. 单次散射积分公式
float3 SafeScatteringAmount = saturate(ScatteringCoeff * (1.0f - Transmittance) / ExtinctionCoeffSafe);

// 3. 结合相函数计算最终亮度
DirLightPhaseValue = SchlickPhase(PhaseG, dot(-ResolvedView.DirectionalLightDirection.xyz, UnderWaterRayDir));
float3 IncomingLuminance = (AmbScattLuminance + SunScattLuminance * LightFunctionColor ...);
float3 ScatteredLuminance = IncomingLuminance * SafeScatteringAmount;

它假设光线进入水体后,只经过一次散射就直接进入眼睛。它没有考虑光线在水分子或杂质之间多次弹跳后再进入眼睛的情况。

比如 NAP = 20, PhaseG = 0.85 ,代入 Epic 的公式:

  1. Transmittance 瞬间衰减至 ≈ 0 \approx 0 ≈0。积分项 SafeScatteringAmount 退化为 b c \frac{b}{c} cb(单次散射反照率 ω 0 \omega_0 ω0)。
  2. 直射光计算 SchlickPhase(0.85, 背向) 时,因为光线被极度推向水底,返回摄像机的后向散射值趋近于 0
  3. 最终结果,ScatteredLuminance = 0 × ω 0 0 \times \omega_0 0×ω0 =

在现实中,冲向水底的光会发生成百上千次弹射(多重散射),最终大量光线会掉头出水。但 SLW 为了实时性能,只求解单次散射解析积分,彻底丢失了这部分能量。

当然我们也不可能计算真正的多重散射

这样的话,光线 每次 弹射都需要对整个 4 π 4\pi 4π 球面立体角做极度昂贵的积分。

所以这里需要补偿丢失的能量:

极度浑浊且极度前向散射( g g g 很大)的水体,在光学宏观表现上,等效于一个不那么浑浊且低不对称度( g ∗ g^* g∗ 较小)的水体。

引入了辐射传输方程求解中的 Delta-Eddington 近似 (Joseph et al., 1976)。利用相似性缩放(辐射传输)降低 G 值补偿掉丢失的高阶散射能量。


制作

进入到喜闻乐见的环节了。

现在我们制作函数:

MF_Lambda

  • RGB对应波长(nm)

MF_Water_Pure

MF_Water_Phyto

  • Chlorophyll: 叶绿素-a 浓度。范围: 0.02 ~ 25.0,默认: 0 ,单位: mg/m^3
    0 不能Pow,理论上应该 if ,不过可以用max限制最小值。
  • PhaseG: 海藻相函数不对称因子。范围: 0.85 ~ 0.95,默认: 0.924。
  • Scattering_Slope: 散射光谱斜率,一般情况下为常量1,不过生物这种事很难说。范围: 0.5 ~ 1.5,默认: 1.0。

MF_Water_NAP

  • Concentration: 泥沙质量浓度。范围: 0.0 ~ 50.0+,默认: 0.0。单位: g/m^3。
  • PhaseG: 泥沙相函数不对称因子。范围: 0.80 ~ 0.90,默认: 0.85。
  • Specific_Absorption_440nm: 泥沙特定质量吸收系数(放大100倍)。决定地质颜色,高岭土约1.0,富铁土约12.0,欧洲均值 4.1。
  • Spectral_Slope: 泥沙吸收光谱斜率。范围: 0.011 ~ 0.015,默认: 0.0123。

MF_Water_CDOM

  • Absorption_440nm: CDOM 吸收系数(放大100倍)。代表溶解物浓度。纯水为 0,清澈大洋约 2.0,河口/黑水河可达 50.0+。
  • Spectral_Slope: CDOM 吸收光谱斜率。吃掉蓝光的速度。范围: 0.013 ~ 0.018,默认: 0.014。

MF_Water_IOPs

为了完美接收前面 4 个模块相加后的总和,并执行 Delta-Eddington 多重散射补偿,函数需要以下4个输入:

  1. Total_Absorption_100m (v3) 水体总吸收系数:

    将纯水、浮游植物、泥沙、CDOM 这 4 个模块输出的 Absorption_100mAdd 节点全部相加,连入此引脚。

  2. Total_Water_Scattering_100m (v3) 仅纯水分子产生的瑞利散射:

    直接连接 MF_Water_Pure 模块输出的 Water_Scattering_100m

  3. Total_Particle_Scattering_100m (v3) 颗粒物(海藻 + 泥沙)产生的米氏散射总和:

    MF_Water_PhytoMF_Water_NAP 输出的 Particle_Scattering_100mAdd 节点相加,连入此引脚。

  4. Total_Particle_Scattering_times_G_100m (v3) 颗粒物散射乘以各自 G 值的能量总和(用于在内部计算加权平均 G 值):

    MF_Water_PhytoMF_Water_NAP 输出的 Particle_Scattering_times_G_100mAdd 节点相加,连入此引脚。

组合在一起

测试

只需要做简单的加法,输入分别是:

  • 吸收 (A) : Pure + Phyto + NAP + CDOM
  • 纯水散射 (B_w) : Pure
  • 颗粒物散射 (B_p) : Phyto + NAP
  • 颗粒物G权重 (B_p * G) : Phyto + NAP

测试之后,把参数放到之前做的材质参数集

材质参数集没办法设置参数范围之类的,调起来很麻烦,都完成了再丢进去

封装

然后全部封装为函数待用。

预览




切大号看看,先来个渤海

再来个黄河

最后来个马尔代夫


预告

现在波也有了,颜色也有了,下一篇就是制作水线水下效果了!

相关推荐
Yasin Chen4 小时前
Unity TMP_SDF 分析(五)片元着色器
unity·游戏引擎·着色器
chudonghao5 小时前
[UE学习笔记][基于源码] 运行时网格 PMC / DMC / RMC
笔记·学习·ue5
吴梓穆7 小时前
UE5 C++ 使C++创建动画蓝图
开发语言·c++·ue5
吴梓穆10 小时前
UE5 动画状态机
ue5
电子云与长程纠缠19 小时前
UE5 两种方式解决Decal Actor贴花拉伸问题
学习·ue5·游戏引擎
妙为20 小时前
UE5中武器未跟随角色
ue5·gas·gameplay
平行云1 天前
虚拟直播混合式2D/3D应用程序实时云渲染推流解决方案
linux·unity·云原生·ue5·图形渲染·实时云渲染·像素流送
曼巴UE51 天前
UE 客户端 需要的网络同步概念总结
网络·c++·ue5
AIminminHu2 天前
OpenGL渲染与几何内核那点事-项目实践理论补充(一-3-(10):从“像素画师”到“硅基神明”:一个CAD开发者穿越GPU着色器管线的十年进化史)
着色器·片段着色器·顶点着色器·opengl 1.0·顶点/片段着色器