How to efficiently blur Scene Background [C++] [Shader]

Hello Cocos2dx Community,

I want to show a MessageBox in the UI-Layer of the Scene. Somethimes the MessageBox Colors and the Colors of the Scene Background are almost identical (dark)… so the MessageBox is not enough “highlighted”.

How do I blur the complete Background-Layer of the Scene efficiently? I found a few glsl shaders… some made the Game very slow :-/

1 Like

I also tried to blur a layer by rendering it into a RenderTexture and applying a shader to it.
But it also slowed down my game and I found no solution to fix it.

But if you have no movement in your background layer while the MessageBox is on screen you can create the blurred background just once (not every frame) and keep it as long as your MessageBox is visible.

Alternatively you could just overlap your background layer with a semi transparent white layer to seperate your foreground and background colors.

1 Like

The Background Layer has movements :-/
Right now I have implemented the “overlapping” Solution. like you wrote above! It’s okay!

But Games like Rayman, Super Mario Run and some other has blurred (dynamic) BG’s. Possibly these are Unity Games… but that should be possible with Cocos2dx (even on older Devices.)

Hmmmmmm

A couple thoughts: you could shrink your rendering framebuffer (cocos2d::experimental) while the message box is displayed. You could also try the RenderTexture approach again, but create it with 1/2 or 1/4 resolution (to reduce shader load from large fill rate). You may also want to also lower the framerate, say 30fps instead of 60 (or even 15fps), etc.

1 Like

These are some good ideas @stevetranby!
I’ll try these in a few days.

@MuratAlbayrak Did you make any progress on this topic?

@RobinK I tired it with igormats suggestions. With most of my Shaders it possible to create a Fullscreen Effect (on Mobiles too). Most of the blur Shaders that I found so far are to slow for mobiles.

I kept the solution with the additonal semi transparent Layer. For a Messageboxs Background it’s okay.

There are some other solutions like 1. creating all needed blurred SpriteFrames at initialisation and save them on device. 2. faking Real-time Blur. There are some LibGDX / Java solutions. In my case it would be to much effort just for a msg background!

Hey! You really need to reduce your FrameBuffer size and then scale the texture to the whole screen to improve the performance in case it’s shader works slow!

@igormats I’m currently working on other Parts of my Project so I’m answering a little late… but I reviewed my Blurred-Layer Code again.

The Framebuffer Size is -50%. The FPS drops down to 15-19 fps (with the default Cocos2dx Blur-Shader) .
Second strange behaviour is, that all Animations are running much faster than before. even without Shaders. why? Are Animations Frames get skipped?

I would be glad for any Help.

// Sizes
auto size = Director::getInstance()->getWinSize();
const Size _sizeInPixels = Director::getInstance()->getWinSizeInPixels();
Size _framebufferSize = Size(_sizeInPixels.width * 0.5f, _sizeInPixels.height * 0.5f);

// Framebuffer
auto _renderTarget = cocos2d::experimental::RenderTarget::create(_framebufferSize.width, _framebufferSize.height);
auto _depthStencil = experimental::RenderTargetDepthStencil::create(_framebufferSize.width, _framebufferSize.height);
auto _frameBuffer = cocos2d::experimental::FrameBuffer::create(1, _framebufferSize.width, _framebufferSize.height);

_frameBuffer->attachRenderTarget(_renderTarget);
_frameBuffer->attachDepthStencilTarget(_depthStencil);
_frameBuffer->setClearColor(Color4F(0.0f, 0.0f, 0.0f, 1.0f));

// Camera
cocos2d::Camera* _camera = cocos2d::Camera::create();
_camera->setFrameBufferObject(_frameBuffer);
_camera->setLocalZOrder(1);
_camera->setCameraFlag(CameraFlag::USER1);
this->addChild(_camera);

// Texture
auto _texture = this->m_frameBuffer->getRenderTarget()->getTexture();

// Render-Sprite
auto _renderSprite = cocos2d::Sprite::createWithTexture(_texture);
_renderSprite->setScale(2.0f);
_renderSprite->setFlippedY(true);
_renderSprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE);
_renderSprite->setPosition( Vec2(size.width * 0.5f, size.height * 0.5f) ); //
_renderSprite->setLocalZOrder(1);
this->addChild(_renderSprite);

// create Shader
...
auto renderspriteSize = renderSprite->getTexture()->getContentSizeInPixels();

glprogramstate->setUniformVec2("resolution", renderspriteSize);
glprogramstate->setUniformFloat("blurRadius", 10.0f);
glprogramstate->setUniformFloat("sampleNum", 2.0f);
...

// Apply to _renderSprite
...

Sorry, but I don’t know. To little information :’(