Cocos2d-x 3.x 的精灵修改色相(Hue)

来源:互联网 发布:下列属于软件特性 编辑:程序博客网 时间:2024/04/28 13:21

Cocos2d-x 3.x 的精灵修改色相(Hue)


原文链接  : http://www.cocoachina.com/bbs/read.php?tid=282479


首先是shader文件

hueChange.fsh

varying vec2 v_texCoord;uniform mat3 u_hue;uniform float u_alpha;void main(){    vec4 pixColor = texture2D(CC_Texture0, v_texCoord);    vec3 rgbColor ;    rgbColor = u_hue * pixColor.rgb;        gl_FragColor = vec4(rgbColor.r,rgbColor.g,rgbColor.b, pixColor.a * u_alpha);}

hueChange.vsh

attribute vec4 a_position;attribute vec2 a_texCoord;attribute vec4 a_color;varying vec2 v_texCoord;void main(){    gl_Position = CC_PMatrix * a_position;    v_texCoord = a_texCoord;}

CCSpriteWithHue.h

#ifndef __SnippetsProject__CCSpriteWithHue__#define __SnippetsProject__CCSpriteWithHue__#include "cocos2d.h"USING_NS_CC;class CCSpriteWithHue :public Sprite {    private://variable        GLint m_hueLocation;    GLint m_alphaLocation;    protected://variable    public://variable        CC_SYNTHESIZE_READONLY(GLfloat, m_hue, Hue);    private://method          protected://method        virtual void setupDefaultSettings();        virtual void getUniformLocations();        virtual void updateColorMatrix();        virtual void updateAlpha();        virtual GLfloat alpha();        virtual void updateColor();        virtual bool initWithTexture(Texture2D *texture, const Rect& rect, bool rotated);        virtual void initShader();    public://method        CCSpriteWithHue();        virtual ~CCSpriteWithHue();        static CCSpriteWithHue* create(const std::string& filename);        virtual void setHue(GLfloat _hue);            };


CCSpriteWithHue.cpp

#include "CCSpriteWithHue.h"void xRotateMat(float mat[3][3], float rs, float rc);void yRotateMat(float mat[3][3], float rs, float rc);void zRotateMat(float mat[3][3], float rs, float rc);void matrixMult(float a[3][3], float b[3][3], float c[3][3]);void hueMatrix(GLfloat mat[3][3], float angle);void premultiplyAlpha(GLfloat mat[3][3], float alpha);CCSpriteWithHue::CCSpriteWithHue(){    }CCSpriteWithHue::~CCSpriteWithHue(){    }CCSpriteWithHue* CCSpriteWithHue::create(const std::string& filename){    CCSpriteWithHue *sprite = new (std::nothrow) CCSpriteWithHue();    if (sprite && sprite->initWithFile(filename))    {        sprite->autorelease();        return sprite;    }    CC_SAFE_DELETE(sprite);    return nullptr;}bool CCSpriteWithHue::initWithTexture(Texture2D *texture, const Rect& rect, bool rotated){        if (!Sprite::initWithTexture(texture, rect, rotated)) {        return false;    }    this->setupDefaultSettings();    this->initShader();    return true;}void CCSpriteWithHue::setupDefaultSettings(){    this->m_hue = 0.0;}void CCSpriteWithHue::initShader(){    GLProgram * p = new GLProgram();    this->setGLProgram(p);    p->release();    p->initWithFilenames("hueChange.vsh", "hueChange.fsh");    p->link();    p->updateUniforms();    this->getUniformLocations();    this->updateColor();}void CCSpriteWithHue::getUniformLocations(){    m_hueLocation = glGetUniformLocation(this->getGLProgram()->getProgram(), "u_hue");    m_alphaLocation = glGetUniformLocation(this->getGLProgram()->getProgram(), "u_alpha");}void CCSpriteWithHue::updateColorMatrix(){    this->getGLProgram()->use();    GLfloat mat[3][3];    memset(mat, 0, sizeof(GLfloat)*9);    hueMatrix(mat, m_hue);    premultiplyAlpha(mat, this->alpha());    glUniformMatrix3fv(m_hueLocation, 1, GL_FALSE, (GLfloat *)&mat);}void CCSpriteWithHue::updateAlpha(){    this->getGLProgram()->use();    glUniform1f(m_alphaLocation, this->alpha());}GLfloat CCSpriteWithHue::alpha(){        return _displayedOpacity / 255.0f;}void CCSpriteWithHue::setHue(GLfloat _hue){    m_hue = _hue;    this->updateColorMatrix();}void CCSpriteWithHue::updateColor(){    Sprite::updateColor();    this->updateColorMatrix();    this->updateAlpha();}#pragma mark -void xRotateMat(float mat[3][3], float rs, float rc){    mat[0][0] = 1.0;    mat[0][1] = 0.0;    mat[0][2] = 0.0;        mat[1][0] = 0.0;    mat[1][1] = rc;    mat[1][2] = rs;        mat[2][0] = 0.0;    mat[2][1] = -rs;    mat[2][2] = rc;}void yRotateMat(float mat[3][3], float rs, float rc){    mat[0][0] = rc;    mat[0][1] = 0.0;    mat[0][2] = -rs;        mat[1][0] = 0.0;    mat[1][1] = 1.0;    mat[1][2] = 0.0;        mat[2][0] = rs;    mat[2][1] = 0.0;    mat[2][2] = rc;}void zRotateMat(float mat[3][3], float rs, float rc){    mat[0][0] = rc;    mat[0][1] = rs;    mat[0][2] = 0.0;        mat[1][0] = -rs;    mat[1][1] = rc;    mat[1][2] = 0.0;        mat[2][0] = 0.0;    mat[2][1] = 0.0;    mat[2][2] = 1.0;}void matrixMult(float a[3][3], float b[3][3], float c[3][3]){    int x, y;    float temp[3][3];        for(y=0; y<3; y++) {        for(x=0; x<3; x++) {            temp[y][x] = b[y][0] * a[0][x] + b[y][1] * a[1][x] + b[y][2] * a[2][x];        }    }    for(y=0; y<3; y++) {        for(x=0; x<3; x++) {            c[y][x] = temp[y][x];        }    }}void hueMatrix(GLfloat mat[3][3], float angle){#define SQRT_2      sqrt(2.0)#define SQRT_3      sqrt(3.0)        float mag, rot[3][3];    float xrs, xrc;    float yrs, yrc;    float zrs, zrc;        // Rotate the grey vector into positive Z    mag = SQRT_2;    xrs = 1.0/mag;    xrc = 1.0/mag;    xRotateMat(mat, xrs, xrc);    mag = SQRT_3;    yrs = -1.0/mag;    yrc = SQRT_2/mag;    yRotateMat(rot, yrs, yrc);    matrixMult(rot, mat, mat);        // Rotate the hue    zrs = sin(angle);    zrc = cos(angle);    zRotateMat(rot, zrs, zrc);    matrixMult(rot, mat, mat);        // Rotate the grey vector back into place    yRotateMat(rot, -yrs, yrc);    matrixMult(rot,  mat, mat);    xRotateMat(rot, -xrs, xrc);    matrixMult(rot,  mat, mat);}void premultiplyAlpha(GLfloat mat[3][3], float alpha){    for (int i = 0; i < 3; ++i) {        for (int j = 0; j < 3; ++j) {            mat[i][j] *= alpha;        }    }}


使用实例


CCSpriteWithHue *hueSprite = CCSpriteWithHue::create("HelloWorld.png");hueSprite->setHue(1.6);//值在 0 ~ 2 Pi 之间hueSprite->setPosition(visibleSize.width / 2, visibleSize.height / 2);this->addChild(hueSprite);

运行效果

setHue(1.6):


setHue(2.6):


setHue(3.6):



0 0
原创粉丝点击