一、前言
这是在七夕写的一篇文章,在desmos的2d计算器上做了一个3d效果的跳动心形函数。这个函数是来源于shadertoy创始人之一的iq大佬(Inigo Quilez),使用的是一种称之为Signed Distance Functions(SDF,有符号距离函数)的方法。我将这个函数改为desmos 3d计算器上可以显示的版本,并且在这个基础上修改为2d版本,进行了动画的调整和着色

二、构造Signed Distance Functions(SDF,有符号距离函数)
2.1 球体SDF
首先要构造一个球体函数,公式为:
S(x,y,z)=x2+y2+z2
当输入S(x,y,z)<152时可以得到一个半径为15的球体

2.2 调整y轴,得到半颗心
将y调整为一个斜着的抛物面的函数:
Y(x,y)=y−x(4020−x)

然后应用到球体函数中进行y的空间扭曲,得到半颗心的形状:
S(x,Y(x,y),z)=x2+y2+z2

2.3 y轴对称并微调,得到对称的心
将y轴改为一个对称函数,做法就是加一个绝对值:
Y(x,y)=y−∣x∣(4020−∣x∣)


然后再对y轴函数微调,打磨一下心的形状:
Y(x,y)=4+1.2y−∣x∣1520−∣x∣

2.4 z轴调整心的厚度
从侧面看,心的厚度还需要进行调整

使用函数进行调整:
Z(y,z)=z(1.5−25y)S(x,Y(x,y),Z(y,z))<152

2.5 半径调整,做心跳动画
引入半径随时间变化的函数:
R(t)=15+3sin(2πt)S(x,Y(x,y),Z(y,z))<R(t0)2
其中t0是一个不断增长的时间参数

在这个半径函数的基础上,做一些调整,让跳动更有生物感:
R(y,t)=15+3(21+21sin(2πt+25y))4S(x,Y(x,y),Z(y,z))<R(y,t0)2

2.6 最终公式整理
S(x,y,z)=x2+y2+z2Y(x,y)=4+1.2y−∣x∣1520−∣x∣Z(y,z)=z(1.5−25y)R(y,r,t)=r+3(21+21sin(2πt+25y))4H(x,y,z,r,t)=S(x,Y(x,y),Z(y,z))−R(y,r,t)2
其中r为半径,提取出来方便调整,最终的效果的预览可以输入以下公式:
H(x,y,z,15,t0)<0
三、附加矩阵旋转
完成基础的SDF构造后,可以再加入一些整体的旋转,使用矩阵运算修改自变量x和z:
Hr(x,y,z,a,r,t)=H(xcosa−zsina,y,xsina+zcosa,r,t)
其中a为旋转角度,可以用以下公式预览结果:
Hr(x,y,z,t0,15,t0)<0

四、3D转2D
4.1 不同高度轮廓截取
为了将3D转为2D,我们可以对3D模型的不同高度的轮廓截取下来,根据高度给不同颜色拼到2D上。我们可以简单地将自变量高度z改为常数,例如获取高度0时的截面:
Hr(x,y,0,t0,15,t0)<0

然后我们再将不同高度截面都获取到,并给不同的颜色,就可以得到基础的3D效果了(高度取 [0, 3, 6, …, 15]):

4.2 动画微调,添加相机透视
我设计了一个转2D的函数方便调用:
H2d(x,y,z)=Hr((1−s0z)x,(1−s0z)(y+4r0sinπt0),z,4sin8πt0,r0,t0)
其中:
- r0为半径常数,默认15,提取出来方便调整
- s0为相机透视参数,默认50
最终效果:

五、最后
最后借用iq大佬的一句话,“祝愿你们心中都有所爱”❤️
