Can't get my scene to blur or shaders to work on v4

Hi, I’m building a pause menu for a game. When paused, I want the scene to get blurred and become sort of a background for a few buttons that should appear on top of it. However, getting this blurring action to work has been quite the challenge. First, I just googled how to do it, which led me to this stack overflow post and I, thus figured I need OpenGL shaders to get that to work (or at least that’s what I understood from that). Upon further inspection, the answer on that thread has been written to with a version of cocos2d-x different from that which I’m using (v4.0) and, therefore, the code is not compatible. Then, I found out about this page from the official cocos2d-x v4.0 documentation, which states the whole OpenGL Shader API has been “kind of substituted” by an abstraction layer, which should grant compatibility with Metal shaders. The page also links to two examples (here and here) on how to get shaders to work under this new API.

Example 1 states that I need to build a cocos2d::backend::ProgramState, using this constructor:

ProgramState(const std::string& vertexShader, const std::string& fragmentShader)

But, when I tried that piece of code, the compiler (G++) threw and error, which stated that no such constructor existed. So I ran this command on my shell:

grep -re "ProgramState::ProgramState" ./cocos2d/

Which should find all constructors available for this class. It returned only, these two, both of which didn’t match the documentation:

ProgramState::ProgramState(Program* program)
ProgramState::ProgramState()

Then I went ahead and grepped for the signature given on the docs, like so:

grep -re "(const std::string& vertexShader, const std::string& fragmentShader)" ./cocos2d/

And ended up finding these entries:

Program* DeviceMTL::newProgram(const std::string& vertexShader, const std::string& fragmentShader)
Program* DeviceGL::newProgram(const std::string& vertexShader, const std::string& fragmentShader)

Which, I think, could be used to make the shaders i want to work to actually work, should I write one version for Metal and one version for OpenGL. However, that “v4 Upgrade Guide” from earlier stated that:

In principle, the graphics API under any platform is not allowed to be used directly except for the source code under the two folders metal and OpenGL.

and that:

To support the OpenGL ES shader running on the Metal framework, V4 uses glsl-optimizer to convert the OpenGL ES shader to a Metal MSL shader.

So how can I actually get my scene to blur as described above? Am I missing some detail or is the only way to do it actually write two shaders? Do I even need shaders or is this task doable without them?

Those documentation links may not have been updated with the most recent changes to the shader code in V4, and it’s perhaps not a good idea to be grepping for the exact function signatures in the code.

Check the cpp-tests project, specifically the ShaderTest.cpp file.

One important difference between v3 and v4 is that the Program and ProgramState are no longer automatically released (via autorelease()), so make sure you free the memory associated with them at the right time. The code in ShaderTest.cpp shows you how and when to do this.

This post may help.

2 Likes

Hi, thanks for replying! Where can I find this cpp-tests project?

In your cocos2d-x root/tests

1 Like

Dude thank you SO MUCH for pointing me to those resources! I’ve been stuck on this challenge for DAYS and now, thanks to you, it FINALLY WORKS!!

For those who are in a similar trouble in the future, void SpriteBlur::initProgram() from this example file is basically all the code you need for your blurring/shading action to work. Oh and be mindful, like @R101 said in the post he linked, to CC_SAFE_RELEASE properly.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.