效果视频
Shader特效——“爱心❤的变换” 的实现 【GLSL】
静态效果图
设计思路与核心代码
首先我们将纹理坐标 p 换算为以 center 为中心的坐标系,如下所示
float inHeart (vec2 p, vec2 center, float size)
{
// 奇异值的处理
if (size == 0.0)
return 0.0;
vec2 o = (p - center) / (1.6 * size); ///< 以 center 为中心的坐标变换,随着 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); ///< 返回的结果用于插值
// float eps = 5e-4;
// return smoothstep(a-eps, a+eps, s);
}
然后重点是 和 的计算:
①
它的三维视图为
等值线图为
②
它的三维视图为
等值线图为:
③ ,我们知道 step 函数是当 s1 > s0 的时候返回1, s1<= s0 的时候返回 0 。结果如图所示
④ 的三维视图为
s0-s1 的等值线图为
完整代码与详细注释为
#define PI 3.141592653589
#define PI_HALF (PI/2.)
#iChannel0 "file://./images/0.jpg"
#iChannel1 "file://./images/2.jpg"
float progress = 0.f;
vec4 getFromColor(vec2 uv)
{
return texture2D(iChannel0, uv);
}
vec4 getToColor(vec2 uv)
{
return texture2D(iChannel1, uv);
}
float inHeart (vec2 p, vec2 center, float size)
{
// 奇异值的处理
if (size == 0.0)
return 0.0;
vec2 o = (p - center) / (1.6 * size); ///< 以 center 为中心的坐标变换,随着 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); ///< 返回的结果用于插值
}
vec4 transition (vec2 uv)
{
float aspect = iResolution.x / iResolution.y;
vec2 pos = uv;
vec2 center = vec2(0.5, 0.4);
return mix(
getFromColor(uv),
getToColor(uv),
inHeart(pos, center, progress)
);
}
void main()
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
progress = fract(.5 * iTime); ///< 线性速度
gl_FragColor = transition(uv);
}