cocos2dx shader -- Vol.1(灰度、流光、百叶窗)
2014-09-05 13:45
851 查看
cocos2dx shader系列一——基本篇
这里介绍几种最基本也较常用的shader特效,当然序列帧动画也可以做这些特效,但远没有shader做的高效完美,而且省去不必要的内存消耗和cpu消耗,毕竟现在手机的gpu远远没有发挥它的作用,今天我们就让它发挥它该有的作为,让cpu歇一歇,不让你的手机烫坏你的手。。。。
以下shader均在cocos2dx引擎下测试过。
一、灰度图
这是最基本的shader,也是常用的效果,比如一个按钮会有三个状态,可点击、点击中、不可点击,第三种状态正是用灰度图表示的。灰度图也叫黑白图,即使用算法将每个像素RGB值转换为一种“灰色”颜色。
二、流光
流光的特效也常用,当然闪光的特效也类似,主要是给像素的RGB乘个因子,比如闪光是所有像素变亮或变暗
做流光的话,就不能这么简单的处理了。因为是要用到2张texture的混合。这里我们用shader生成一个有颜色的线条,选择一个x+y-c=0这条斜线为高亮部分。c从0到
生成的效果,width是线条的宽度,offset是线条的偏移(控制线条的移动),color是线条的颜色,
然后,我们用这条有颜色的线条来混合我们真实的贴图,起到高亮明显的效果。
效果如下:
factor来控制凸显部分的亮度(如图为正常亮度,即factor=1)
ps:如果觉得麻烦,可以另外传一张贴图来代替第一步生成的线条,这样可以省去动态生成有颜色的线条。
三、百叶窗
这是关于texture切换的效果,需要传递2张texture,这里我们就可以控制那张texture显示,那张不显示。shader如下:
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:代码
这里介绍几种最基本也较常用的shader特效,当然序列帧动画也可以做这些特效,但远没有shader做的高效完美,而且省去不必要的内存消耗和cpu消耗,毕竟现在手机的gpu远远没有发挥它的作用,今天我们就让它发挥它该有的作为,让cpu歇一歇,不让你的手机烫坏你的手。。。。
以下shader均在cocos2dx引擎下测试过。
一、灰度图
这是最基本的shader,也是常用的效果,比如一个按钮会有三个状态,可点击、点击中、不可点击,第三种状态正是用灰度图表示的。灰度图也叫黑白图,即使用算法将每个像素RGB值转换为一种“灰色”颜色。
#ifdef GL_ES precision lowp float; #endif uniform sampler2D u_texture; // pass from vs varying 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:代码
相关文章推荐
- Cocos2dx 使用Shader使精灵变灰
- 基于cocos2dx 2.x做的一些shader效果Demo
- 转载{shader流光效果}
- cocos2dx3.2版本利用shader实现sprite灰态图的正确方法
- Unity3D Shader 模型流光效果
- Cocos2dx - CCSprite使用 shader生成自己想要的颜色的图片
- cocos2dx shader实现深入浅出的背景
- cocos2dx 九宫格 shader失效的问题
- Cocos Creator 实现按钮图标的流光特效(Shader)
- Cocos2dx Shader学习
- cocos2dx(3.X)中使用shader
- Unity Shader-非主流纹理采样研究(流光,溶解,隐身效果)
- cocos2dx shader分析之CCGLProgram
- Shader实例:2D流光
- opengl之vsh、fsh简易介绍+cocos2dx 3.0 shader 变灰
- cocos2dx shader应用——sprite变灰
- cocos2dx shader应用——sprite变灰去色
- cocos2dx 自带shader 创建一个三角形
- cocos2dx shader实现的简单滤镜 基于3.0版本
- Cocos2dx - CCSprite使用 shader生成自己想要的颜色的图片