cocos2dx shader -- Vol.1(灰度、流光、百叶窗)

来源:互联网 发布:淘宝满减券漏洞 编辑:程序博客网 时间:2024/05/01 16:48

cocos2dx shader系列一——基本篇
这里介绍几种最基本也较常用的shader特效,当然序列帧动画也可以做这些特效,但远没有shader做的高效完美,而且省去不必要的内存消耗和cpu消耗,毕竟现在手机的gpu远远没有发挥它的作用,今天我们就让它发挥它该有的作为,让cpu歇一歇,不让你的手机烫坏你的手。。。。

以下shader均在cocos2dx引擎下测试过。

一、灰度图

这是最基本的shader,也是常用的效果,比如一个按钮会有三个状态,可点击、点击中、不可点击,第三种状态正是用灰度图表示的。灰度图也叫黑白图,即使用算法将每个像素RGB值转换为一种“灰色”颜色。

#ifdef GL_ES                                precision lowp float;                       #endif               uniform sampler2D u_texture;  // pass from vsvarying vec4 v_fragmentColor;               varying vec2 v_texCoord;                   void main()                                 {                                                 vec4 texColor = texture2D(u_texture, v_texCoord);      float gray = dot(texColor.rgb, vec3(0.299, 0.587, 0.114));      gl_FragColor = v_fragmentColor * vec4(gray, gray, gray, texColor.a);}       

二、流光

流光的特效也常用,当然闪光的特效也类似,主要是给像素的RGB乘个因子,比如闪光是所有像素变亮或变暗

vec4 texColor = texture2D(u_texture, v_texCoord);  texColor[0] = texColor[0] * factor;texColor[1] = texColor[1] * factor;texColor[2] = texColor[2] * factor;gl_FragColor = v_fragmentColor * texColor;            
factor=1时就是正常的显示,大于1的话,会发亮,小与1会变暗。

做流光的话,就不能这么简单的处理了。因为是要用到2张texture的混合。这里我们用shader生成一个有颜色的线条,选择一个x+y-c=0这条斜线为高亮部分。c从0到

#ifdef GL_ES                               precision lowp float;                        #endif                                        varying vec4 v_fragmentColor;                varying vec2 v_texCoord;                    uniform sampler2D u_texture;                uniform float factor;uniform float width;uniform float offset;uniform vec3 color;   void main()                                    {                                                 vec4 texColor = texture2D(u_texture, v_texCoord);     // line (x+y-offset=0) offset:[0, 2] (2->0)     //     |y     //     |     // ____|0__ 1__2____x     //     |       |     //     |_______|     float distance = abs(v_texCoord[0]+v_texCoord[1]/1.414;     // linear gradient (base on distance)     // (1/width)x + y = 1     distance = 1.0-(1.0/width)*distance;     distance = max(distance, 0.0);     vec4 sample = vec4(0.0,0.0,0.0,0.0);     sample[0] = color[0] * distance;     sample[1] = color[1] * distance;     sample[2] = color[2] * distance;     sample[3] = distance;     gl_FragColor = v_fragmentColor * sample;}      


生成的效果,width是线条的宽度,offset是线条的偏移(控制线条的移动),color是线条的颜色,

然后,我们用这条有颜色的线条来混合我们真实的贴图,起到高亮明显的效果。

void main()                                    {                                                 vec4 texColor = texture2D(u_texture, v_texCoord);     // line (x+y-offset=0) offset:[0, 2] (2->0)     //     |y     //     |     // ____|0__ 1__2____x     //     |       |     //     |_______|*     float distance = abs(v_texCoord[0]+v_texCoord[1]-offset)/1.414;      // linear gradient      // (1/width)x + y = 1     distance = 1.0-(1.0/width)*distance;     distance = max(distance, 0.0);     vec4 sample = vec4(0.0,0.0,0.0,0.0);     sample[0] = color[0] * distance;     sample[1] = color[1] * distance;     sample[2] = color[2] * distance;     sample[3] = distance;     // blend additive      float alpha = sample[3]*texColor[3];     texColor[0] = texColor[0] + sample[0]*alpha*factor;     texColor[1] = texColor[1] + sample[1]*alpha*factor;     texColor[2] = texColor[2] + sample[2]*alpha*factor;     gl_FragColor = v_fragmentColor * texColor;}

效果如下:


factor来控制凸显部分的亮度(如图为正常亮度,即factor=1)

ps:如果觉得麻烦,可以另外传一张贴图来代替第一步生成的线条,这样可以省去动态生成有颜色的线条。


三、百叶窗

这是关于texture切换的效果,需要传递2张texture,这里我们就可以控制那张texture显示,那张不显示。shader如下:

#ifdef GL_ES                                precision lowp float;                       #endif                                      uniform sampler2D texture0;uniform sampler2D texture1;uniform float flag;uniform float lineWidth;uniform float offset;varying vec4 v_fragmentColor;                varying vec2 v_texCoord;                    void main(){     float modPart = mod(v_texCoord[0], lineWidth);     float solidPart = (1.0-offset) * lineWidth;     // reduce tex-switch times     // (0, 1) (2, 1) (2, 3) (0, 3)     //modPart = modPart * flag;     //solidPart = solidPart * flag;     if (modPart > solidPart)      {          gl_FragColor = v_fragmentColor * texture2D(texture1, v_texCoord);     }     else     {          gl_FragColor = v_fragmentColor * texture2D(texture0, v_texCoord);     }}
我们通过linewidth变量来控制百叶窗分成几块,每一块区间[0,1],然后通过offset变量来控制[0, offset]部分显示tex0, [offset,1]部分显示tex1。效果如下:

ps:当有多张贴图时,就要改变texture0和texture1,之前担心切换texture的开销,所以加了个flag变量来较少切换的个数,不过在手机上试下,切换时不会卡顿。在不加flag变量的情况下需要切换2张texture,加了flag变量每次就只要切换一张texture。

例如 0, 1,2 三张texture,

不加flag: (0, 1) - > (1, 2) -> (2, 0) - > (0, 1)

加flag:(0, 1) -> (2, 1) - > (2, 0) - > (1, 0)

Repository:代码

0 0
原创粉丝点击