Unity Crest Ocean System源码如何阅读与?
摘要:1.前言 crest是一款海洋模拟插件,其开源的基础版本位于github(https:github.comwave-harmoniccrest),年末清下Flag。 1.1.对比Boat Attack 之前基于BoatAttack(
1.前言
crest是一款海洋模拟插件,其开源的基础版本位于github(https://github.com/wave-harmonic/crest),年末清下Flag。
1.1.对比Boat Attack
之前基于BoatAttack(https://github.com/Unity-Technologies/BoatAttack)做过一套水体方案,对比下两者。
- Boat Attack Water
BoatAttack没有水下渲染,无吃水线
Lod只有mesh做了远处简化处理,没有系统级Lod的设计。
水体交互通过叠加Gerstner波形实现,但有叠加上限限制。
无FFT波形,只有Gerstner波。
无船只水体交互,只有深度差泡沫效果,海浪是粒子特效。
- Crest
基础版本无吃水线,但有完善水下渲染实现。
完整的大规模海面LOD方案,大量ComputeShader处理,但也提供常规VF Shader兼容性支持,需手动开关。
波形模拟做了封装处理,可自由切换FFT与Gerstner,可自定义某块区域用哪一种。
查询接口做了封装处理,一套接口可以支持异步和非异步。
船只与水体可配置波浪等交互,海浪是GPU Instancing的面片特效。
1.2 插件结构
以github上开源的基础版本为例,Examples.unity场景有所有效果演示
核心逻辑在OceanRenderer中,但要让海洋正常运行需要一定层级结构配置,例如参考BoatScene.unity
Shader部分较为清晰,主要在Ocean.shader中,包含折射、反射、泡沫、SSS等基础的海水实现。
展开OceanRenderer的Debug菜单后,可显示Tile、线框等。
2.Tile & ShiftingOrigin
2.1 Tile拼接
在OceanRenderer脚本处勾选showOceanTileGameObjects即可显示隐藏的Chunk对象
具体代码在OceanBuilder的GenerateMesh中。
所有Tile都是独立Mesh,替换为Unlit shader查看,会发现有接缝:
Shader中通过SnapAndTransitionVertLayout函数,进行坐标偏移修复,解决接缝问题。
unlit shader:
切回带Snap函数的shader:
但感觉实际上也可以用类似geo mipmap的做法,离线生成一张带顶点缝合的大型Mesh,
实时跟着Camera走(缺点是不好按Tile优化):
2.2 ShiftingOrigin实现原理
当实际坐标大于某阈值时,直接让transform.position减去一定偏移量,实现拉回,从而避免
因浮点数偏差而导致模型出现撕扯问题。
维基百科(http://wiki.unity3d.com/index.php/Floating_Origin)
插件实现:
public class ShiftingOrigin : CustomMonoBehaviour
{
...
void FixedUpdate()
{
var newOrigin = Vector3.zero;
if (Mathf.Abs(transform.position.x) > _threshold) ...
if (Mathf.Abs(transform.position.y) > _threshold) ...
if (Mathf.Abs(transform.position.z) > _threshold) ...
if (newOrigin != Vector3.zero)
{
MoveOrigin(newOrigin);
}
}
}
2.3 Texel对齐
为了避免偏移时无法对齐mesh网格,实际还会进行一步Texel偏移操作。
即用最小lod网格的尺寸进行坐标量化,避免shader通过世界坐标采样噪声贴图时,
因为浮点数采样到完全不同的中间位置,造成抖动感。
