常用图片处理算法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);
}