作者最近有些忙哈哈哈,连这篇文章还在年前拖到了年后才更新完成!这里只简单比较叙述多pass的基本原理,与毛发各种的渲染模拟的比较等等,后续会更详细描述毛发相关的渲染~
毛发渲染模拟的简介:
毛发渲染一直是实时图形学的难题,因为其光照复杂,数量众多,物理效果不好抽象等。所以才有了多pass的毛发、面片(card)与Mesh实现毛发、Marschner毛发模型、 Kajiya-Kay模型等等。毛发的渲染模拟按照适用范围大概分为几种:长发或者短毛发。其中人类主要是长发居多、动物的毛皮主要是表现为短发当然它们的适用范围也不同,动物的短毛皮比人类头发更加复杂,一种是表层的长毛(被毛),另一种是内层的绒毛(更加细小、弯曲)就适合使用混合的多pass实现。
毛发模拟的几种方式:
毛发的物理‘:
- K帧动画:技术实现简单,通过使用不同移动方向播放不同动画来实现。优点:技术简单,性能消耗最低。缺点:堆人力,需要大量的美术人员及其工作耗时;
- Dynamic Bone 动态骨骼,优点:性能消耗低,在移动端表现良好。缺点:无自碰撞、无法拉伸可能会发生自穿插。另外一方面DynamicBone所有计算都不考虑时间因素,所以同样弹簧参数不同更新频率参数下表现会非常不同,加大了调参难度。详细请看我另一篇文章移动端布料的模拟 -基于DynamicBone的实现。
毛发的渲染:
- phong,就不必多说优点:算法简单好实现,无技术难度,计算量不大性能消耗低;缺点:经验模式,不真实。
- KaijiyaKay,基于卡通的毛发渲染,是基于经验的着色模型,也就是并不是完全的着色物理正确。在Kajiya-Kay模型中,头发纤维被抽象化为一个不透明的圆柱体,不能够透射和产生内部反射。因此,Kajiya-Kay模型不能表现一些肉眼观察到的头发效果,同时也是能量不守恒的。在kajiya中,光照主要分为diffuse和Specular。现代动画中常见。缺点:莫名的高光,不是基于真是的渲染是NPR。
-
Marschner(siggraph03) 是除Kajiya-Kay模型外另一个应用广泛的头发着色模型。Marschner模型将头发纤维抽象为一个透明的椭圆柱体。其将有相关散射的光路,最主要的三个光路R“光线从头发丝表面反射给view”,
TT“光折射进头发然后反射给view”,TRT“光线折射进头发丝,再内部反射后最终折射给观察者”。优点:真实,经典算法;缺点:消耗大;
多RenderPass渲染原理:
说多pass前先说一下什么是单pass,简单来说一个pass就是走完图形渲染底层一个渲染流程,(从顶点计算 着色 光栅化等这一套流程)从而得到一帧数据的过程;multi-pass就是多pass也就是渲染一帧需要多个pass来配合完成最后那一帧的效果的过程。
一个物体我们需要多次渲染,每个渲染过程的结果会被累加到最终的呈现结果上或者说是一个RenderTarget(FBO 离屏渲染),所以往往多PASS往往又与透明相联系;至于为什么需要多pass当然是因为一个pass无法满足我们的需求,就比如“Z-prepass”、“多pass短毛发的渲染”。 pass之间是相互依赖的,后边的pass会用到前面的pass数据(深度、几何信息、alpha),最后的pass出来的数据才是帧缓冲中的数据。(这里作者遇到了一个Bug,多pass毛发透底,就是渲染的顺序问题,alpha值的叠加问题!)
虽然不管引擎做了什么抽象比如unity的多pass只需要写一次代码剩余使用配置来,但本质上就是一系列drawcall的集合, 这类DrawCall通常有着类似的属性,并且按照一定的顺序执行,绘制结果通常保存在一张RT中,作为输入供后边使用****。一次FBO bind 当前所有绘制指令 unbind FBO解绑绘制指令。所以现代的引擎中有各种各样的pass 比如unity 或者UE大致分为了 Reflection Pass,Shadow Pass、 highlights pass、Global illumination pass、Light Pass、 Pre-Z、 还有一种比较特别的pass ——后处理的全屏pass,这种pass只绘制两个或者一个三角形,但也称为一个pass。
如上所说的
多PASS实现毛发的渲染
大致是实现流程:
分为两步,也可以说分为两种材质(可以通过宏编译来划分一个sahder,根据不同的引擎有不同的做法但是原理相同,大同小异而已)
一、材质一是一个底图,不开启透明混合的底图(理解:想象一下毛发底下是皮层是不透明度),但是该有的噪声纹理还是要有。然后只需要设置要渲染毛发的Mesh的材质setMaterial(furmMat1) 然后draw() 即可。
二、材质二就是多pass,需要开启透明混合,同样需要噪声纹理同样纹理的采样环绕方式是四方连续环绕模式GL_MIRRORED_REPEAT
,噪声纹理的噪声就是毛发生成的位置!然后每一次pass都要设置一个FUR_OFFSET参数,在opengl中是0到1 的一个范围,可以等于1 不能为0;该项就是毛发layer朝着法线normal方向的偏移量(理解:想象一下一层一层的挤出去)所以毛发长度越长需要的pass数量越多,即层数越多也就是Draw的次数越多!比如pass 10 层偏移FUR_OFFSET = 0.1,没层+0.1;pass 25 层0.04;在毛发的片元函数中,把noise的灰度输出到alpha,并且让alpha值随着层数衰减,至此我们已经完成了多pass毛发原理的主要部分。
根据RenderPass渲染原理,别看unity或者UE 看起来多pass 实现原理很难,其实很简单的(引擎只是做了一些便捷化的操作)伪代码如下:
local defaultMat //不透明底图
local furMaterial //透明
render(){ //渲染循环中
furFbo:bind()
for (i = 1, passCount>i, i++)
if(i == 1){
model:setMaterial(defaultMat)
model:draw()
}
else
{
flurMaterial:getParmeter():setFloat(i - 1) //设置偏移量(根据需求来设置)
model:setMaterial(furMaterial)
model:draw()
}
end
furFbo:unbind()
}
一次draw就是一个pass,对应的材质设置即对应的drawcall,及其排序也跟循环顺序一致。alpha值根据各个层pass叠加。(这里作者遇到了开启循环大于一多pass的时候一个透底的Bug,只draw不透明是正常的,是由于FBO的问题用的第一层alpha值)alpha值多少看你选择的blend类型,alpha不支持交换律一层一层叠加,如果中途被不开启混合的叠加加直接使用不开启混合的!
优点:多pass毛发能在移动端实现毛发的渲染!如上面谈论的一样,毛发的渲染有很多方式,然而类似UE的groom毛发系统等通用毛发物理实现,长短毛发都可以,但是在移动端消耗性能非常庞大所以并不太适合移动端。所以目前在移动端实现毛发渲染而且性能效果不错的也就啊它了。
缺点:
• 多pass的制作方式,无法制作头发这样的长毛,只能制作较短的毛发。
• 要有比较好的效果, 就需要非常多的pass来进行计算, 因为移动平台对大量Overdraw这样的像素级处理是非常大的一笔开销。
如图中的毛发模型所示,它把毛发分成了很多层。每一层,顶点往法线方向“生长”一点点,通过控制每一层的alpha值来实现毛发从根部到尖部逐渐变小,每一层只渲染alpha大于0的顶点,再利用一张噪波图来控制alpha值,就可以调出一个毛发模型。
能模拟真实毛发衣服比如我最近春节年前买的衣服 休闲仿羊羔绒外套的效果,在我最近做的虚拟衣服中就是这样的例子。
头发的光:
环境光、轮廓光、太阳光各项异性高光:毛鳞片,头发的组成部分。头发主要由表皮层、皮质层、膸质层组成,而表皮层是由许多细小的鳞片重叠而成,这就是我们所说的毛鳞片,它可称为一种保护层。发丝上的小鳞片排列整齐,会折射更多的光线,头发将显得亮丽动人;如保护不当、用力梳刷、吹发或经常洗发、烫发、染发等都会损害头发的表皮层,使头发失去亮泽。完整的毛鳞片,平滑、边缘整齐未受损伤。 具平滑的毛鳞片,头发柔顺、亮泽,易于梳理。毛鳞片损伤、毛鳞片拱起或被坏,头发开始失光泽,手感粗糙。损失部分毛鳞片,使皮层暴露,头发变得粗糙呆板。毛鳞片的进一步损失使皮层变弱以致干枯,导致头发开叉。
轮廓光:
轮廓光其实也是环境光的一部分。这里单独给轮廓光计算,也只是弥补环境反光的不足,同时加一些可控项,同时也和上面的一样,物体的颜色越浅,轮廓光穿透率越强;反之颜色越深,轮廓光穿透率越弱。
文章来源:https://www.toymoban.com/news/detail-464268.html
参考资料:
真香预警!新版“峡谷第一美”妲己尾巴毛发制作分享
Fur Effects - Teddies, Cats, Hair …
多pass毛发制作愤怒的小鸡儿
剖析Unreal Engine超真实人类的渲染技术Part 3 - 毛发渲染及其它
头发渲染的前世今生:如何在游戏中拥有一头迷人秀发?
毛发渲染总结文章来源地址https://www.toymoban.com/news/detail-464268.html
到了这里,关于毛发渲染(一)--基于多pass透明混合的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!