Shader特效——“爱心❤的变换” 的实现 【GLSL】

效果视频

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);
}

然后重点是 s_{0}s_{1} 的计算:

① s_{0}=(x^2+y^2-0.3)^3

它的三维视图为

s0 三维视图

 等值线图为

s0 等值线图

② s_{1} = x^2*y^3 

它的三维视图为

s1 三维视图

等值线图为:

s1 等值线图

③ s_{0} < s{1}  ,我们知道 step 函数是当 s1 > s0 的时候返回1, s1<= s0  的时候返回 0 。结果如图所示

不要问为什么,问就是数学的神奇 ^_^ ❤

s_{0}-s{1} 的三维视图为

s0-s1 三维可视图

 s0-s1 的等值线图为

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);
}
发布了233 篇原创文章 · 获赞 221 · 访问量 106万+

猜你喜欢

转载自blog.csdn.net/panda1234lee/article/details/104146816