本笔记仅为个人的理解,如果有误欢迎指出
A Pipeline for Authored Structural Damage 一个可人工设计的结构破坏管线
Authored Structural Damage :人工的结构破坏,指的是美工手工制作的被破坏结构的细节,比如断肢的残面,建筑被破坏后暴露的钢筋之类的。
为了表现角色和建筑的破坏效果,传统的方式是使用贴花(decal)技术,比如弹痕。但是这种技术表现不了结构变化类型的破坏,比如断肢,身体的孔洞,建筑被轰炸后造成的孔洞之类的。
本文则介绍一套制作这种破坏效果的管线(或者说流程)
这套管线需要满足三个需求:
1,对美术人员友好:这个管线不能给美术增加额外的复杂性,也不能干扰或限制美工的创作。
2,灵活性:在当个物体上的任意位置添加任意数量的损伤区域
3,渲染效率:效率要好
主要难点:
本文实现这种破坏效果是通过替换破坏部位到指定位置的网格 来展现,那这个管线最难点就是如何隐藏物体原本的网格,提供一个干净的替换区域给替换网格。
目前有三种办法去实现隐藏网格:
1,将可被替换的部位做成独立的部位,这样就可以在运行的时候选择性的显示或者隐藏,这个办法的弊端在于对于美工拆部位独立建模会不方便,在渲染的时候不同的模型也会增加DrawCall的调用。
2,通过压缩骨骼,使得三角形在某一点附近退化,从而达到隐藏网格的目的。这种办法高效也容易实现,但只适用于蒙皮网格,适用的部位也相当有限。
3,通过渲染时Alpah测试剔除需要隐藏像素。(《求生之路2》中使用的方式)
这种方法能够提供像素级别精准的网格隐藏能力,但是存在以下缺点
1)渲染效率问题,像素是在Alpah测试中被隐藏的,被隐藏的像素其实还是执行了像素着色器的执行,这个具体可以了解渲染管线流程。
2)某些GPU架构上(PlayStation3),Alpha测试会干扰Early-Z的优化,从而降低深度测试的效率。
3)为了实现这个效果,该方法在着色器中需要为每一个破坏区域计算一个参数化椭球,但是在实际中,这种椭球是有数量限制的。
4)切割边界对美术那边设计会有限制,需要考虑如何填充这个切面

最终文章所构建的流程被分为三个阶段:
1,创作阶段:
美术人员通过给网格涂色标记当前部位可以被隐藏。
2,管线阶段:
管线对被标记的网格分配一个唯一的ID。
2,运行阶段:
程序员通过这个ID在顶点着色器中通过压缩网格的方式隐藏网格,再渲染用于替换的部位。
创作阶段细节:
这个阶段主要是决定什么破坏会出现在物体上,每个区域都会分配一个唯一的颜色,被标记的区域表示当前破坏效果需要处理的网格,如下图


管线阶段细节:
管线阶段是链接美术和程序,这个阶段将美术标记的区域转为能够在运行阶段使用的数据。
1,检查网格是否包含顶点颜色信息 ,实现这个管线的网格都必须保存顶点颜色的数据。
2,逐顶点对顶点中的颜色和表中的颜色匹配
3,从表中匹配到颜色后分配这个颜色对应的ColorID
这个ColorID就是后续运行阶段需要使用的数据。
运行阶段细节:
在这阶段就是控制物体损伤的表现了,在运行时中会有个数据保存当前物体的损伤状态,里面记录着每个ColorID是否需要改为显示破坏部位。
在渲染的顶点着色器阶段的通过读取顶点数据里的ColorID,用这个ColorID查询对应的损伤状态从而判断当前的渲染是要渲染为正常部位还是破坏部位。
文章中如果当前的顶点是要显示破坏部位的话,那就会在顶点着色器中把该顶点的坐标改为(0,0,0)
代码示例如下:


checkBit 判断是否是在破坏的区域,代码给出的方案是在浮点数平台下的判断,因为某些平台不支持适用的整数运算判断,这段代码只要起到能判断是不是在破坏区域的作用即可。如果是在破坏区域内,则把当前顶点坐标归零。
最后则是渲染替换部位,这里有两种方法:
1,在主物体的同一个drawCall中渲染。
这个方法没有看明白,文章中解释替换部位与主体部位顶点部位需要一一对应,那这个可能的实现办法应该是替换部位的网格和正常部位的网格在切断面的顶点上是相同的,那渲染这整个物体的时候替换部位和正常部位都会在同一个drawCall送到GPU去处理,再在顶点着色器中判断需要渲染哪一个部位,隐藏另一个。
2,在单独的drawCall中渲染替换的部位。
这个比较直接,替换组件另外再走一遍渲染流程,顶点着色器中如果这个部位是破坏区域内就渲染这个替换组件
LOD方面:
现在一般模型都有做LOD的功能,那么对应的LOD模型美术人员都要做相应的染色处理,替换部位与LOD模型也要做好适配。
参考资料: