(说在前头,如标题说的,这是一个"近似"的,就是大体上是差不多的,细节上其实还需要扣的,希望有大佬可以指点指点)
刚接触unity的shader没多久,冯女神的《Unity Shader入门精要》看到消融效果的实现,然后按着书上的代码敲完后,想要拓展这个效果,首先想到的就是自定义方向消融,于是就开始了动手。先来看下最终的效果:
这个动图里,一开始是展示整个消融过程,然后后面通过调整自定义起始点来观察消融的方向。 最初始的代码是照着《Unity Shader入门精要》中消融那一章写的,然后我只是改动了片元着色器的一小部分就实现图里面的效果了。下面就开始讲这个近似效果的实现过程。
要实现自定义方向,就需要有一个起始的点。从这个点开始,越靠近这个点的像素,越早剔除,自然而然地就会想到求像素到这个点的距离,于是就有下面的这一行代码:
float dis = length(i.objPos.xyz - i.startPos.xyz);
代码里的i就是片元着色器的参数,i.objPos存储的是顶点坐标(模型空间下),i.startPos存储的是在Properties中自己声明的起始点坐标(模型空间下),注意这两个坐标都需要是在模型空间坐标系下。接着我把这个dis组装成(dis, 1, 1, 1),在片元着色器中直接返回,观察这个dis的变化规律,得到的效果如下:
可以看到这个正方体的8个顶点位置接近白色,而每一个面从中心向四周,呈现一个淡蓝色向白色渐变的圆(至于为什么是淡蓝色,可以打开颜色选择器,然后把g、b、a通道的值都拉到最满,然后拉动r通道观察)。这个时候调节图片中Start Point的x、y、z的值就可以看到蓝色区域也在跟着变化。
因为考虑到白色部分的值是会超出过1的,所以我直接把这个dis取倒数,即(1/dis, 1, 1, 1),然后再观察下规律:
可以看到当我增大x的值的时候,蓝色部分是从一边慢慢过渡到另一边的。由于对dis取了倒数,dis越大则dis的倒数会越小,所以要注意一下起始点的方向所导致消融方向的问题。
接着,把Burn Amount作为分母乘以dis的倒数,即(_BurnAmount/dis, 1 ,1 ,1),作为片元着色器的输出值观察:
然后再与噪声纹理的r通道相减,即(_BurnAmount / dis - burn.r, 1, 1 ,1),再输出观察:
到了这里基本就差不多可以实现了,最后放上片元着色器的代码和效果图:
fixed4 frag (v2f i) : SV_Target
{
fixed3 burn = tex2D(_BurnMap, i.uvBurnMap).rgb;
float dis = length(i.objPos.xyz - i.startPos.xyz);
float args = _BurnAmount / dis - burn.r; // 自定义方向消融
clip(args);
fixed t = 1 - smoothstep(0.0, _LineWidth, args);
fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);
burnColor = pow(burnColor, 5);
fixed3 albedo = tex2D(_MainTex, i.uvMainTex).rgb;
fixed3 finalColor = lerp(albedo, burnColor, t * step(0.0001, _BurnAmount));
return fixed4(finalColor,1);
}
就此,自定义方向消融效果就实现了。之后鉴于习惯问题,因为减少Burn Amount才会开始消融,而且物体的消融方向是从远离Start Point开始的(至于为什么,可以看下上面蓝色的动图),所以我对args进行了修改,如下:
float args = (dis/_BurnAmount - 1) / burn.r - burn.r
使用这个args后的效果就是本篇文章最开始的那个gif图片的效果。
文章中如有不正确的表述,欢迎大家指出。因为是第一篇博文,所以可能会有写得不太好的地方,也欢迎大家提些建议。
最后,谢谢观看。