Cocos2D-X shader(四) 利用shader改变图片色相Hue

背景

美术给出一套资源后,可以通过改变图片色相,复用同一套资源产生出多套资源的效果


上图中蓝色是原始图片,利用代码改变图片色相后,可以产生效果差异明显的资源出来。像一些传统的游戏,如星际争霸等,都是通过这种技术实现了同一兵种,不同颜色种族的特效。

实现理论原理

看上去非常神奇的转换,实际上是利用了HSV格式图像处理的技术:

传统RGB模型:RGB是一种加色模式 将不同比例的RED/GREEN/BLUE混合在一起得到新的颜色

HSV(HSB)模型:通过色相/饱和度/亮度来得到颜色
H(hue):色相 表示颜色的类型 值域[0,360]
S(Saturation):饱和度 从灰度到纯色 值域[0,1]
V(Value or Brightness):亮度 从黑色到特定饱和度的颜色 值域[0,1]

HSV模型图

RGB到HSV的转换公式

HSV到RGB的转换公式

公式可以参考
http://baike.baidu.com/subview/541362/8445478.htm?fr=aladdin

普通代码实现

利用上述转换公式,实现代码如下(透明像素不处理):

  1. <spanstyle="font-family:Simsun;font-size:14px;">Texture2D*HelloWorld::initTextureWithImage(Image*image,float_fhue)
  2. {
  3. unsignedchar*tempData=NULL;
  4. boolhasAlpha=image->hasAlpha();
  5. SizeimageSize=Size((float)(image->getWidth()),(float)(image->getHeight()));
  6. Texture2D::PixelFormatpixelFormat;
  7. unsignedintwidth=image->getWidth();
  8. unsignedintheight=image->getHeight();
  9. //Repackthepixeldataintotherightformat
  10. unsignedintlength=width*height;
  11. unsignedintnewDataLen=0;
  12. //Convert"RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA"to"RRRRRRRRGGGGGGGGBBBBBBBB"
  13. float_f=_fhue/60;//节省运算
  14. if(hasAlpha)
  15. {
  16. //computepixelformat
  17. pixelFormat=Texture2D::PixelFormat::RGBA8888;
  18. tempData=newunsignedchar[length*4];
  19. newDataLen=length*4;
  20. unsignedchar*outPixel8=tempData;
  21. unsignedint*inPixel32=(unsignedint*)image->getData();
  22. for(unsignedinti=0;i<length;++i,++inPixel32)
  23. {
  24. unsignedchar*_colRGB=outPixel8;
  25. *outPixel8++=(*inPixel32>>0)&0xFF;//R
  26. *outPixel8++=(*inPixel32>>8)&0xFF;//G
  27. *outPixel8++=(*inPixel32>>16)&0xFF;//B
  28. *outPixel8=(*inPixel32>>24)&0xFF;//A
  29. //透明图层不做处理
  30. if(*outPixel8++)
  31. {
  32. unsignedchar_r=*_colRGB;
  33. unsignedchar_g=*(_colRGB+1);
  34. unsignedchar_b=*(_colRGB+2);
  35. unsignedcharmin=(_r<_g)?_r:_g;
  36. min=(min<_b)?min:_b;
  37. unsignedcharmax=(_r>_g)?_r:_g;
  38. max=(max>_b)?max:_b;
  39. unsignedchartemp=(max-min);
  40. floathsbH=0;//temp
  41. if(temp)
  42. {
  43. if(max==_r){
  44. if(_g>=_b)
  45. {
  46. hsbH=(float)(_g-_b)/(float)temp;
  47. }
  48. else
  49. {
  50. hsbH=((float)(_g-_b)/(float)temp)+6;
  51. }
  52. }
  53. elseif(max==_g){
  54. hsbH=((float)(_b-_r)/(float)temp)+2;
  55. }
  56. elseif(max==_b){
  57. hsbH=((float)(_r-_g)/(float)temp)+4;
  58. }
  59. }
  60. else
  61. {
  62. hsbH=0;
  63. }
  64. hsbH+=_f;
  65. if(hsbH<0)
  66. hsbH+=6;
  67. elseif(hsbH>6)
  68. hsbH-=6;
  69. chari=(int)hsbH;
  70. hsbH=hsbH-i;
  71. switch(i){
  72. case6:
  73. case0:
  74. (*_colRGB++)=max;
  75. (*_colRGB++)=min+(int)(hsbH*temp);
  76. (*_colRGB++)=min;
  77. break;
  78. case1:
  79. (*_colRGB++)=max-(int)(hsbH*temp);
  80. (*_colRGB++)=max;
  81. (*_colRGB++)=min;
  82. break;
  83. case2:
  84. (*_colRGB++)=min;
  85. (*_colRGB++)=max;
  86. (*_colRGB++)=min+(int)(hsbH*temp);
  87. break;
  88. case3:
  89. (*_colRGB++)=min;
  90. (*_colRGB++)=max-(int)(hsbH*temp);
  91. (*_colRGB++)=max;
  92. break;
  93. case4:
  94. (*_colRGB++)=min+(int)(hsbH*temp);
  95. (*_colRGB++)=min;
  96. (*_colRGB++)=max;
  97. break;
  98. case5:
  99. (*_colRGB++)=max;
  100. (*_colRGB++)=min;
  101. (*_colRGB++)=max-(int)(hsbH*temp);
  102. break;
  103. default:
  104. break;
  105. }
  106. }
  107. }
  108. }
  109. else
  110. {
  111. pixelFormat=Texture2D::PixelFormat::RGB888;
  112. tempData=newunsignedchar[length*3];
  113. newDataLen=length*3;
  114. unsignedchar*out3=image->getData();
  115. unsignedchar*outPixel8=tempData;
  116. for(unsignedinti=0;i<length;++i)
  117. {
  118. unsignedchar_r=*out3++;
  119. unsignedchar_g=*out3++;
  120. unsignedchar_b=*out3++;
  121. //changeHSLForRgb(255,0);
  122. //unsignedchar*_NowRGB=changeHSLForRgb(_r,_g,_b,_fhue);
  123. //_r=*_NowRGB++;
  124. //_g=*_NowRGB++;
  125. //_b=*_NowRGB++;
  126. *outPixel8++=_r;//R
  127. *outPixel8++=_g;//G
  128. *outPixel8++=_b;//B
  129. }
  130. }
  131. Texture2D*_text2d=newTexture2D();
  132. _text2d->initWithData(tempData,newDataLen,pixelFormat,width,height,imageSize);
  133. delete[]tempData;
  134. //_text2d->_hasPremultipliedAlpha=image->hasPremultipliedAlpha();
  135. return_text2d;
  136. }</span>

利用Shader实现

Shader可以利用GPU提升渲染效率:

colorHSL.fsh

  1. #ifdefGL_ES
  2. precisionmediumpfloat;
  3. #endif
  4. varyingvec2v_texCoord;
  5. uniformsampler2DCC_Texture0;
  6. uniformfloatu_dH;
  7. uniformfloatu_dS;
  8. uniformfloatu_dL;
  9. voidmain(){
  10. vec4texColor=texture2D(CC_Texture0,v_texCoord);
  11. floatr=texColor.r;
  12. floatg=texColor.g;
  13. floatb=texColor.b;
  14. floata=texColor.a;
  15. //convertrgbtohsl
  16. floath;
  17. floats;
  18. floatl;
  19. {
  20. floatmax=max(max(r,g),b);
  21. floatmin=min(min(r,b);
  22. //----h
  23. if(max==min){
  24. h=0.0;
  25. }elseif(max==r&&g>=b){
  26. h=60.0*(g-b)/(max-min)+0.0;
  27. }elseif(max==r&&g<b){
  28. h=60.0*(g-b)/(max-min)+360.0;
  29. }elseif(max==g){
  30. h=60.0*(b-r)/(max-min)+120.0;
  31. }elseif(max==b){
  32. h=60.0*(r-g)/(max-min)+240.0;
  33. }
  34. //----l
  35. l=0.5*(max+min);
  36. //----s
  37. if(l==0.0||max==min){
  38. s=0.0;
  39. }elseif(0.0<=l&&l<=0.5){
  40. s=(max-min)/(2.0*l);
  41. }elseif(l>0.5){
  42. s=(max-min)/(2.0-2.0*l);
  43. }
  44. }
  45. //(h,s,l)+(dH,dS,dL)->(h,l)
  46. h=h+u_dH;
  47. s=min(1.0,max(0.0,s+u_dS));
  48. l=l+u_dL;
  49. //convert(h,l)torgbandgotfinalcolor
  50. vec4finalColor;
  51. {
  52. floatq;
  53. if(l<0.5){
  54. q=l*(1.0+s);
  55. }elseif(l>=0.5){
  56. q=l+s-l*s;
  57. }
  58. floatp=2.0*l-q;
  59. floathk=h/360.0;
  60. floatt[3];
  61. t[0]=hk+1.0/3.0;t[1]=hk;t[2]=hk-1.0/3.0;
  62. for(inti=0;i<3;i++){
  63. if(t[i]<0.0)t[i]+=1.0;
  64. if(t[i]>1.0)t[i]-=1.0;
  65. }//gott[i]
  66. floatc[3];
  67. for(inti=0;i<3;i++){
  68. if(t[i]<1.0/6.0){
  69. c[i]=p+((q-p)*6.0*t[i]);
  70. }elseif(1.0/6.0<=t[i]&&t[i]<0.5){
  71. c[i]=q;
  72. }elseif(0.5<=t[i]&&t[i]<2.0/3.0){
  73. c[i]=p+((q-p)*6.0*(2.0/3.0-t[i]));
  74. }else{
  75. c[i]=p;
  76. }
  77. }
  78. finalColor=vec4(c[0],c[1],c[2],a);
  79. }
  80. finalColor+=vec4(u_dL,u_dL,0.0);
  81. gl_FragColor=finalColor;
  82. }

以下适用COCOS2.2版本

.H中增加以下代码

  1. voidsetHSLMode();
  2. voidsetHSL(floath,floats,floatl);
  3. voidupdateHSL();
  4. floatm_dH;
  5. floatm_dS;
  6. floatm_dL;
  7. gluintm_dhlocation;
  8. gluintm_dSlocation;
  9. gluintm_dLlocation;


具体实现

  1. voidGameColorSprite::setHSLMode(){
  2. ccBlendFuncblendFunc={GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA};
  3. this->setBlendFunc(blendFunc);
  4. GLchar*fragSource=(GLchar*)CCString::createWithContentsOfFile(CCFileUtils::sharedFileUtils()->fullPathForFilename("colorHSL.fsh").c_str())->getCString();
  5. CGLProgramWithUnifos*pProgram=newCGLProgramWithUnifos();
  6. pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert,fragSource);
  7. this->setShaderProgram(pProgram);
  8. pProgram->release();
  9. CHECK_GL_ERROR_DEBUG();
  10. this->getShaderProgram()->addAttribute(kCCAttributeNamePosition,kCCVertexAttrib_Position);
  11. this->getShaderProgram()->addAttribute(kCCAttributeNameColor,kCCVertexAttrib_Color);
  12. this->getShaderProgram()->addAttribute(kCCAttributeNameTexCoord,kCCVertexAttrib_TexCoords);
  13. CHECK_GL_ERROR_DEBUG();
  14. this->getShaderProgram()->link();
  15. CHECK_GL_ERROR_DEBUG();
  16. this->getShaderProgram()->updateUniforms();
  17. CHECK_GL_ERROR_DEBUG();
  18. m_dhlocation=glGetUniformlocation(getShaderProgram()->getProgram(),"u_dH");
  19. m_dSlocation=glGetUniformlocation(getShaderProgram()->getProgram(),"u_dS");
  20. m_dLlocation=glGetUniformlocation(getShaderProgram()->getProgram(),"u_dL");
  21. updateHSL();
  22. }

  1. voidGameColorSprite::setHSL(floath,floatl){
  2. m_dH=h;
  3. m_dS=s;
  4. m_dL=l;
  5. updateHSL();
  6. }

  1. voidGameColorSprite::updateHSL(){
  2. gluniform1f(m_dhlocation,m_dH);
  3. gluniform1f(m_dSlocation,m_dS);
  4. gluniform1f(m_dLlocation,m_dL);
  5. }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


    本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991.  软件准备 下载地址:http://cn.cocos2d-x.org/download 2.  简介2.1         引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download  v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
    Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0    有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1.  来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
   Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
 下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建
2019独角兽企业重金招聘Python工程师标准>>>cocos2d2.0之后加入了一种九宫格的实现,主要作用是用来拉伸图片,这样的好处在于保留图片四个角不变形的同时,对图片中间部分进行拉伸,来满足一些控件的自适应(PS: 比如包括按钮,对话框,最直观的形象就是ios里的短信气泡了),这就要求图
原文链接:http://www.cnblogs.com/linji/p/3599478.html1.环境和工具准备Win7VS2010/2012,至于2008v2版本之后似乎就不支持了。 2.安装pythonv.2.0版本之前是用vs模板创建工程的,到vs2.2之后就改用python创建了。到python官网下载版本2.7.5的,然后
环境:ubuntu14.04adt-bundle-linux-x86_64android-ndk-r9d-linux-x86_64cocos2d-x-3.0正式版apache-ant1.9.3python2.7(ubuntu自带)加入环境变量exportANDROID_SDK_ROOT=/home/yangming/adt-bundle-linux/sdkexportPATH=${PATH}:/$ANDROID_SDK_ROOTools/export
1开发背景游戏程序设计涉及了学科中的各个方面,鉴于目的在于学习与进步,本游戏《FlappyBird》采用了两个不同的开发方式来开发本款游戏,一类直接采用win32底层API来实现,另一类采用当前火热的cocos2d-x游戏引擎来开发本游戏。2需求分析2.1数据分析本项目要开发的是一款游
原文链接:http://www.cnblogs.com/linji/p/3599912.html//纯色色块控件(锚点默认左下角)CCLayerColor*ccc=CCLayerColor::create(ccc4(255,0,0,128),200,100);//渐变色块控件CCLayerGradient*ccc=CCLayerGradient::create(ccc4(255,0,0,
原文链接:http://www.cnblogs.com/linji/p/3599488.html//载入一张图片CCSprite*leftDoor=CCSprite::create("loading/door.png");leftDoor->setAnchorPoint(ccp(1,0.5));//设置锚点为右边中心点leftDoor->setPosition(ccp(240,160));/
为了答谢广大学员对智捷课堂以及关老师的支持,现购买51CTO学院关老师的Cocos2d-x课程之一可以送智捷课堂编写图书一本(专题可以送3本)。一、Cocos2d-x课程列表:1、Cocos2d-x入门与提高视频教程__Part22、Cocos2d-x数据持久化与网络通信__Part33、Cocos2d-x架构设计与性能优化内存优
Spawn让多个action同时执行。Spawn有多种不同的create方法,最终都调用了createWithTwoActions(FiniteTimeAction*action1,FiniteTimeAction*action2)方法。createWithTwoActions调用initWithTwoActions方法:对两个action变量初始化:_one=action1;_two=action2;如果两个a
需要环境:php,luajit.昨天在cygwin上安装php和luajit环境,这真特么是一个坑。建议不要用虚拟环境安装打包环境,否则可能会出现各种莫名问题。折腾了一下午,最终将环境转向linux。其中,luajit的安装脚本已经在quick-cocos2d-x-develop/bin/中,直接luajit_install.sh即可。我的lin
v3.0相对v2.2来说,最引人注意的。应该是对触摸层级的优化。和lambda回调函数的引入(嗯嗯,不枉我改了那么多类名。话说,每次cocos2dx大更新。总要改掉一堆类名函数名)。这些特性应该有不少人研究了,所以今天说点跟图片有关的东西。v3.0在载入图片方面也有了非常大改变,仅仅只是