「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」
爱心函数由来
说到爱心函数就要提起一个名人勒内·笛卡尔
,法国著名哲学家、物理学家、数学家、神学家。他是17世纪欧洲哲学界和科学界最有影响力的名人之一誉为近代科学始祖。传说爱心函数是勒内·笛卡尔
在欧洲游历邂逅瑞典公主克里斯汀并彼此产生爱慕之心,但因为种种原因两人无法相爱。勒内·笛卡尔
在给公主寄出第十三封信的时候与世长辞,第十三封信的内容并是爱心公式。这就是关于爱心函数由来的传奇故事。
爱心公式:
爱心实现效果
在glsl
中可以使用内置函数直接复刻出爱心公式。内置函数组合技就是length
+sqrt
+pow
实现爱心公式。
x的y次方
genType pow (genType x, genType y)
x的开方
genType sqrt (genType x)
向量x的长度
float length (genType x)
const vec3 white = vec3(1.);
const vec3 red = vec3(0.9608, 0.2745, 0.0275);
vec3 sdfHeart(vec2 uv){
float value = uv.y - sqrt(pow(uv.x,2.));
float d = length(vec2(uv.x,value)) - 0.2;
return d > 0. ? white: red;
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
uv -= 0.5;
uv.x *= iResolution.x/iResolution.y;
gl_FragColor = vec4(sdfHeart(uv),1.0);
}
复制代码
最终效果上来说好像并不能达到希望看到的爱心形状,这个爱心有点“瘦”。
升级版爱心
除了勒内·笛卡尔
版本的爱心之外,还有其他爱心生成公式,例如桃型爱心、标准爱心等。
桃型爱心
公式如下:
const vec3 white = vec3(1.);
const vec3 red = vec3(0.9608, 0.2745, 0.0275);
vec3 sdfHeart2(vec2 uv){
float value = pow(length(uv)-0.2,3.);
float d = value - pow(uv.x,2.)*pow(uv.y,3.);
return d > 0.? white: red;
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
uv -= 0.5;
gl_FragColor = vec4(sdfHeart2(uv),1.0);
}
复制代码
标准爱心
标准爱心
使用和桃型爱心
相同公式但修改了公式参数以及glsl
部分代码调整后得到更加饱满锐利的爱心形状。爱心的中心定位在inHeart
函数内部来实现而不在全局去处理了。
float isHeart (vec2 uv, vec2 center)
{
vec2 o = (uv - center) / (0.5);
float a = o.x * o.x + o.y * o.y - 0.3;
float s0 = a * a * a;
float s1 = o.x * o.x * o.y * o.y * o.y;
return step(s0, s1);
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
gl_FragColor = vec4(mix(
white,
red,
inHeart(uv, vec2(0.5))
),1.);
}
复制代码
爱心动画效果
增加一个progress
参数,inHeart
函数增加一个size
调节爱心大小,实现爱心变大效果。
float progress = 0.f;
float inHeart (vec2 uv, vec2 center, float size)
{
if (size == 0.0)
return 0.0;
vec2 o = (uv - center) / (1.6 * size);
float a = o.x * o.x + o.y * o.y - 0.3;
float s0 = a * a * a;
float s1 = o.x * o.x * o.y * o.y * o.y;
return step(s0, s1);
}
void main() {
vec2 uv = gl_FragCoord.xy / iResolution.xy;
progress = fract(.4 * iTime);
gl_FragColor = vec4(mix(
white,
red,
inHeart(uv, vec2(0.5), progress)
),1.);
}
复制代码