cocos2d-xでETCのアルファマスクをシェーダを使って実装する際にArmatureで苦戦したので残しておこうと思います。
とりあえず調べた限りは日本語による記事は存在しなかったので何か役に立てば嬉しい。
(なお中国語の記事はあった模様。というかそれを参考にした。)
とりあえず書いてみた
hoge.cpp
// 初期化系統の処理内にぶち込む
void onEnter()
{
// 頂点シェーダとフラグメントシェーダを使ってシェーダを作成
auto shader = GLProgram::creatWithByteArrays();
auto shader_state = GLProgramState::getOrCreateWithGLProgram(shader);
// 自前のシェーダをセット
setCustomShader(shader_state, getChildren());
}
// シェーダセット
void setCustomShader(GLProgramState *glpstate, Vector<Node*>& childrens)
{
if(chidrens.empty()) return;
for(auto& child : childrens)
{
// 再帰
setCustomShader(glpstate, dhild->getChildren());
// dynamic_castでSpriteに
auto sp = dynamic_cast<Sprite*>(child);
// nullptrじゃなければシェーダ突っ込む
if(sp != nullptr){
sp->setGLProgramState(glpstate);
}
}
}
と上記の書き方で基本的には対応出来たけど、Armatureだけ見事にマスク効いてない。
どうやらArmatureは違うらしい。
Armatureの中を潜っていくと...
いた。
Armature -> Bone -> DecorativeDisplay -> Node に対してシェーダ突っ込まないと駄目らしい。
なので
auto arm = dynamic_cast<Armature*>(child);
auto& map = arm->getBoneDic();
for(auto& entry : map){
auto bone = entry.second;
if(bone != nullptr){
auto list = bone->getDisplayManager()->getDecortaiveDisplayList();
for(auto dd : list){
dd->getDisplay()->setGLProgramState(glpstate);
}
}
}
という感じで対応すると、Armatureに対してシェーダが反応しました。
もっと良い記述に出来ると思うけど、まぁ多少はね?
記事投稿初めてなのでこういう書き方でいいか分かりませんが、
とりあえず今回はこんな感じで。