Cocos2dx 更改sprite色相/饱和度/亮度(HSV)

首先先来了解一下概念

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


三原色混合

2.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

OK 有了基础知识的储备 下面上shader
colorHSL.fsh

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
uniform sampler2D CC_Texture0;
uniform float u_dH;
uniform float u_dS;
uniform float u_dL;

void main() {
    
    vec4 texColor=texture2D(CC_Texture0, v_texCoord);
    float r=texColor.r;
    float g=texColor.g;
    float b=texColor.b;
    float a=texColor.a;
    //convert rgb to hsl
    float h;
    float s;
    float l;
    {
        float max=max(max(r,g),b);
        float min=min(min(r,g),b);
        //----h
        if(max==min){
            
            h=0.0;
        }else if(max==r&&g>=b){
            h=60.0*(g-b)/(max-min)+0.0;
        }else if(max==r&&g<b){
            h=60.0*(g-b)/(max-min)+360.0;
        }else if(max==g){
            h=60.0*(b-r)/(max-min)+120.0;
        }else if(max==b){
            h=60.0*(r-g)/(max-min)+240.0;
        }
        //----l
        l=0.5*(max+min);
        //----s
        if(l==0.0||max==min){
            s=0.0;
        }else if(0.0<=l&&l<=0.5){
            s=(max-min)/(2.0*l);
        }else if(l>0.5){
            s=(max-min)/(2.0-2.0*l);
        }
    }
    //(h,s,l)+(dH,dS,dL) -> (h,s,l)
    h=h+u_dH;
    s=min(1.0,max(0.0,s+u_dS));
    l=l+u_dL;
    //convert (h,s,l) to rgb and got final color
    vec4 finalColor;
    {
        float q;
        if(l<0.5){
            q=l*(1.0+s);
        }else if(l>=0.5){
            q=l+s-l*s;
        }
        float p=2.0*l-q;
        float hk=h/360.0;
        float t[3];
        t[0]=hk+1.0/3.0;t[1]=hk;t[2]=hk-1.0/3.0;
        for(int i=0;i<3;i++){
            if(t[i]<0.0)t[i]+=1.0;
            if(t[i]>1.0)t[i]-=1.0;
        }//got t[I]
        float c[3];
        for(int i=0;i<3;i++){
            if(t[i]<1.0/6.0){
                c[i]=p+((q-p)*6.0*t[I]);
            }else if(1.0/6.0<=t[i]&&t[i]<0.5){
                c[i]=q;
            }else if(0.5<=t[i]&&t[i]<2.0/3.0){
                c[i]=p+((q-p)*6.0*(2.0/3.0-t[i]));
            }else{
                c[i]=p;
            }
        }
        finalColor=vec4(c[0],c[1],c[2],a);
    }

    finalColor+=vec4(u_dL,u_dL,u_dL,0.0);
    
    gl_FragColor=finalColor;
    
}

以下适用COCOS2.2版本

.H中增加以下代码

void setHSLMode();
void setHSL(float h , float s, float l);
void updateHSL();

float m_dH;
float m_dS;
float m_dL;

GLuint m_dHlocation;
GLuint m_dSlocation;
GLuint m_dLlocation;

具体实现

void GameColorSprite::setHSLMode(){

    ccBlendFunc blendFunc={GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA};
    this->setBlendFunc(blendFunc);

    GLchar * fragSource = (GLchar*) CCString::createWithContentsOfFile(CCFileUtils::sharedFileUtils()->fullPathForFilename("colorHSL.fsh").c_str())->getCString();
    
    CGLProgramWithUnifos* pProgram = new CGLProgramWithUnifos();
    pProgram->initWithVertexShaderByteArray(ccPositionTextureColor_vert, fragSource);
    this->setShaderProgram(pProgram);
    pProgram->release();
    
    CHECK_GL_ERROR_DEBUG();
    
    this->getShaderProgram()->addAttribute(kCCAttributeNamePosition, kCCVertexAttrib_Position);
    this->getShaderProgram()->addAttribute(kCCAttributeNameColor, kCCVertexAttrib_Color);
    this->getShaderProgram()->addAttribute(kCCAttributeNameTexCoord, kCCVertexAttrib_TexCoords);
    CHECK_GL_ERROR_DEBUG();
    
    this->getShaderProgram()->link();
    CHECK_GL_ERROR_DEBUG();
    
    this->getShaderProgram()->updateUniforms();
    CHECK_GL_ERROR_DEBUG();
    
    m_dHlocation = glGetUniformLocation(getShaderProgram()->getProgram(), "u_dH");
    m_dSlocation = glGetUniformLocation(getShaderProgram()->getProgram(), "u_dS");
    m_dLlocation = glGetUniformLocation(getShaderProgram()->getProgram(), "u_dL");

    updateHSL();
}

void GameColorSprite::setHSL(float h , float s, float l){
    m_dH = h;
    m_dS = s;
    m_dL = l;
    updateHSL();
}
void GameColorSprite::updateHSL(){
    glUniform1f(m_dHlocation,m_dH);
    glUniform1f(m_dSlocation,m_dS);
    glUniform1f(m_dLlocation,m_dL);
}

————————
想要学习Cocos的同学,欢迎关注我的零基础Cocos教程
https://ke.qq.com/course/313749

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,729评论 6 517
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,226评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 169,461评论 0 362
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,135评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,130评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,736评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,179评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,124评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,657评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,723评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,872评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,533评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,213评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,700评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,819评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,304评论 3 379
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,876评论 2 361