使用曲面细分渲染毛发

original link

几周前,我无意间找到了一篇让很有趣的论文,主要讲述的是使用曲面细分技术去渲染头发,并且是在Direct3D 11类型的GPU上。这是我多年前在曲面细分技术上的实践,那时候我也才刚接触D3D11,当时就在尝试基于曲面细分技术的毛发渲染。那时候,我各种收集和挖掘有关资料,同时也决定将它发布在博客中,说不定会有人对它感兴趣。

在开始之前,我会先简短的对曲面细分进行一个总结,当然了,如果你很了解这部分知识,你可以直接跳过,请随意。

曲面细分 101

曲面细分(tessellation)是Direct3D11和OpenGL4.x的图形API中介绍的新特性。简单的说,曲面细分就是通过某种再分割的形式增加网格的几何体,它可以提高网格的多边形分辨率,可以产生更平滑或者说更多(几何学上的)细节的表面。因为这个技术完全由GPU完成,所以,这既省内存又省带宽,节约内存是因为内存中无需很多数据,节约带宽是因为在GPU中获得和处理的顶点较少。

曲面细分的工作伴随着由控制点定义的块,多数情况下,块是网格三角形,而控制点就是顶点。

当我们在曲面细分网格时,我们必须要知道每条边的细分数量,这个我们称之为"细分因子"。细分因子的数量在1-64之间,具体多少得取决于块的形状,如果块是个三角形,举个例子来说,外边缘会有3或者4个细分因子,而"内边"缘会有1个细分因子。通常,外边缘容易被直观显示,可以将之看作是细分之后的顶点个数(上图中,右边三角形外边缘的细分因子是4,3,3)

细分器支持3种图元类型,三角形,四边形以及直线

另外,我们可以使用多种分割策略进行细分操作,比如,整数,以2为底的幂函数(pow2),分数。

如果认真研究过D3D11的渲染管线,你就可以知道曲面细分是2种全新的shader类型的联合体:Hull着色器,Domain着色器以及位于它们之间的固定处理单元

实际上,Hull着色器是由两个着色器组成,一个是控制点着色器(Control Point Shader),另一个是固定块着色器(Patch Constant Shader),虽说,解释这两个着色器就并非这篇文章的主旨,但在讲述毛发渲染之前我已然做好了失去大部分读者的准备。控制点着色器对每个控制点(可以看成顶点)运行一次,同时也可以访问块(可以看成三角形)上的其它控制点;固定块着色器对每个块运行一次,它会输出细分因子,细分处理单元会根据这个细分因子决定图元的再分割程度

细分处理单元正如上述提到的固定处理单元一样,其目的是在常规标准化的图元(四边形,三角形以及直线)上生成新的点,同时输出它们的UVW坐标

有意思的是,细分处理单元并没有控制点/顶点/块的概念,因为它的操作对象是图元。

最后说说Domain着色器,Domain着色器接受控制点着色器的输出以及细分处理单元生成的新顶点,然后,再通过插值去生成新的图元。另外,如果我们想要比如使用高度图去表现顶点位移,那么就可以在这个阶段进行处理。

使用细分曲面渲染毛发

回到渲染毛发上,理论上讲很简单:

  • 构建细分处理单元产生使用直线图元的顶点
  • 在domain着色器中对数据进行插值处理,然后生成新的顶点
  • 使用几何着色器生成新的基于三角形的发丝网格

直线图元是种特殊的细分图元,它会返回2D数据,并且UV限制在0-1中,这对理解毛发渲染很关键,因为我们可以把UV取值范围看作是线的数量,而把其它部分看作是线中的段的数量

细分处理单元最多可以输出64条"线",每根线可以分成64段

发丝的生成发生在domain着色器中,那这里,可以访问到发丝网格几何体(三角形和顶点)的原数据,我们可以使用插值处理每根头发丝。要做到这一点,在CPU计算阶段,我使用了一个随机的重心坐标数组,并且将它们作为domain着色器的输入。如果带宽是瓶颈的话,那么此时你就可以在domain着色器中计算坐标。接着,我将细分处理单元提供的线的数量去索引重心坐标数组,然后去找新发丝所在位置。对于段的数量呢,我会用来向上延伸发丝,在这个例子中,每根毛发被分为4段

在对发丝顶点进行插值运算时,可以有两个做法,其一就是使用原始三角形顶点坐标对发丝的基顶点做一次插值(结果会得到三角面上的一个顶点),然后朝着法线方向向上延伸

对于短发(青草)的简单模拟,这是快速且容易的方法,但是在某些情况下,这样的简单模拟会有问题,比如模拟有很多段的长头发,又或者对更复杂情况的模拟/碰撞。另外,独立模拟每个发丝特别消耗资源

另一个做法就是通过使用"主"发丝顶点对每个发丝顶点进行插值然后生成新的发丝顶点(再次使用重心插值)

这种做法的好处就是:举个例子来说,我们可以在CPU或者compute 着色器中对主发丝进行模拟/碰撞检测,然后,再对‘已经"模拟好的"主发丝进行插值,从而得到新的发丝,这样可以明显降低开销

在这个例子中,我为每个三角形顶点创建了一个主发丝(顶点集合),然后再通过在CPU阶段定义的结构缓冲传递到domain着色器。如此一来,就不在需要基三角形顶点,也不需要除了会使用细分因子构建细分处理单元之外就别无他用的hull着色器。这个例子中还会检测基三角形的法线,同时,会剔除背对相机的部分。细分因子如果被设置为0,那么细分处理单元将不会生成任何新的顶点,这样的做法可以避免生成发丝的背面,不过请记住,即便基表面不可见,发丝仍旧可能可见,所以,在剔除时我们应该尽量保守点

我的所有数据都存储在结构缓冲中,但是我仍然需要做某些渲染层面的事情以便可以激活细分处理器,所以,我创建了有着一个顶点的顶点缓冲(坐标无所谓)以及有着很多三角行索引的索引缓冲。

前边提到过,细分处理器可以输出每个三角形最多64根线(发丝),这意味着,如果我们需要输出每个三角形更多的发丝,我们就必须处理更多的头发渲染过程(或者有一个非常稠密的网格)。在这里,我计算出了头发的强度值(每单位区域发丝的数量)以及根据区域指定每个三角形的发丝数量。如果一个三角形需要多于64根发丝才能被渲染,那么也需要更多的渲染步骤。

坦白讲,对于类似短毛发的渲染,我根本就没有使用主发丝,因为这不需要复杂的模拟,但是无论无何我相尝试一些这种方式。

domain着色器输出的发丝,实际上就是线,因此,很难让毛发产生体积,所以几何体着色器就被用于将直线放大为合适的三角形。

最后,为了让毛发看起来更加真实,我使用了各种不同参数的高光和一盏边缘光。

下边是通过修改毛发各方面比如长度,宽度和强度等对毛发渲染的结果:视频连接

我意识到由于毛发几何体(细丝)的本质,渲染结果很糟糕(没有几何体的抗锯齿),特别是毛发有动画时尤为糟糕:

添加了适度的MSAA(x4)数量以提升效果:

MASSx8的话效果提升了很多,但是x4就也就差不多足够了

我没有做屏幕空间的抗锯齿,不过,我觉得它对画质会有很大的影响(在完全没有使用几何抗锯齿的情况下)

即使使用几何抗锯齿,在与摄像机的距离发生改变时,仍然有会看到有发丝断裂,尤其是细发丝。为了解决这个问题,我尝试使用过 Emil Persson的Phone Wire AA方法,这个方法可以将"金属丝"几何体的宽度限制到最小值,如果实际宽度更小,那么会根据差值将其淡出。这个方法完美适用于"金属丝"类型的几何体,按道理对毛发也该有效才对。我仍然保留宽度最小的想法,意味这会让毛发在外观上有全面的提升

没使用Phone Wire AA方法的情况:

使用了Phone Wire AA:

我增加了毛发的长度以便可以更突出是否使用Phone Wire AA方法的差异,虽然这在静态图片中很难看得出

另外,同样的毛发渲染方法,我只是稍加改动,然后用于在别的例子中渲染草坪,最终很完美的呈现:

如果你有心尝试,你可以在这里找到VS2010的关于渲染毛发的项目工程,这个工程使用了Hieroglyph SDK以及FBX SDK 2013.3.

使用曲面细分渲染毛发相关推荐

  1. Tessellation (曲面细分) Displacement Mapping (贴图置换)

    DirectX 11 Tessellation (曲面细分)-什么是 Tessellation (曲面细分) ? 它为什么可以起到如此关键的数据? 随着近期人们对 DirectX 11 的议论纷纷,你 ...

  2. java nurbs几何库_OpenGL超级宝典笔记——NURBS与曲面细分

    NURBS 贝塞尔曲线的缺点是当我们增加很多控制点的时候,曲线变得不可控,其连续性会变差差.如果控制点很多(高阶曲线),当我们调整一个控制点的位置,对整个曲线的影响是很大的.要获得更高级的控制,可以使 ...

  3. openGL曲面细分

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.OpenGL 中的曲面细分 二.代码 1.主程序c++ 效果 前言 术语Tessellation(镶嵌)是指一大类设计活动,通常 ...

  4. 曲面细分着色器---细分二维四边形

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一.曲面细分 二.细分二维四边形 参考 前言 术语Tessellation(镶嵌)是指一大类设计活动,通常是指在平坦的表面上,用各种 ...

  5. Unity URP 曲面细分

    Unity URP 曲面细分 我终于变得不像我 文章目录 Unity URP 曲面细分 1 曲面细分与镶嵌 1.1 外壳着色器 Hull Shader 1.2 镶嵌器阶段 Tessellator 1. ...

  6. 计算机图形学【GAMES-101】5、几何(距离函数SDF、点云、贝塞尔曲线、曲面细分、曲面简化)

    快速跳转: 1.矩阵变换原理Transform(旋转.位移.缩放.正交投影.透视投影) 2.光栅化(反走样.傅里叶变换.卷积) 3.着色计算(深度缓存.着色模型.着色频率) 4.纹理映射(重心坐标插值 ...

  7. 曲面细分着色器与几何着色器

    着色器执行顺序 顶点着色器->曲面细分着色器->几何着色器->片元着色器 曲面细分着色器细分后的顶点属于重心空间. 曲面细分着色器 应用:海浪.雪地等 与置换贴图结合:只使用法线贴图 ...

  8. UnityShader 曲面细分着色器 生成地形 高度贴图

    什么是曲面细分着色器 如下图 ​ 曲面细分着色器比较官方定义:可以将一个几何体细化为一个球体也能将一根直线无限向曲线逼近 曲面细分着色器将复杂的曲面转换为简单的点,线,三角形等.它分为三部分:曲面细分 ...

  9. Geometry 曲面细分和曲面简化

    Geometry 曲面细分和曲面简化 1 曲面细分 a) Loop细分 b) Catmull-Clark细分(Catmull-Clark Subdivision) 曲面简化 边坍缩 总结: 1 曲面细 ...

最新文章

  1. 物联网下的数据传输,Python 就能搞定!
  2. Redis数据库 安装
  3. UVA - 10859 Placing Lampposts 放置街灯
  4. 【S操作】冰箱正常运行监控系统需求整理
  5. drtek收音机使用说明_【火腿实验室】使用双FSL中波环形天线消除同频干扰电台信号...
  6. 讲解web服务所涉及到的重要知识点
  7. vs 窗体连接mysql_vs2008 c#开发windows窗体程序,怎么连接数据库?
  8. 在你的 iOS App中 使用 OpenSSL 库 转发
  9. 架构设计:远程调用服务架构设计及zookeeper技术详解(上篇)
  10. php高效获取数据分页
  11. 黑苹果html5,黑苹果AppleALC声卡驱动安装使用教程 _ 黑苹果乐园
  12. 明清时期中央朝廷与地方关系中的江南著姓望族
  13. KinectV2 qt opencv 实现平面测量
  14. 0xc000007b的解决办法(续)
  15. nulls first和nulls last
  16. average函数python_在Python3 numpy中mean和average的区别详解
  17. 《大象--Thinking in UML 第二版》已于近日在当当首发,同时邀请各位加入新浪微博[大象-thinkinginUml群]:http://q.weibo.com/1483929
  18. 计算机系统集成能够承接哪些,系统集成资质承接范围
  19. 中层管理者如何脱颍而出?
  20. CentOS 7使用samba共享文件夹

热门文章

  1. 股票大作手回忆录(读书笔记)
  2. 顺序表和链表实现图书管理系统
  3. StreamWiki: Enabling Viewers of Knowledge SharingLive Streams to Collaboratively Generate Archival
  4. Mysql中的七种常用查询连接详解
  5. jaccard相似度算法
  6. 功放限幅保护_限幅器在音响系统中限幅阈值的计算方法
  7. java 实现文字转语音功能并同时生成语音文件 demo
  8. 《富爸爸穷爸爸》读书摘录脑图
  9. 硬盘被写保护不可写Diskpart解决办法
  10. Excel应用{数据加工与公式函数}