前言
这几天MMD复建碰到了在Ray渲环境中透明贴图无法正常实现效果的问题,写篇笔记记录一下自己排除问题和修正的过程,以供日后参考。
另外,在查找资料的过程中,还找到了一些或许有可行性的经验,网址我会一并放在这篇笔记中。
如果你是业余MMD制作者,也被MMD加载Ray渲后透明贴图(尤其是渐变透明贴图)无法正常实现效果的问题困扰,又对原理知识无从下手,这篇笔记的排错思路和找到的资料也许能帮到你。
请注意,本篇笔记不是教程。作者完全没有计算机图形学基础,以前也没有深入学习过原理层面的知识,在着手解决这个问题之前甚至不知道Ray渲采用的是延迟渲染,也不了解延迟渲染很难处理透明材质这一特性,笔记有表述错误的地方在所难免,欢迎交流指正。
本篇笔记使用的模型是IndigO式铃兰v0.9.2,感谢模型作者创作的可爱铃兰。
目录
一、初期问题
二、初步排查:找出导致问题的渲染
三、初步尝试:从Ray渲着手修改Main.fx和Materials
四、新的问题:从模型着手检查和修改贴图
五、原理学习:透明贴图和延迟渲染
六、结论和猜想
一、初期问题
加载完Ray渲(v1.5.2)环境、导入美化MME并完成打光,以1080P分辨率输出视频后,修改4K分辨率准备输出封面。
此时才注意到模型耳朵毛发边缘有不自然的透明部分,随视角变化还会呈现出灰色锯齿。
虽然不打算再输出一遍,但是好奇心上来了,想解决这个问题。
小教训:渲染后期排除并找出问题要花很多时间成本,在前期加载Ray渲环境和分配材质的时候就应该仔细检查。
二、初步排查:找出导致问题的渲染
发现问题后,先检查了模型、场景和天空盒的描绘顺序,没有问题;将特效文件逐个删除,观察是哪个特效导致了透明贴图出现不自然边缘;在删除所有特效只保留Ray主渲染后,不自然边缘依然存在。
新建pmm在正确的描绘顺序下重新为模型挂载Ray,耳朵出现不自然边缘。
又新建pmm为模型挂载A_Toon,耳朵透明贴图可以正常发挥作用。
对比初步判断是Ray渲导致模型耳朵透明贴图无法发挥正常作用,并出现不自然边缘。
(关于MMD中的场景、模型和特效描绘顺序,这篇笔记的图示说明非常清晰,推荐参考。【https://www.bilibili.com/read/cv15704704】)
三、初步尝试:从Ray渲着手修改Main.fx和Materials
基于之前的判断,在Main面板中尝试为耳朵分配自带的Main alpha/noalpha .fx ,在分配后发现透明贴图可以被读取并发挥作用,但是不自然边缘仍然存在。
在内网用中文检索相关关键词后,找到了一些MMD中Ray环境下处理透明贴图和材质的经验笔记。
Ray渲染头发透明(透光)问题 作者:安達・桜
【https://www.bilibili.com/read/cv5279925】
问题很相似,有渐变透明贴图的发尾材质在挂载Ray渲后无法正常显示;但是作者的处理方式是让发尾变得不透明,我想保留铃兰耳朵毛茸茸的效果,所以没办法参考。
虽然没有解决问题,但是文中提到:ray渲染中由于延迟光照的缺陷,导致了对透明物体的不友好。
叶子出现透明白边如何解决 作者:Biscuit-773
【https://www.bilibili.com/read/cv18421737】
也是透明贴图产生不自然边缘的问题,通过修改AlphaThreshold(透明通道阈值)来改变遮罩范围,从而使锯齿边缘消失。
后面查资料得知,这种用透明通道对物体进行裁切的方式术语称作透切(AC——AlphaCutout)。在处理无透明度渐变边缘时才有较好的效果,如树叶和镂空的花纹。
四、新的问题:从模型着手检查和修改贴图
在修改Ray渲没有什么成效后,想起来原模型的贴图还没有进行检查。在MMD和PMDEditor中打开原模型,结果发现了新的问题:
未挂载任何渲染的模型,右耳的透明贴图原本就会产生不自然的边缘;但是左耳的透明贴图则可以正常发挥作用。
虽然有经验的改模和建模作者应该能立刻想到,这种不自然边缘可能是因为材质的顺序不对。但是当时打开材质栏检查后,发现左耳和右耳共用同一个材质:如果不自然的边缘是因为材质顺序产生的,那么左耳应该和右耳一样有不自然的边缘,所以我第一时间将材质因素排除了。
(后面绕了一大圈发现原因就是材质顺序,至于怎么发现的,为什么同样的材质左右耳效果会不一样,请看后文)
排除了材质因素后,我去模型作者的配布页重新下载了一份模型,并且仔细观察了配布视频,发现配布视频内的模型也是右耳有边缘而左耳正常,所以排除文件在下载和压缩中产生损坏或乱码的可能性。
在排除这些因素之后,接着检查耳朵对应的贴图。我的猜测是右耳对应的贴图透明部分仍然有像素存在,或是边缘过渡不够平滑,所以导致了不自然边缘的产生。于是在PS中对耳朵对应的png贴图进行了通道检查,并分别用羽化和渐变蒙版进行处理。
无论怎么修改贴图,右耳的不透明贴图就是会有一圈不自然的边缘,而左耳一切正常。
到这一步为止,如何解决这个不自然的边缘,我已经没有思路了。既然透明部分到不透明部分的平滑过渡暂时无法实现,那就放弃这种过渡吧。
试着用20%的白色将原贴图的透明部分填充,又挂载了一下渲染,因为没有到不透明部分的过渡,所以之前不自然的边缘和锯齿都消失了。
如果只是想实现一开始的目的,那么这样的效果勉强也能糊弄过去,但是如果要使用写实向的,这个方法的缺陷就非常大了。
五、原理学习:透明贴图和延迟渲染
Ray渲真的没办法处理好透明材质吗?为什么不挂Ray渲,原模型右耳的透明贴图也无法正常发挥作用?如果不使用透明贴图,要怎么表达模型耳朵内侧毛绒绒的质感?我还是想解决这些疑惑。带着疑问,我决定去观察其它铃兰模型的作者如何处理耳朵。
防晒霜式铃兰的毛发通过耳部内侧的贴图表现;SatoryAnn的铃兰毛发是单独建模处理;bude_的铃兰模型没有公开配布,耳朵效果非常通透轻盈,边缘的毛发效果也模拟得很柔软。bude_可能采用了其它软件来制作动画,以我目前的知识储备,无法判断这个效果是不是在MMD中实现的。
不过即使不是在MMD中完成的,bude_的作品也让我看到了用透明材质表达耳朵的可能性。或许看看一下其它软件中相同情况的解决方法,可以找到思路。于是我以“透明贴图”“白边”“边缘”为关键词,继续检索相关的信息,最后从【https://www.zhihu.com/question/32087433】这个问题下面David Dong的回答得到了灵感。
虽然软件是Unity,也没有太深入说明原理,但是这句话引起了我的思考:
在透明贴图的边缘,离透明通道的边缘太近,而透明通道又没有切的那么确切,所以搞了半个背景的颜色在里面。
也就是说,透明贴图边缘奇怪的颜色是有来源的。那么铃兰耳朵边缘的颜色是从哪里来的呢?我在PE中打开模型,变换角度仔细观察右耳的奇怪边缘,发现边缘的颜色和后脑勺头发的颜色是一样的。
也就是说,右耳的透明贴图没有将刘海作为背景。
切换到材质窗口,尝试将耳朵内侧的材质顺序调整到刘海的下面,发现透明贴图已经可以正常显示了。
罪魁祸首就是一开始排除了的材质描绘顺序。
那么,为什么使用了同一材质的左耳没有这个问题呢?我又检查了很久的贴图,重新处理了法线,最后终于弄清楚了原因,请看下图:
左耳遮盖区域只有脑壳儿,左耳的透明通道在计算时从头部材质获取颜色,再将计算结果显示在头部材质之后,所以透明效果是正常的;
右耳同时遮盖了脑壳和刘海的材质,透明贴图要想正常显示,则应该从头部材质和刘海材质获取背景颜色。由于材质顺序错误,原模型右耳没能从刘海材质获取背景颜色,在以头部材质为背景计算透明通道之后,再进行了刘海材质的描绘,所以产生了不自然的边缘。
至此,原模型自带的透明贴图bug已经解决了,原因就是很简单的材质顺序错误。
在检索之后,也找到了一些简要介绍透明渲染的资料。
透明贴图实现 作者:yumefx
【https://www.yumefx.com/?p=3437】
简要介绍了透明贴图的三种类型透切(AC——AlphaCutout)、透混(AB——AlphaBlend)以及透叠(AD——Additive)和它们的实现方式。
IndigO式铃兰耳朵贴图轮廓复杂,没有明确的边缘,透混才能有比较好的效果,所以材质顺序是非常重要的。
《LearnOpenGL》混合章节 作者:JoeyDeVrie
【https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/03%20Blending/】
一些原理层面的知识,介绍了OpenGL中实现物体透明度的技术“混合(Blending)”,本篇笔记碰到的问题在这篇教程中都能找到规范的原理说明。
至此,透明渲染相关的知识就了解得差不多了。想起上文看到的笔记提到了“延迟光照”这个名词,“延迟光照”是什么?为什么“延迟光照”在实现透明渲染方面会有困难呢?我又去搜索了相关的资料。
延迟渲染(Deferred Rendering)的前生今世 作者:浅墨_毛星云
【https://blog.csdn.net/poem_qianmo/article/details/77142101】
详尽地介绍了延迟渲染以及它的实现原理和应用。Ray-MMD采用的“延迟光照(Deferred Lighting)”是“延迟渲染(Deferred Rendering)”这一渲染方法的改进,延迟渲染又称延迟着色(英文写作Deferred Shading),在查找相关资料时要注意三者区别。
延迟渲染和延迟光照这两种方法只能完成对不透明物体的渲染,要想渲染透明或半透明的物体则需要采用另外的渲染方法,例如“向前渲染(Forward Rendering)”。
延迟渲染作者:lygyue
【https://zhuanlan.zhihu.com/p/102134614】
结合作者自身经验,将延迟渲染和向前渲染两种技术进行了对比,简单易懂,如果看上面那篇有困难可以看看这篇专栏。
[OpenGL] 延迟渲染下的简单透明渲染机制 作者:ZJU_fish1996
【https://blog.csdn.net/ZJU_fish1996/article/details/102333692】
介绍了一种依旧使用延迟渲染框架处理透明材质的低消耗渲染思路:分别渲染不透明物体,透明物体背面,透明物体正面,再把三者按照alpha合并。
在外网检索“Deferred Lighting”和“Ray mmd”后,我在Ray渲Github的讨论区中找到了和铃兰耳朵透明贴图问题相似的提问。
【https://github.com/ray-cast/ray-mmd/issues/17】
提问者的问题:
作者的回答:
看来延迟光照在处理透明材质方面,确实有很大的局限性。提问的时间是2017年,现在已经2022了,或许会有新的方法能解决这个问题——抱着这个想法,我继续检索类似情况的提问,不过也没有找到太多新的资料。
【Ray-MMD1.5.2】アルファマップ画像を使って透過する部分を指定して、動画中でモデルのモーフから透過度を操作する方法 作者:inwerwm
【http://conjectwrariwm.blog.2nt.com/blog-entry-13.html】
作者介绍了他在Ray渲环境中用透明通道贴图指定图像透明部分、从而在动画中控制透明度变化的方法。看正文有提到头发渐变透明的实现,但是因为没有示例图,涉及代码的部分看得非常吃力,去作者主页翻了很久也没看到实现这种效果的视频,所以暂时放弃了阅读。
至此,延迟光照和延迟光照渲染方法下透明材质的处理也了解得差不多了。
六、结论和猜想
先总结MMD使用Ray渲染时透明贴图和材质出现问题时的排查流程:
1、检查MMD工程文件的描绘顺序,包括模型顺序和特效顺序。排序的原则是:从上到下,先绘制所有不透明的物体,对所有透明的物体排序,按顺序绘制所有透明的物体。
2、在MMD和PE中检查模型本体,未挂载渲染的模型透明贴图是否存在问题。
如果第二步检查模型不存在问题,则回到MMD中找出导致透明贴图出现问题的特效:
1、如果是Ray渲导致的,在Main面板中尝试为出现问题的材质赋予Main Alpha/noAlpha.fx,使透明通道贴图被正常读取。
2、如果透明通道贴图属于透切类贴图,也可以被正常读取,但是依然存在不自然边缘,尝试修改Main.fx文件中的透明通道阈值。
如果第二步检查模型本身存在问题,则:
1、确认模型文件本身没有损坏或乱码。
2、在PE中检查材质描绘顺序,排序的原则也是:从上到下,先绘制所有不透明的物体,对所有透明的物体排序,按顺序绘制所有透明的物体。
3、检查材质对应的透明贴图通道是否完整,边缘有无杂色。
按照这个流程,应该可以花较低的时间成本找出问题所在并解决。
至于Ray渲处理透明材质的缺陷,由于Ray渲采用“延迟光照(Deferred Lighting)”这一渲染方法,所以目前很难解决。我根据上文中其它作者处理延迟渲染中透明材质的方法,猜想一下MMD-Ray中优化透明材质表达的可能方式:
1、使用M4Layer为透明材质单独挂载其它支持透明贴图的渲染,但是可能会有兼容问题,混合的模式也需要调整探索。
2、根据ZJU_fish1996的低消耗渲染思路(分别渲染不透明物体,透明物体背面,透明物体正面,再把三者按照alpha合并)进行渲染,但以我的知识储备不知道要如何在MMD-Ray中实现。
又需要写实渲染,又需要处理大量透明材质的话,还有一种思路是放弃Ray渲,使用其它基于向前渲染方法的渲染器,如sdPBR,不过本人也没有使用经验就是了。
以上就是本人对MMD加载Ray渲后透明贴图(尤其是渐变透明贴图)无法正常实现效果这一问题的探索经验,林林总总写了四千多字,希望这些思路和经验能帮到读者,有问题或者补充的话也欢迎在评论交流!
(本来只是一时兴起想要解决小锯齿,没想到一下找了这么多资料甚至产生了在写文献综述的错觉……)
2022年10月1日
藤椒狐狸