3

ポイント スプライトを使用して花火を実装し、花火を 2 つの異なるテクスチャにレンダリングしてトレイルを描画し、アルファを 1 未満に設定して 1 秒おきに描画し、以前の各描画をますますフェードアウトさせようとしています。

見栄えが良く、以前にレンダリングしたテクスチャを描画するときに使用するアルファに応じて、予想どおり、軌跡が長くなったり短くなったりします。ただし、ほとんどのデバイス (すべてではない) では、軌跡が完全に消えることはありません。それらは、消えるはずだった後、非常に透明ですが、まだ目立つ痕跡を残します。

これは私が現在していることです:

second というブール値に応じて、buff1 と buff2 という 2 つのテクスチャのいずれかにレンダリングするようにフレーム バッファを設定します。

((GL11ExtensionPack)gl).glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, myFBO.get(0));
if (second){
    ((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, buff2.texture.textureId, 0);
} else {
    ((GL11ExtensionPack)gl).glFramebufferTexture2DOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, GL10.GL_TEXTURE_2D, buff1.texture.textureId, 0);
}
gl.glViewport(0, 0, bufferSize, bufferSize);
gl.glClearColor(0, 0, 0, 0);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

次に、アルファ値 < 1 を使用して、以前に描画したテクスチャを現在のテクスチャにレンダリングします。buff オブジェクトは、テクスチャでクワッドを描画する単なるヘルパーです。draw 関数は、アルファを他のカラー チャネルに事前乗算します。

// a = alpha, higher value = longer trails = more distinct leftovers
if (second){
    buff1.setColor(1, 1, 1, a);
    buff1.draw(gl);
    second = false;
else {
    buff2.setColor(1, 1, 1, a);
    buff2.draw(gl);
    second = true;
}

その後、点スプライト花火の描画を行います。また、あらかじめ乗算されたアルファと gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); を使用します。

最後に、フレーム バッファをリセットし、古いトレイル フェードを含む新しいテクスチャを作成し、現在の花火を 100% アルファで描画します。次に、このテクスチャを使用して、花火テクスチャの前後にある他のすべてのオブジェクトと一緒にシーンに描画します。

私が言ったように、ほとんどすべてが機能していますが、トレイルが消えた後も残っているほとんど透明なトレイルを除いて. 前のバッファを描画するアルファ値が高いほど、永遠に残るトレイル「残り物」がより目立ちます。

私はさまざまなブレンディング モード、事前に乗算されたものと事前に乗算されていないアルファなどを試してきました。

私は何を間違っていますか?これを行うより良い方法はありますか?

助けてくれてありがとう、アンダース

4

1 に答える 1

2

私は何を間違っていますか?

縮小された (値で) 画像を合計する方法は、実質的にアルファ値を指数化するベキ級数です。このようなベキ級数はゼロに漸近しますが、ゼロに到達することはありません。

これを行うより良い方法はありますか?

実はこれが正しいやり方です。最後の手順を 1 つ忘れただけです。特定のアルファ値を下回る値がゼロにクランプされるように、しきい値を追加する必要があります。これは、GL_GREATER アルファ テストを追加することで最も簡単に取得できます。しきい値は、削除したいトレイルのアルファ値よりわずかに高くなります。

于 2012-07-05T11:19:28.440 に答える