这是我参与8月更文挑战的第14天,活动详情查看: 8月更文挑战
效果图
调节部分参数可得到不同风格的效果
原图
核心算法思路
该效果的核心思路一共分为以下几步【参考 Photoshop 中的图层操作】
- 先根据图像的亮度,人为设定阈值,分为(6个)不同等级的灰度图; 然后构造(6个)不同旋转方向的 “木刻纹” 图像,如下图所示;
- 接着,将 “木刻纹” 图像作为遮罩,以上二者两两进行结合,得到如下图像
- 最后将上一步得到的结果进行叠加起来,就可以得到如下的最终结果
简化后的核心代码与注释
#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);
}
(完)