2017-01-24 21 views
0

Я добавляю Sprite в качестве фона. Теперь я хочу, чтобы мой Sprite мог размываться, постепенно размываться.(Cocos2d-x) Есть ли какие-либо действия, которые могут размыть Sprite?

Я думаю, что могу изменить Texture2D для выполнения задания, но, похоже, Texture2D не может быть изменен.

Итак, что мне делать?

ответ

0

У вас есть три варианта:

1) сделать размытый фон в фотошопе (быстрый и простой, но дополнительный размер),

2) использовать затенение (не так просто и размытости тяжелой операции),

3) перерисовать (на лету) ваш фон, сделав его новой текстурой. Вот мой пост, как рисовать на текстуре:

http://discuss.cocos2d-x.org/t/is-it-possible-to-erase-some-pixels-from-a-sprite/34460/5?u=piotrros

Зная это вот функция от моего проекта, который размывает одно изображение (массив данных) в другой один:

void Sample::blur(unsigned char* inputData, unsigned char* outputData, float r) { 
    int R2 = pow(r + 2, 2); 
    for(int i = 0; i < canvasHeight; i++){ 
     for(int j = 0; j < canvasWidth; j++) { 
      int val1 = 0; 
      int val2 = 0; 
      int val3 = 0; 
      int val4 = 0; 

      int index2 = (j + (canvasHeight - i - 1) * canvasWidth) * 4; 

      for(int iy = i - r; iy < i + r + 1; iy++){ 
       for(int ix = j - r; ix < j + r + 1; ix++) { 

        int x = CLAMP(ix, 0, canvasWidth - 1); 
        int y = CLAMP(iy, 0, canvasHeight - 1); 

        int index = (x + (canvasHeight - y - 1) * canvasWidth) * 4; 

        val1 += inputData[index]; 
        val2 += inputData[index + 1]; 
        val3 += inputData[index + 2]; 
        val4 += inputData[index + 3]; 
       } 
      } 

      outputData[index2] = val1/R2; 
      outputData[index2 + 1] = val2/R2; 
      outputData[index2 + 2] = val3/R2; 
      outputData[index2 + 3] = val4/R2; 
     } 
    } 
} 

Только помните, это размытие - тяжелая и продолжительная операция, поэтому, если у вас есть большое изображение, это может занять некоторое время.

1

Вы можете использовать шейдер для этого. Вы можете получить простой размытости шейдер из Кокосовые тестового проекта, как это:

#ifdef GL_ES 
precision mediump float; 
#endif 

varying vec4 v_fragmentColor; 
varying vec2 v_texCoord; 

uniform vec2 resolution; 
uniform float blurRadius; 
uniform float sampleNum; 

vec4 blur(vec2); 

void main(void) 
{ 
vec4 col = blur(v_texCoord); //* v_fragmentColor.rgb; 
gl_FragColor = vec4(col) * v_fragmentColor; 
} 

vec4 blur(vec2 p) 
{ 
    if (blurRadius > 0.0 && sampleNum > 1.0) 
    { 
     vec4 col = vec4(0); 
     vec2 unit = 1.0/resolution.xy; 

     float r = blurRadius; 
     float sampleStep = r/sampleNum; 

     float count = 0.0; 

     for(float x = -r; x < r; x += sampleStep) 
     { 
      for(float y = -r; y < r; y += sampleStep) 
      { 
       float weight = (r - abs(x)) * (r - abs(y)); 
       col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)) * weight; 
       count += weight; 
      } 
     } 

     return col/count; 
    } 

    return texture2D(CC_Texture0, p); 
} 

Если вы не знаете, как добавить пользовательские шейдеры на ваш спрайт - вот пример! Вы расширяете класс Sprite:

class MySpriteBlur : public Sprite { 
public: 
    ~MySpriteBlur(); 
    bool initWithTexture(Texture2D* texture, const Rect& rect); 
    void initGLProgram(); 
    static MySpriteBlur *create(const char *pszFileName); 
    void setBlurRadius(float radius); 
    void setBlurSampleNum(float num); 
protected: 
    float _blurRadius; 
    float _blurSampleNum; 
}; 

А затем реализовать его:

MySpriteBlur::~MySpriteBlur() { 
} 
MySpriteBlur* MySpriteBlur::create(const char *pszFileName) { 
    MySpriteBlur* pRet = new (std::nothrow) MySpriteBlur(); 
    if (pRet && pRet->initWithFile(pszFileName)) { 
     pRet->autorelease(); 
    } else { 
     CC_SAFE_DELETE(pRet); 
    } 
    return pRet; 
} 
bool MySpriteBlur::initWithTexture(Texture2D* texture, const Rect& rect) { 
    _blurRadius = 0; 
    if (Sprite::initWithTexture(texture, rect)) { 
#if CC_ENABLE_CACHE_TEXTURE_DATA 
     auto listener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom* event) { 
      initGLProgram(); 
     }); 
     _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); 
#endif 
     initGLProgram(); 
     return true; 
    } 
    return false; 
} 
void MySpriteBlur::initGLProgram() { 
    std::string fragSource = FileUtils::getInstance()->getStringFromFile(
     FileUtils::getInstance()->fullPathForFilename("shaders/example_blur.fsh")); 
    auto program = GLProgram::createWithByteArrays(ccPositionTextureColor_noMVP_vert, fragSource.data()); 
    auto glProgramState = GLProgramState::getOrCreateWithGLProgram(program); 
    setGLProgramState(glProgramState); 
    auto size = getTexture()->getContentSizeInPixels(); 
    getGLProgramState()->setUniformVec2("resolution", size); 
    getGLProgramState()->setUniformFloat("blurRadius", _blurRadius); 
    getGLProgramState()->setUniformFloat("sampleNum", 7.0f); 
} 
void MySpriteBlur::setBlurRadius(float radius) { 
    _blurRadius = radius; 
    getGLProgramState()->setUniformFloat("blurRadius", _blurRadius); 
} 
void MySpriteBlur::setBlurSampleNum(float num) { 
    _blurSampleNum = num; 
    getGLProgramState()->setUniformFloat("sampleNum", _blurSampleNum); 
} 

Надеются, что поможет!