实现思路
今天来写一个肥皂泡的shader,虽然最后出来的结果不太像。。但是还是简单讲一下思路好了。
一般写shader的话先从现实生活找找参考,肥皂泡的话首先形状不是标准的球形,而且在移动的过程中外形会改变,因此我们需要写一个顶点偏移函数。
接着就是肥皂泡表面上的薄膜干涉效果,使得肥皂泡表面表现出来就是花花绿绿的。这种光学效果要真的靠计算光线去模拟的话不太现实,因此就用一张渐变贴图加上一张噪声图来模拟。
然后就是很常见的rim效果,这个只用计算出来之后叠加上去就可以了。
最后就是反射和折射,反射的话用表面着色器自带的就可以了,折射的话用grabpass加上一个基于法线的偏移就可以了。
大致就是这些效果叠加起来,理清楚之后就可以开始写了。
代码实现
顶点位移函数使用的是顶点的y坐标加上时间变量来计算,另外放在三角函数里保证了是一个周期效果,其实这个偏移函数也不是固定的,只要自己觉得看上去像是那么回事就可以了。另外记得在表面着色器的顶点偏移函数里如果要传递值,需要调用UNITY_INITIALIZE_OUTPUT宏来初始化结构体。
void vertexDataFunc(inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input, o);
float3 value = (cos(5.0 * v.vertex.y + _Time.y) * 0.015 + sin(5.0 * v.vertex.y + _Time.y) * 0.005).xxx;
v.vertex.xyz += value;
}
接下来把rim效果加上,对视角方向和顶点法线方向做点积,然后用幂函数改变rim值的衰减曲线
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(IN.worldPos));
float rimValue = 1 - pow(dot(worldViewDir, IN.worldNormal), 2);
肥皂泡的颜色用了两张贴图,一张黑白噪声贴图一张渐变颜色贴图,首先用主uv采样噪声图得到一个亮度值,然后用这个亮度值重新对渐变颜色图进行采样,同时加上定义的偏移值_UVOffset以及乘上缩放值_UVScale,就可以得到一种花花绿绿的效果。
使用的贴图
uv映射
//重新映射uv
fixed2 newUV = tex2D(_MainTex, (IN.uv_MainTex + _SinTime.x * fixed2(1, 1))