With v4, built-in shaders are cached, but custom shaders are not, so you will need to cache the shaders yourself if required. Also, be mindful of the fact that they no longer have autorelease()
called on them, and since you create them via new
, so you will either need to either call autorelease()
on the custom Program/ProgramState
yourself, or just handle them using retain()/release()
calls.
For example:
ProgramState* CreateProgramStateFromFragment(const std::string& fragmentShaderPath)
{
const auto fileUtils = cocos2d::FileUtils::getInstance();
const auto fragmentFullPath = fileUtils->fullPathForFilename(fragmentShaderPath);
const auto fragSource = fileUtils->getStringFromFile(fragmentFullPath);
const auto program = cocos2d::backend::Device::getInstance()->newProgram(cocos2d::positionTextureColor_vert, fragSource);
const auto programState = new (std::nothrow) ProgramState(program);
// Program must be released if no longer used, since it is not auto-released
CC_SAFE_RELEASE(program);
return programState;
}
// and this is how you use it
const auto programState = CreateProgramStateFromFragment("path/to/example_shader.frag");
// say it has a float as a uniform variable
float myFloat = 1.0f;
auto myUniformLocation = programState->getUniformLocation("u_myUniformVariable");
programState->setUniform(myUniformLocation, &myFloat, sizeof(myFloat));
sprite->setProgramState(programState);
CC_SAFE_RELEASE(programState); // required since Sprite::setProgramState() calls 'retain' on it, so the reference count goes to 2, and since it is not auto-released, we need to release it here to bring it back to reference count of 1.
Now, if you call clone()
on a ProgramState, then you would also need to release the object after assigning it to anything that calls retain()
on it, like a sprite:
auto clonedProgramState = programState->clone();
sprite->setProgramState(clonedProgramState);
auto uLocation = clonedProgramState->getUniformLocation("u_myUniformVariable");
clonedProgramState->setUniform(uLocation, &myFloat, sizeof(myFloat));
CC_SAFE_RELEASE(clonedProgramState); // required since Sprite::setProgramState() calls 'retain' on it, so the reference count goes to 2, and since it is not auto-released, we need to release it here to bring it back to reference count of 1.
Anyhow, I hope that helps.
EDIT: Fixed up some mistakes in my initial description of the release/retain
requirements.