【问题标题】:(Cocos2d-x) Is there any action can blur a Sprite?(Cocos2d-x) 有没有什么动作可以模糊一个Sprite?
【发布时间】:2017-01-24 02:30:45
【问题描述】:

我添加了一个 Sprite 作为背景。 现在我希望我的 Sprite 可以逐渐变得模糊。

我想我可以修改 Texture2D 来完成这项工作,但似乎不能修改 Texture2D。

那么,我该怎么办?

【问题讨论】:

    标签: opengl textures cocos2d-x


    【解决方案1】:

    您可以为此使用着色器。您可以从 cocos 测试项目中获取简单的模糊着色器,如下所示:

    #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);
    }
    

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      您有三个选择:

      1) 在 Photoshop 中制作模糊背景(快速简单,但需要额外的尺寸),

      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;
              }
          }
      }
      

      请记住,模糊是繁重且耗时的操作,因此如果您的图像很大,可能需要一段时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-01-05
        • 1970-01-01
        • 2012-05-23
        • 2014-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-24
        相关资源
        最近更新 更多