HairStrandPlugin的迭代总结 - 纳金网
联系我们

给我们留言

联系我们

地址:福建省晋江市青阳街道洪山路国际工业设计园纳金网

邮箱:info@narkii.com

电话:0595-82682267

(周一到周五, 周六周日休息)

当前位置:主页 > 3D教程 > 图文教程

HairStrandPlugin的迭代总结

来源: 52vr | 责任编辑:传说的落叶 | 发布时间: 2019-06-13 08:17 | 浏览量:
这篇文章介绍了HairStrandPlugin在迭代过程中遇到的一些问题以及思考。
 
背景
 
HairStrandPlugin的1.0版本推出到现在也已经过去快一个月了,在这段期间我也一直在不停调试这个插件以及模拟代码,在此记录一下迭代过程中碰到的一些问题以及对应的思考。
 
代码层次的迭代
 
长度约束(Distance Constraint)逻辑迭代
 
问题描述
 
在参考TressFX的论文和代码过程中,我个人收获很大,但是开源的TressFX似乎还是藏起了一些黑科技。诚然,在系统偏向稳定的情况下,TressFX的效果非常好,而且针对于中短发的约束收敛也做的很不错,此外还使用GPU进行多线程模拟,大大提升了运算效率。
 
但是略有蛋疼的是——在不太稳定的系统下,TressFX针对于长度的收敛还是不够的,在TressFXSimulation.hlsl中能够找到如下代码:
 

[代码]:

01 void ApplyDistanceConstraint(inout float4 pos0, inout float4 pos1, float targetDistance, float stiffness = 1.0)
02 {
03     float3 delta = pos1.xyz - pos0.xyz;
04     float distance = max(length(delta), 1e-7);
05     float stretching = 1 - targetDistance / distance;
06     delta = stretching * delta;
07     float2 multiplier = ConstraintMultiplier(pos0, pos1);
08  
09     pos0.xyz += multiplier[0] * delta * stiffness;
10     pos1.xyz -= multiplier[1] * delta * stiffness;
11 }
 
这意味着在头发高速运动的过程中(例如角色急速冲刺、坠下山崖等),发丝依然有可能被拉长,以下的截图来自原生的TressFX的可执行文件。
 

Technical Artist的不归路 —— HairStrandPlugin的迭代总结

 
可以看到当模型进行位移时,头发还是出现了拉扯的情况。这还仅仅是小位移,联想到古墓丽影中劳拉运动速度比这高的情况还是比较多的,因此大概可以推测还有黑科技没有批露出来。
 
诚然这种状况可以通过调节例如迭代次数、Substeptime来进行改善,但毕竟仅仅是改善而已,无法彻底解决。而且单一的调整上面的数值还会影响整个发丝的质感,工作量还是比较大。
 
插件在《隐龙传:影踪》的实装过程也遇到了这个问题。由于《隐》是一个动作游戏,角色的运动速度有时会很高(例如主角在空中的重下劈速度达到了100m/s),因此在最初的实装中头发不可避免地被拉长了。
 
解决方案
 
最终的解决方案是在进行发丝设计时先离线计算出各个粒子与发根粒子的稳定距离,然后在模拟的过程中检测距离的大小关系。如果距离过大了,则强制将粒子推至稳定距离的位置。
 
这样的方案能够是Iteration数量大大减少,目前来看针对于每根发丝来说只需要进行一次Iteration即可。而且发丝的表现效果也更加稳定,当主角在山崖间快速跳跃的时候发丝也并不会被拉长。
 

Technical Artist的不归路 —— HairStrandPlugin的迭代总结

 
上图是初次实装后的效果,可以看到长度被约束到了一个稳定值(锯齿状的震颤来源于阻尼没有调整好,大家无视即可……)。
 
LOD的实现
 
由于发丝的模型是依照样条曲线来进行动态构建的,因此导致发丝的网格会比较密,这样一来对GPU的消耗就有可能比较大(虽然我知道这个插件主要是CPU杀手……)。
 
因此花了一些精力用于动态LOD的构建了,难度不大也没什么好说的,距离越远则网格越稀疏而已……
 

Technical Artist的不归路 —— HairStrandPlugin的迭代总结

 
发丝插值
 
工具链问题
 
发丝插值是一个很蛋疼的事,而这个蛋疼不是来源自技术而是来源自工具链。
 
由于《隐》的开发团队人数比较少,因此很多时候都只能使用现有的工具来进行开发。由于模型师的习惯,针对于发型的设计是使用Maya的Shave插件,然后直接导出曲线数据,再在UE4中进行导入操作。
 
但是这样一来,发丝与发丝之间的拓扑结构就被破坏了。导出之后的曲线数据不带有“哪三根曲线是在同一个三角面上”的信息,因此原本想好的三角面插值就难以实现了。
 

Technical Artist的不归路 —— HairStrandPlugin的迭代总结

 
这个问题嘛……实际上不隶属与这个插件,难度也不大,但是由于涉及到工具链改变所带来的成本因此暂时就这样搁下了。目前的发丝插值是针对发丝插值总数进行随机的两两发丝配对,然后在渲染的时候在这两根发丝之间进行插值即可。
 
插值发丝的碰撞结算
 
这个问题目前也还没解决。发丝的插值的出现的目的主要是用于解决模拟发束太少而导致发丝稀疏的问题,换句话说,可能针对于类似于马尾之类的简单发型,只需要四五根发丝进行模拟结算,然后在这些发丝之间进行插值即可,这样能够大大节省CPU运算时间。
 
但是这样的潜在问题在于如果这几根发丝之间有一些进行了碰撞结算而其他的没有进行碰撞结算该怎么办?如果直接进行插值的话势必会导致有一些发丝直接进入了碰撞体内,但是如果针对于插值发丝再进行碰撞结算则一来计算量将增大不少,二来只有碰撞结算而无长度约束将导致发丝的极度诡异的状况。
 
目前来看,插件提供的插值功能只适用与单侧马尾这一类走向统一,发束简单的发型。如果日后能够解决三角面插值的问题的话,这个问题也将得到一定程度的解决。
 
线条网格(Line Primitive)
 
不同于三角网格,Line Primitive是用于线条的绘制。随着现在机器性能的提升,大量的Line Primitive也不再是幻想了。
 
在这个迭代后,开发者可以选择是否使用LinePrimitive进行模拟,并且也可以工作正常。但是可以预见的问题是:除非插值发丝的问题得到解决,否则使用LinePrimitive势必带来极高的CPU运算量。
 
或者……如果与TressFX一样,将模拟逻辑写到GPU上,应该也能解决这个问题。
 
质点系统
 
这个东西其实很简单也不需要多说——越靠近发根的粒子质量越大,越远离发根的粒子质量越小。这样一来在进行物理模拟的时候将更加真实。
 
下一步的计划
 
GPU!GPU!GPU!
工具链!工具链!工具链!
GrowMesh的对应逻辑。

相关文章
网友评论

您需要登录后才可以发帖 登录 | 立即注册

关闭

全部评论:0条

推荐
热门