V.4 Shaders. Create a ProgramState?

Hi,
I’m trying to port my old GL shader program to V.4. The doc says:

Create a backend::ProgramState object with ProgramState(const std::string& vertexShader, const std::string& fragmentShader)

Well, I’m stuck here. I don’t seem to have this constructor. I tried to have a look around cocos to spy how it’s done, but I’ve had no luck in finding examples of loading shaders from files.

What do I do? I must be missing something obvious!

Edit: Should I subclass Program?
Also:

Metal uses MSL as the shader development language. 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.

Does this mean that my GL shaders will automatically be adapted to Metal without me having to rewrite them?

Hi,
you can take a look at this https://github.com/cocos2d/cocos2d-x/blob/v4/tests/cpp-tests/Classes/ShaderTest/ShaderTest.cpp#L477

And yes, that’s right.

1 Like

Thanks a lot!
I’ll check it out. Although I tried with cocos2d::backend::Device previously, getting a strange error “No member named ‘Device’ in namespace ‘cocos2d::backend’”, even though everything seems to be in place (backend.h includes Device.h so I should have it). Compiling for iOS/Xcode11.5.
I’ll get back to you when I get it right.

Edit: of course. Wrong include. Grrr.

Super! Now my shaders load, hooray!
Except they fail to convert to Metal ( Can not get metal shader:).
I’ll mark your answer as a solution as soon as I’m sure I don’t want to ask any more questions :).

@kalika06
There are a few factors that i’ve came across which result in that error.

  • initializing uniforms (eg uniform int u_var1 = 0;), which is not allowed
  • using uniforms within a global function (outside on main()), which is also not allowed.
  • gl_position in your vertex shader has been used in an operation that involves half4. (refer to my post here)

i can only think of these for now… i remember back then i could let it print out the error but somehow don’t remember the steps already. :sweat_smile:

@kalika06
Hi, i’m just facing the same issue right now.
@Darren is talking about a trick to get more verbose log.
Add NSLog(@"%s", glslopt_get_log(glslShader)); at line 52 at cocos/renderer/backend/metal/ShaderModuleMTL.mm then build again.
It is showing optimisation logs that may help debug.

In my case to illustrate, it is showing glsl errors like :
(1,1): error: syntax error, unexpected $end

1 Like

Thank you guys, you’ve both been more than very helpful :slight_smile:

Thanks to you both, I’ve managed to port the shaders for my Sprite. Here’s the code and some additional hints, in case someone finds them helpful:

    std::string vertexSource = cocos2d::FileUtils::getInstance()->getStringFromFile(cocos2d::FileUtils::getInstance()->fullPathForFilename(“file/path/shader.vsh"));
    std::string fragSource = cocos2d::FileUtils::getInstance()->getStringFromFile(cocos2d::FileUtils::getInstance()->fullPathForFilename(“file/path/shader.fsh”));

    auto program = cocos2d::backend::Device::getInstance()->newProgram(vertexSource, fragSource);
    auto programState = new cocos2d::backend::ProgramState(program); 

    setProgramState(programState);
    
    SET_UNIFORM(_programState, "u_PMatrix", cocos2d::Director::getInstance()->getMatrix(cocos2d::MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION));
    
	// (…)
   	// set some custom uniforms here…

    auto res = getTexture()->getContentSizeInPixels();
    SET_UNIFORM(_programState, "u_resolution", res);
    
    CC_SAFE_RELEASE(programState);
    CC_SAFE_RELEASE(program);

The shader files are located in the Resources folder.
Also:

  • CC_Texture0 became u_texture (declared as uniform sampler2D u_texture; in the fragment shader)
  • CC_PMatrix became u_PMatrix (declared as uniform mat4 u_PMatrix; in the vertex shader)
    And other stuff, in case anyone needs it, has changed naming in a similar way.
1 Like

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