CG技术的转折点,算法TD的觉醒路

CG技术正在面临一场革命性的变化,谁能抓住这次机会,谁就能主导下一代CG世界

如果您想成为一名算法研究方向的TD,那么恭喜您,这篇文章很适合您。我会从最近自主研发曲线场工具的开发经验和马克西姆的经验分享一步一步带您认识节点式可视化编程的魅力。

什么是算法TD呢?简单点说,就是开发艺术家实用工具。比如,建模工具、变形器、绑定系统、特效解算器、材质球和程序纹理等等,我们的目标是开发商业软件没有的功能,解决预置工具无法解决的问题。我们开发的工具必须是高性能的,实用型的。可以对某个问题进行针对型开发,也可以是通用型开发。算法TD是可以和C++专业级研发相媲美的,但它们之间还有一定的区别。

一款先进的工具并不是仅仅能把效果做出来就完事了,它还需具备艺术家友好度,与艺术家之间有亲和力,并且可以让艺术家轻松愉快地高效率完成任务。

当前中国视效领域主要或者说大部分TD是流程类的,很少有算法研发类的TD。这会出现一种现象,国内影视制作流程会日趋完善,但是算法类工具研发这块还存在很大的空白。制作效率是提上去了,但是制作质量和效率却没有跨越式的发展。质量和效率的跨越式发展,就好像原子弹相比普通炸弹。

算法TD的核心就是技术。何为技术,在我看来,就是能高效率高质量完成任务,那它就是技术。站在商业角度看,你能用的东西别人用不了就是你的私有技术,绝对的竞争优势。这就是为什么维塔、工业光魔、MPC等公司每年都会展示他们技术制作幕后花絮的原因。

节点式可视化编程是未来TD的最佳游乐场所,它对于c++纯代码式编程有极大的优势。更高的开发效率,更低的学习成本等等。

现在市面上可以进行可视化编程的软件有很多,但是,能真正用于开发大型高性能工具的很少。Bifrost算是后期之秀,在我看来,现在它是商业中唯一能媲美甚至超越c++传统代码式编程的可视化编程工具。

在详细谈论Bifrost可视化编程之前,我想给您介绍一位精通Bifrsot的高级人才。他是来自日本游戏公司的高级TA(技术美术)MaximeJeanmougin。

MaximeJeanmougin(马克西姆·让穆金)

我叫MaximeJeanmougin,我是一名法国角色技术艺术家,目前在日本大阪的PlatinumGames工作,我在3D领域拥有大约8年的经验,主要从事角色FX方面的工作,还从事程序设计和绑定等其它领域。我在视觉编程方面的旅程始于年的ICE,在Softimage之后转入FabricEngine。在年,我加入了BifrostBeta计划,从此我就获得了很多乐趣。在此博客中,我将尝试分享自那时以来我收集的一些知识。

Maxime用业余时间开发的MJCG2.0工具包

这是我最近使用Bifrost可视化编程开发基于物理的曲线场工具。它完全基于Bifrost强大的场系统,拥有漂亮的外观和强大的功能,并且具有高级的可扩展性,将可控性发挥到了极致,它可以满足初级艺术家和高级艺术家不同用户群体的需求。我敢说,它已经完全碾压所有商业软件中已经存在的曲线场工具。

基本所有的属性已经实现自定义控制,可以构建无限度的自定义场数据

工具已经在Bifrost官方论坛免费分享:

曲线影响工具第一版

曲线影响工具第二版

因为我开发这个曲线场工具的时候,Bifrost发行版还是2.2.0.2版本。然后,我发现在测试版2.2.1.0中会发生崩溃,团队调查后,发现是Bifrost场系统的一个Bug,并且只有在我这个工具里才会出现,但是此时代码已经冻结,马上就要发行了,所以它在2.2.1版本里无法正常使用。很快,团队就发行了2.2.1.1版本,修复了这个Bug。从这件事也可看出团队对用户的重视程度是非常高的。

一位来自英国的PhilRadford艺术家在他的项目中使用这个曲线影响工具后,给我反馈了一个问题。它很难在快速运动的曲线上正确模拟。虽然这个工具支持动态曲线,但是对于极速运动的曲线还是很难得到好的结果。得到Phil的反馈后,我马上就针对这个问题专门开发了一个curves_deformer节点。这个节点能非常完美解决极其快速曲线的问题。但是,它只在Bifrostslack发布,并没有正式公开,因为我想让它更加完美一些。

针对快速运动曲线

这是我最近开发的point_interpolation点插值工具,它现在可以快速插值巨量粒子,并且可以根据粒子密度属性调节插值数量和插值范围以及粒子半径。专为解决大型水、雪和沙子等。等我在项目中对它进行实际的测试应用,完善它后发布。

这是来自印度一家公司的技术总监SachinShrestha开发的羽毛工具,使用MPM真实物理动态模拟以及毛发物理撕碎

Wizix开发的散布工具,底层基于Bifrost节点可视化编程(有趣的是这个工具底层用了MJCG2.0工具包里大量节点,并且有个相关算法是我帮他实现的,我们提倡大家互相帮助学习)

我们这些都是普通的技术人员,不是专业的程序员,我们希望更多的技术爱好者能加入到这个旅途的团队中。现在我刚对数据结构和算法产生了浓厚的兴趣,但也只是一脚刚踩在开发之路的边缘,未来的路还很长很遥远。今后的目标是希望可以轻松地将国内外最先进的论文算法植入到Bifrost里,开发优秀的工具提供给中国的艺术家使用。

节点的世界拥有程序化流程和可视化编程,这是完全不同性质的两个领域。而Bifrost的目标就是将这两个领域的世界互相结合,并将它们的优势发挥到极致。

曲线影响工具开发经验分享

我是主攻FX模块的工具开发,所以更多涉及的是力学和物理动画的研究。

FXTD研究目标主要集中于一个字,场。场是影响物体运动的直接因素,而官方自带的场工具是有限的,无法满足各种复杂的需求,高级FX艺术家需要对场的操作达到炉火纯青的地步,高级FXTD需要能高效率设计和开发各种优秀的场工具。但是,我们并不研究涉及更深层次的复杂算法,因为这些算法是专家、科学家研究的,不是TD研究的范畴。TD所做的最多是将他们发表论文里算法移植到我们的工具里。

一个很重要的优化点,当一个模块的功能效果为0时,一定要用if绕过去,这对于提升性能非常重要。

可视化节点编程和传统代码编程一样,使用的节点越低级,性能越高,可控性越强,缺点是开发难度越大。

曾经有个ScanlineVFX的高级FX艺术家提到为什么不能将逻辑运算都放在一个节点里让用户选择。然后,我们很多人都表示反对,因为这样做会增加编译时间,对人来说是方便了,但是对机器就很麻烦。

开发工具分前端和后端。最好将它们分开变成模块化进行设计而不是混杂在一起,方便后期修改调试。

在后端功能开发的过程中,前端UI就已经基本开发好了

开发工具性能是第一位,所以尽量简洁直接,能不用软件自带的复杂节点就不用,这也是我为啥不推荐在其它现在市面上商业软件里开发工具的原因,它们大部分都是封装好的高级节点,很多不需要的参数也会参与计算,这会增加算法的复杂度。算法的好坏由空间和时间的复杂度决定,大量用预制的高级节点是没法进行优化的。比如大于、小于、等于,这些逻辑判断都放到一个节点里进行选择,表面上看起来很快捷很方便,实际上增加了编译时间,影响性能。

高内聚,低耦合

当我在设计一个功能之前,我会思考,我对这个功能的控制度能达到多少,就是传统代码编程中常说的耦合度,耦合度越低越好。可以自己设计,就尽量不用预制的节点。将你的工具对官方预置节点的依赖性这个因素降到最低。不论是修改还是未来进行升级都有绝对的优势。我很怕我开发的工具里直接使用官方预制的高级节点,比如粒子系统,我希望拥有绝对的控制权限。

编程语言越高级执行效率越低,可控性也越低。

功能模块化设计

交互性不强的功能,尽量并行化设计,也就是区分模块,类似面向对象编程。

自定义数据结构

下面内容很好的向我们解释了Bifrost里数据结构的高级操作。Bifrost节点可视化编程是非常底层和开放的,它的目标是超越传统的c++代码式编程,让艺术家或者TD、TA等技术家轻松地构建自己的大型高性能工具。

下面内容转载马克西姆的博客文章:

欢迎回到博客!自从我写上一篇文章以来已经有很长时间了。今天,我想谈谈Bifrost的另一个高级和隐藏功能:自定义数据结构。这些可以在图形中或化合物内部使用,在涉及可视化编程的复杂方案时,它们非常有用,在这种情况下,仅处理标准数据结构将使事情变得非常混乱。

第1部分:原始数据类型

在进入主题的核心之前,让我们从基础开始。与常见的编程语言一样,Bifrost中的数据类型也基于基本数据类型。这些是人们可以使用的最低级别的数据类型。每种数据类型都有不同的大小,该大小定义了用于存储值的内存量。较大的数据类型允许使用更大范围的值。

在Bifrost中,所有这些类型都列在“SetValueTtype”对话框的“简单”选项卡中,可通过使用value节点进行访问,在右键单击节点的自动类型端口时也可以使用这些类型。以及任何可编辑化合物的端口。

“SetValueTtype”对话框,通常用于设置数据类型

第2部分:数据结构

现在我们已经了解了原始数据类型,我们可以跳到下一个主题并开始讨论“数据结构”。这些是由多种原始数据类型组成的数据类型。最常用的数据结构是float3(通常用作向量或颜色)。它仅由3个浮点数组成。如果使用值节点并将类型设置为Math::float3,然后单击图标,则可以清楚地看到3个结构成员是浮点型。

Math::float3数据结构

在Bifrost中,几乎所有的不是原始类型的数据类型都是数据结构。确定数据类型是否为数据结构的最简单方法是将鼠标悬停在端口上,然后在“图形编辑器”的信息栏中检查数据类型的名称。如果数据类型的名称具有名称空间,则您正在处理数据结构。仅原始类型使用纯名称,当使用具有单个值的值节点时,您还可以检查是否有一个+图标,表示该数据类型具有成员。请注意,还有一些数据结构不会显示成员。对于已编译的硬编码数据类型就是这种情况。

Bifrost中的所有数据类型都可以用于多维数组。当在数组中使用数据类型时,Bifrost将通过在数组标志的尖括号之间封装数据类型的基本名称空间来更改数据类型的名称,如下所示:arrayxxx。如果我们要处理多维数组,那么先前的数据类型也将封装到另一个array中,依此类推。

数组的float和float3数据类型

Bifrost中的大多数标准数据结构都在Math::名称空间下,但是在“SetValueTtype”对话框的“其他”选项卡中也可以找到其他数据结构。GeoLocation是内置的高级数据结构的一个很好的例子。如您所见,单个geoLocation值存储其他数据结构,例如Math::float4和Math::uint4,它还存储数组数据类型,例如arrayfloat和arrayuint,甚至包含一个枚举类型!

GeoLocation数据结构,在哪里找到以及它所拥有的成员

这是可以与值节点一起使用的技巧。您可以使用数据类型的非数组版本来设置其类型,如果您插入与其输入相同数据类型的数组,那么Bifrost的自动循环功能将启动,您可以访问所有数组的数据结构的成员。相反,如果直接在值节点上设置数据类型的数组变量,则+图标消失,并且无法访问其成员,就像在第一个值节点上看到的那样。这就是为什么我建议始终将数据类型的非数组版本与值节点一起使用的原因。

在单值GeoLocation值节点上自动循环播放

第3部分:自定义数据结构

是时候学习如何制作我们自己的自定义数据结构了!但是在此之前,我想谈几件事,关于何时,为何使用它们以及如何最大程度地利用它们。首先让我向您展示我自定义数据结构之一,该结构是我在MJCG化合物2.0中提供的ivy生成器内部使用的。

如您所见,成员很多。在常春藤求解器内部,在每个成长步幅中,所有这些成员都将在几个不同的循环中进行多次迭代。为了使常春藤生长并生成线和叶实例的几何形状,这是必需的。

您能想象如果每个循环中每个成员都有一个端口,该复合物会是什么样?还有所有电线?它将变得一团糟,以至于在可视化编程环境中将变得难以管理。

在这种情况下,这种迭代的化合物上,每个数据结构我只需要使用一个状态端口,这使得该化合物更干净,更高效,因为增加状态/迭代端口的数量会导致很小的性能损失。

通过将每个子数据存储到Amino对象中可以完成相同的操作,但是我喜欢处理数据结构的另一个很棒的功能。在下图中,我展示了如何使用数据结构仅更新一个或几个成员,而保留所有其他成员。

如果仔细看,您会发现主结构的数据是通过output和value之间的连接保留的,只有leaf_size和stem_size插入第二值节点。通过使用这样的结构,我们不必在两个值节点之间连接每个成员。只有与输入连接的成员才会被覆盖,而该结构的所有其他成员保持不变。

如果要使用Amino对象执行相同的操作,则可以肯定以相同的方式在对象内部维护一些子数据,但是对于每个要更新的子数据,我们必须使用set_property或set_geo_property节点,这将产生更混乱的图。由于数据结构的原因,我们不需要处理任何此类问题。我们只是将更新的数据插入到我们想要的成员中。然后瞧瞧,没有混乱,没有性能损失。

仅更新某些数据结构成员,并保留其他成员

聊够了!是时候创建我们自己的了!首先创建一个JSON文件并给它一个适当的名称,然后将其放置在我们的自定义化合物库中。因为您的化合物将保留对该文件名称的引用,所以在开始时正确设置它而不要再次处理它是很重要的。万一您更改其名称,使用数据结构的化合物仍然可以正常加载,但是在Bifrost加载时,它可能会生成少量错误消息,因此请记住这一点。

我们的自定义数据结构的json文件

现在最重要的是自定义数据结构的.json文件的内容。如您所见,这些结构看起来与我们在自定义枚举教程中创建的JSON文件非常相似。不同之处在于,在这里,我们声明的是数据结构而不是枚举。这里有两件重要的事情,因此请务必仔细阅读。

在第13行,我们在此处设置自定义数据结构的名称空间。确保首先正确设置。如果您开始使用图形中的数据结构,后来又决定对其进行更改,则将不会加载所有正在使用它的化合物!而且它也可能阻止Bifrost加载!所以要小心。如果决定以后更改它,则必须编辑所有化合物的JSON文件,并手动替换所有出现的命名空间。

然后,在第16和17行,我们声明数据结构成员的名称和数据类型。在这里,您应该注意正确设置数据类型,否则,在加载Bifrost时,无效成员将不会成为数据结构的一部分。但是,成员比名称空间更安全地进行修改。如果您以后决定更改成员的名称或其数据类型,您的化合物仍然可以正常加载,但是连接到已修改成员的端口将断开连接,而其他成员仍将按预期工作。因此,您只需要重新连接几个端口即可。没什么大不了。

JSON文件准备好后,让我们重新加载Bifrost,获取一个值节点,然后在“SetValueTtype”对话框的“Other”选项卡中找到我们的自定义数据结构。选择类型,单击“确定”,然后瞧瞧!我们已经成功地将自定义数据结构加载到Bifrost中。从现在开始,它可以在从值节点节点到端口的任何地方使用。由于Bifrost的数据类型机制,您的自定义数据结构将可以用作数组。

我们在value节点上的自定义数据结构!

第4部分:结论

因此,本文结束了有关如何在Bifrost中设置自定义数据结构的教程。如果您是初学者,或者对Bifrost的可视化编程不太熟悉,我建议您不要使用它们,因为自定义数据结构将在高级和复杂的场景中使用。在大多数情况下,最好使用标准Amino对象并将数据存储为属性。但是,如果您觉得自己处于中级或高级水平,那么在进行更复杂的编程时,我绝对建议您使用它们!定制数据结构可以通过减少化合物上的端口和电线的数量来使可视化编程更加令人愉悦,并且在仅更新其成员之一时它们也可以派上用场。

Bifrost引擎介绍

Bifrost第一版TD版本基本已经完成,它由包含所有的数学运算,函数,逻辑运算,数据流控制,循环迭代等部分组成,并且提供了从底层构建点线面体积和实例化的低级节点。这些节点是构成Bifrost大楼的基层。可视化编程是围绕着这些低级节点进行设计和开发。

Bifrost是使用LLVM编译的,因此for-each节点和自动循环都将成为TBB并行for循环。因此,这实际上与C++代码使用的东西相同,因此它应该完全一样快。

LLVM是LowLevelVirtualMachine(低级虚拟机)的简称,这个库提供了与编译器相关的支持,可以作为多种语言编译器的后台来使用。能够进行程序语言的编译期优化、链接优化、在线编译优化、代码生成。LLVM的项目是一个模块化和可重复使用的编译器和工具技术的集合。

视觉(基于图形)编程语言是LLVM编译成直接可执行代码的JIT,使用Intel的TBB库在线程之间进行负载均衡(以便使用所有CPU内核)。产生的性能可与表达相同算法的手写和经过专业调优的C++代码相媲美,艺术家和技术主管也可以使用。

Bifrost是Turing的完整语言。使用它编写了整个粒子系统和流体模拟。没有理由不能将其用于光线投射或其它任何用途。鉴于足够的创造力和工作量,Bifrost应该能够做任何事情。

TBB,ThreadBuildingBlocks,线程构建模块,是Intel公司开发的并行编程开发的工具。一个TBB程序根据算法(即高级并行编程范例(又称算法骨架))创建,同步和销毁相关任务的图形。然后根据图形依赖关系执行任务。这种方法将TBB归为一类并行编程技术,旨在使编程与底层计算机的细节脱钩。

TBB实施了偷窃工作,以平衡可用处理核心之间的并行工作负载,从而提高了核心利用率并因此进行了扩展。最初,工作负载在可用处理器内核之间平均分配。如果一个核心完成了工作而其他核心仍然有大量工作要做,那么TBB会将一些工作从繁忙的核心之一重新分配给空闲的核心。这种动态功能使程序员与机器脱钩,从而允许使用该库编写的应用程序进行扩展以利用可用的处理核心,而无需更改源代码或可执行程序文件。

Bifrost数组经过边界检查,而在C++中则不是。这是一个有意识的决定,在C++中,超出范围的读取或写入可能是数据损坏或崩溃,而在Bifrost中,这是经过检查且不允许的。但是,这是有代价的。

Bifrost还积极寻找添加更多高级迭代方式,以表达比for-each更为高级的功能。

可视化编程是Bifrost设计目标的重中之重,截止到目前的版本,在开发优先级里处于第一位。团队进行了大量的改进和优化,还有很多更加先进的可视化编程设计方案正在开发中。这些都是以便更加利于用户使用Bifrost开发工具的流程。

最后,一个新的名为BifrostAddicts的Slack频道于几个月前诞生,它是寻求帮助并分享您的Bifrost实验的好地方。

欢迎加入这个汇聚世界各地的艺术家,技术家和Bifrost官方团队的聊天社区。并且它还有一个中文频道。




转载请注明:http://www.92nongye.com/gaishu/gaishu/204625806.html