常用图片处理算法shader版

 - by Hector

最近学习了一段时间的gles, 搜了一些photoshop的常见图片处理算法,用shader实现了一下,下面所有效果基于opengles 2.0,利用Cocosd-x 3.0引擎框架测试通过。所有算法在实际使用时,注意优化与改进。

New:后面又加了几种特效,并把刀塔传奇里面的shader也加进去了,代码是在cocos2d-x项目下开了一个branch,写在Test项目里(第一个Test就是)。如果你本地有clone, cocos2d-x的项目,加一个remote,运行即可。

branch地址:https://github.com/myourys/cocos2d-x/tree/mytest

反相(底片效果)

说明:对应ps反相操作,rgb值都取反,比如r = 1-r。效果为黑变白,白变黑。

frame shader:

    vec4 nomalColor = texture2D(CC_Texture0, v_texCoord);
    gl_FragColor = vec4(1.0 - nomalColor.r,1.0 - nomalColor.b,1.0 - nomalColor.g,1.0);

灰图

说明:灰色图片每个颜色点的rgb值是一样的,只有明暗变化,因此,综合rgb的亮度得到灰图的亮度,rgb的亮度因子是前人综合得到。

frame shader:

    vec4 v_orColor = texture2D(CC_Texture0, v_texCoord);
    float gray = dot(v_orColor.rgb, vec3(0.299, 0.587, 0.114));
    gl_FragColor = vec4(gray, gray, gray, v_orColor.a);

黑白照片

说明:黑白照片只有黑白两种颜色,求RGB平均值Avg = (R + G + B) / 3,如果Avg >= 100,则新的颜色值为R=G=B=255;如果Avg < 100,则新的颜色值为R=G=B=0;100是一个经验值,设置为128也可以,可以根据效果来调整。

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;

void main()
{
    vec4 color;
    color = texture2D(u_texture, v_texCoord);
    if ((color.r + color.g + color.b)/3.0 > 100.0/255.0) {
        color.rgb = vec3(1);
    }
    else{
        color.rgb = vec3(0);
    }
    gl_FragColor = vec4(color.rgb, 1);
}

浮雕

说明:用当前点的RGB值减去相邻点的RGB值并加上0.5作为新的RGB值。由于图片中相邻点的颜色值是比较接近的,因此这样的算法处理之后,只有颜色的边沿区域,也就是相邻颜色差异较大的部分的结果才会比较明显,而其他平滑区域则值都接近128左右,也就是灰色,这样就具有了浮雕效果。

ps:shader 中的参数可调节,得到更丰富的明暗变化,凹凸变化。

frame shader:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;
// image's size
uniform vec2 v_texSize;

void main()
{
    vec2 onePixel = vec2(1.0 / v_texSize.r, 1.0 / v_texSize.g);

    vec4 color;
    color.rgb = vec3(0.5);
    color -= texture2D(u_texture, v_texCoord - onePixel) * 5.0;
    color += texture2D(u_texture, v_texCoord + onePixel) * 5.0;

    color.rgb = vec3((color.r + color.g + color.b) / 3.0);
    gl_FragColor = vec4(color.rgb, 1);
}

平滑图像

说明:每个像素点平均上下左右和几个角的像素值,然后平均。

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;
// image's size
uniform vec2 v_texSize;

void main()
{
    vec2 onePixel = vec2(1.0 / v_texSize.r, 1.0 / v_texSize.g);

    vec4 nomalColor = texture2D(u_texture, v_texCoord);
    nomalColor += texture2D(u_texture, v_texCoord + vec2(onePixel.r,0));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(-onePixel.r,0));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(0,onePixel.g));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(0,-onePixel.g));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(onePixel.r,onePixel.g));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(onePixel.r,-onePixel.g));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(-onePixel.r,onePixel.g));
    nomalColor += texture2D(u_texture, v_texCoord + vec2(-onePixel.r,-onePixel.g));

    nomalColor.rgb = vec3(nomalColor.rgb / 9.0);
    gl_FragColor = vec4(nomalColor.rgb, 1);
}

曝光效果

说明:逆转值小于128的R、G、B分量值,产生正片和负片混合的效果。

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;

void main()
{
    vec4 color= texture2D(u_texture, v_texCoord);
    if (color.r < 128.0/255.0) {
        color.r = 1.0- color.r;
    }
    if (color.g < 128.0/255.0) {
        color.g = 1.0- color.g;
    }
    if (color.b < 128.0/255.0) {
        color.b = 1.0- color.b;
    }

    gl_FragColor = vec4(color.rgb, 1);
}

霓虹效果

说明:用来描绘图像的轮廓,勾画颜色变化的边缘,加强其过度效果,产生轮廓发光的效果。计算方式是将原图像当前像素的R、G、B分量与其右方和下方像素做梯度运算(差的平方和的平方根)。

frame shader:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D u_texture;
// image's size
uniform vec2 v_texSize;

void main()
{
    vec2 onePixel = vec2(1.0 / v_texSize.r, 1.0 / v_texSize.g);

    vec4 color = texture2D(u_texture, v_texCoord);
    vec4 colorRight = texture2D(u_texture, v_texCoord + vec2(0,onePixel.t));
    vec4 colorBottom = texture2D(u_texture, v_texCoord + vec2(onePixel.s,0));

    color.r = 3.0* sqrt( (color.r - colorRight.r) * (color.r - colorRight.r) + (color.r - colorBottom.r) * (color.r - colorBottom.r) );
    color.g = 3.0* sqrt( (color.g - colorRight.g) * (color.g - colorRight.g) + (color.g - colorBottom.g) * (color.g - colorBottom.g) );
    color.b = 3.0* sqrt( (color.b - colorRight.b) * (color.b - colorRight.b) + (color.b - colorBottom.b) * (color.b - colorBottom.b) );

    color.r >1.0 ? 1.0 : color.r;
    color.g >1.0 ? 1.0 : color.g;
    color.b >1.0 ? 1.0 : color.b;
    gl_FragColor = vec4(color.rgb, 1);
}

 

Leave a comment