ShaderJoy —— 简单脉冲波(带锯齿的半正弦波)绘制【GLSL】

870 阅读1分钟

这是我参与8月更文挑战的第15天,活动详情查看: 8月更文挑战

效果图

简单脉冲波(带锯齿的半正弦波)绘制

image.png

三角波

首先我们来看如何绘制三角波,三角波(犹如锯齿)所使用的核心算法代码如下

abs(mod(x * 0.2, 2.0) - 1.0) - 0.5;

函数示意图如下

image.png

半正弦波

接着是半正弦波(截取正弦波的一部分,看起来犹如地平线上冒出一座山峰),其所使用的核心算法代码如下

    if (x < 0.0 || x > sineWidth)
        return 0.0;
    else
        return sin(x * pi / sineWidth) * height;

函数示意图如下

image.png

实际代码中我们使用和时间关联的参数 t ,随着时间推移,这样我们的半正弦波形就可以从左到右移动至指定位置

两个波函数的结合

将以上二者结合起来的话,(两种波形相乘就能得到我们所需的新波形函数)则可以得到如下的效果

image.png

完整的代码与注释如下所示

float triangle(float x)
{
    /// @note Triangle wave 三角波
    return abs(mod(x * 0.2, 2.0) - 1.0) - 0.5;
}

#iUniform float height = 40.0 in {40., 250.}
float truncSine(float x)
{
    /// @note Half sine wave 半正弦波
    const float sineWidth = 40.0;
    const float pi = 3.1415;

    if (x < 0.0 || x > sineWidth)
        return 0.0;
    else
        return sin(x * pi / sineWidth) * height;
}

/// @note 二者的结合
float rdWave(float x, float t)
{
    /// @note 半正弦波随时间平移
    return truncSine(x - t) * triangle(x);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    float yOffset = iResolution.y * .5;
    float x = floor(fragCoord.x);
    float y = floor(fragCoord.y) - yOffset;

    float t = mod(iTime, 10.) * 40.0;

    if (y < rdWave(x, t))
        fragColor = vec4(1.0, 0.0, 0.0, 1.0);
    else
        fragColor = vec4(0.0, 0.0, 0.0, 1.0);
}

Bonus

稍作修改我们可以得到如下类似心脏跳动脉冲的效果

image.png

修改的部分代码如下

    bool center = rdWave(x, t) >  y;
    bool right  = rdWave(x - 1.0, t) >  y;
    bool left   = rdWave(x + 1.0, t) >  y;
    bool up     = rdWave(x, t) >  y + 1.0;
    bool down   = rdWave(x, t) >  y - 1.0;

    if (center && !(right && left && up && down))
        fragColor = vec4(1.0, 0.0, 0.0, 1.0);
    else
        fragColor = vec4(0.0, 0.0, 0.0, 1.0);