ShaderJoy —— 漫画笔触效果【GLSL】

1,341 阅读1分钟

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

效果图

image.png

调节部分参数可得到不同风格的效果

image.png

原图

image.png

核心算法思路

该效果的核心思路一共分为以下几步【参考 Photoshop 中的图层操作】

  • 先根据图像的亮度,人为设定阈值,分为(6个)不同等级的灰度图; 然后构造(6个)不同旋转方向的 “木刻纹” 图像,如下图所示;

image.png

  • 接着,将 “木刻纹” 图像作为遮罩,以上二者两两进行结合,得到如下图像

image.png

  • 最后将上一步得到的结果进行叠加起来,就可以得到如下的最终结果

image.png

简化后的核心代码与注释


#iChannel0 "file://../images/20.jpg"
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    vec2 uv = fragCoord.xy / iResolution.xy;

    float amplitud = 0.03;
    float frecuencia = 10.0; 
    float gris = 1.0;
    float divisor = 4.8 / iResolution.y;
    float grosorInicial = divisor * 0.2;

    const int kNumPatrones = 6;

    /// @note x:角的正弦,y:角的余弦,z:亮度因子
    vec3 datosPatron[kNumPatrones];
    datosPatron[0] = vec3(-0.7071, 0.7071, 1.0); // -45°
    datosPatron[1] = vec3(0.0, 1.0, 0.6); // 0°
    datosPatron[2] = vec3(0.0, 1.0, 0.5); // 0°
    datosPatron[3] = vec3(1.0, 0.0, 0.4); // 90°
    datosPatron[4] = vec3(1.0, 0.0, 0.3); // 90°
    datosPatron[5] = vec3(0.0, 1.0, 0.2); // 0°

    vec4 color = texture(iChannel0, uv);
    fragColor = color;

    for (int i = 0; i < kNumPatrones; i++)
    {
        float sinv = datosPatron[i].x;
        float cosv = datosPatron[i].y;

        // @note 对 uv 坐标进行旋转
        vec2 rotuv = vec2(
                         uv.x * cosv - uv.y * sinv,
                         uv.x * sinv + uv.y * cosv
                     );

        /// @note 增加对比度
        float grosor = grosorInicial * float(i + 1);
        /// @note 构造不同方向的 “木刻纹”
        float dist = mod(rotuv.y - sin(rotuv.x * frecuencia) * amplitud, divisor); 

        /// @note 灰度
        float lum = dot(vec3(.3, .4, .3), color.rgb);
        /// @note 将各个亮度分级的 “木刻纹” 进行融合
        if (lum < 0.82 - .12 * float(i)) ///< 亮度分级
        {
            // @note 增加对比
            float k = datosPatron[i].z;
            float x = (grosor - dist) / grosor;
            float fx = abs(x / k);
            gris = min(gris, fx);
        }
    }

        fragColor = vec4(gris, gris, gris, 1.0);
}

(完)