20

グリッド上の一連のスプライトの下に影を作成したいゲームに取り組んでいます。影はスプライト自体よりも大きく、スプライトはアニメーション化されます (つまり、移動と回転)。

それらを単にスプライトpngにレンダリングすることはできません。そうしないと、影が隣接するスプライトに重なってしまいます。

また、影を下のレイヤーに単独で配置することもできません。影が重なると、交点に暗い帯ができるからです。

これらのスプライトはアニメーション化されるため、まとめてレンダリングすることはできません。

基本的には、スプライトのシャドウをブレンドして、設定した不透明度で最大になるようにしたいと考えています。例:

ここに画像の説明を入力

これは、(Rs,Gs,Bs,Max(As,Ds)) の openGL ブレンドと同等であると考えています。R、G、および B は、src では常に同じ色であるため、あまり気にしません。そしてdst。

ただし、これは有効な openGL ブレンド モードではありません。特にcocos2d-iphoneでこれを達成する簡単な方法はありますか?

シャドウ スプライトを不透明にしてから、両方を親スプライトに適用し、親スプライトの不透明度を 40% にすることで、これに近づけることができます。ただし、cocos2d の動作では、結合されたスプライト イメージではなく、各子の不透明度を 40% に設定するだけで、結果として同じストライプになります。

4

1 に答える 1

22

OK、よく調べてみると、自分の考えの誤りに気づいたと思います。

まず、Max Alpha openGLブレンディングを行う方法があり、それはglBlendEquationsを使用しています。これを行うには、drawメソッドを変更し(そして、textureNodeにこれらのメソッドを切り替えるための新しい属性を作成し)、次のいずれかを使用する必要があります。

 glBlendEquationOES( GL_MAX_EXT );
 glBlendEquationSeparateOES( GL_FUNC_ADD_OES, GL_MAX_EXT );

1つ目はRGBAにmax()を使用し、2つ目はRGBに標準加算を使用し、alphaにmax()を使用します。

ここで問題となるのは、各スプライトとその子がzオーダーで画面に描画されることです。これは、最初のシャドウが描画された後、それがメイン画面バッファの一部であることを意味します。つまり、不透明度が変更され、max()ブレンドと標準の不透明な背景で、背景にペイントされるようになりました。次のシャドウを描画すると、max(As、1)が1になります。背景は不透明です。だから私は私が望むブレンドを達成していません。背景が透明であれば「機能」しますが、その「背後」に背景を適用することはできず、バッファに追加することしかできません。

max()ブレンドを使用して最初にシャドウを描画し、次に{ONE_MINUS_DST_ALPHA、DST_ALPHA}glBlendを実行できます。これは問題のない回避策ですが、これを困難にする他の問題があります。

さて、私がついに気付いた本当の解決策は、RenderTextureを使用して、シャドウを背景に適用する前に別のバッファーにレンダリングすることです。これはパフォーマンスに影響を与える可能性があるため、これがどこに行くのかを見ていきます。

アップデート:

OK、私は今、実用的な解決策を持っています。

奇妙なことに、結局、この解決策は必要ありませんでした。私の特定のケースでは、バンディングが努力を正当化するほど目立たなかったためですが、これは私が思いついた解決策であり、私が望んでいたことを実行しているようです。

  1. まず、画面全体に0%の黒のアルファpngを描画します。(これが必要かどうかはわかりません。画面のデフォルトのアルファが何であるかわかりません)。

  2. glEquationSeperateOES( GL_ADD, GL_MAX_ENT)とを使用して画面に影を描きますglBlend( GL_ONE, GL_ONE )。これにより、説明したように、アルファのmax()を使用して、すべてのシャドウがブレンドされます。

    • 黒に合成しているので、を使用するのと同じglBlendEquationOES( GL_MAX_ENT )です。(X + 0 == max(X、0))

    • glBlend( GL_ZERO, GL_ONE )ステップ1の必要性、または少なくともそのレイヤーが0%黒である必要性を排除します。 GL_ZERO基本的に、0%の黒になります。

  3. 影のにある床を描画しますが、を使用しますglBlend( ONE_MINUS_DST_ALPHA, DST_ALPHA )。これにより、で床に影を追加した場合とまったく同じ結果になりglBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA )ますが、この方法で追加した場合、影をブレンドすることはできません(回答の上部にある理由をお読みください)。

  4. これで完了です。このメソッドの良いところは、別のrenderTextureで「visit」を呼び出すことなく、シャドウスプライトを通常どおりにアニメーション化できることです。

残り:

また、CocosNodeを変更して、別のCocosNodeにリンクするシャドウをレイヤーに追加できるようにしました。このように、シャドウは床の子としてレンダリングされます(または、シャドウブレンディングの場合は0%の黒の背景スプライト)が、別のCocosNodeにリンクされます。スプライトが移動すると、シャドウがある場合は、シャドウの位置も更新されます。これにより、画面上のすべてのオブジェクトの下にすべての影を配置し、影を自動的にオブジェクトに追従させることができます。

長い答えでごめんなさい。たぶん私の解決策は厄介ですが、それはうまくいくようです。

于 2010-01-27T07:28:17.223 に答える