(PS这里读者得具备一定的CommandBuffer的使用经验)用过Unity的都知道,引擎本身不具备次表面 眼睛 毛发 布料等复杂视觉效果的材质提供。最近因为某些需求就在Unity里面实现了一个基于屏幕空间的次表面。特此来分享一下。如果不清楚次表面的可以看下面链接。
洛城:角色渲染技术——皮肤zhuanlan.zhihu.com
首先呢本SSS的算法来自Iryouku的GitHub开源项目"Separable SSS"。接下来我就来分享一下我在Unity的实现。第一呢根据作者源代码他的计算是每次高斯模糊的时候加权一个颜色叠加官方的HDPipeline这个操作是放到ComputeShader计算的,但是就我测试这个计算消耗并不是很大几乎可以忽略不计,所以我这里就直接使用了一个静态C#来实现。
接着就是把作者的SSS的Shader部分在Unity内的重现。我这里做了封装cginc(比较直观且不会杂乱多。。)。以下是cginc的部分(注意这里的参数_MainTex,这个是后面C#部分传递进来的一个参数)。
然后是SSS的Shader计算部分(分了两个Pass,第一个Pass算XBlur第二个算YBlur),其次就是这里开启了Stencil。
至此Shader部分的计算基本完成。剩下C#部分。因为作者这个算法是屏幕空间的次表面那也就代表他其实是一个后期全屏幕特效。这里我使用的是CommandBuffer来进行摄像机的后期处理而不是直接的OnImageRender,好处是这也能拿到Stencil(顺便安利一下Unity的Stencil在延迟渲染下貌似并没有什么作用,所以如果要做延迟次表面就得去修改引擎的延迟渲染文件。下面放个一个大佬的实现。支持延迟渲染和延迟Stencil。)
MaxwellGengYF/Unity-Human-Skin-Shader-PCgithub.com
首先我们新建一个PropertiCommon的C#文件里面内容如此。
这里这个DrawMesh的意义是为了在摄像机前画一个和屏幕一样尺寸大小模型以此来渲染全屏幕后期效果。后面的这些CustomBlit是整理后比较适合做自定义后期的一些函数(PS.这两个内容来自Git的Well大佬)。接着就可以创建挂在摄像机实现最终效果的C#组件了。内容如下图。
最后把这个组件挂在到摄像机(注意渲染路径需使用向前渲染),然后随便从哪儿找一个Shader吧Stencil的内容输出为如下图所示,播放即可实现SSS效果。
到现在实现的功能包括了后期屏幕空间特效和Stencil优化(PS一下因为Forward在GBuffer之后所以如果厂家有延迟渲染的内容可能会出现SSS计算的遮挡问题,正在修复...)。未来可能会加入前向渲染的带透射的皮肤材质或者是基于后期的透射,也计划增加同屏不一样的SSS颜色处理。说了这么多是时候上源代码了,各位支持支持(第一次传Git)。
https://github.com/haolange/UnityCharacterRender_SeparableSubsurfaceScattergithub.com
最后的最后来一串效果展示,奇数张是不带SSS的,偶数张是带SSS的(不要在意那个眼睛。简单扔上去的不是很好看,以后有空做个EyeShader)。