それでは、最初にパーティクルの実装にアプローチする方法を見てみましょう。Sprite
単一のパーティクルを表す抽象クラスがあります。
protected void draw(GLAutoDrawable gLDrawable) {
// each sprite has a different blending function.
changeBlendingFunc(gLDrawable);
// getting the quad as an array of length 4, containing vectors
Vector[] bb = getQuadBillboard();
GL gl = gLDrawable.getGL();
// getting the texture
getTexture().bind();
// getting the colors
float[] rgba = getRGBA();
gl.glColor4f(rgba[0],rgba[1],rgba[2],rgba[3]);
//draw the sprite on the computed quad
gl.glBegin(GL.GL_QUADS);
gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3d(bb[0].x, bb[0].y, bb[0].z);
gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3d(bb[1].x, bb[1].y, bb[1].z);
gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3d(bb[2].x, bb[2].y, bb[2].z);
gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3d(bb[3].x, bb[3].y, bb[3].z);
gl.glEnd();
}
ここでは、ほとんどのメソッド呼び出しがかなり理解できますが、驚くことではありません。レンダリングは非常に簡単です。このdisplay
方法では、最初にすべての不透明なオブジェクトを描画し、次にすべてのオブジェクトを取得してSprite
並べ替え(カメラからの平方距離)、次に粒子を描画して、カメラから離れた場所に最初に描画します。しかし、ここでさらに詳しく調べなければならないのは、メソッドgetQuadBillboard
です。各パーティクルは、次のように、カメラの位置に垂直な平面に「座る」必要があることを理解できます。
このような垂直平面を計算する方法は難しくありません。
カメラの位置からパーティクルの位置をサブストラクチャして、平面に垂直なベクトルを取得し、それを正規化して、平面の法線として使用できるようにします。これで、平面は法線と位置によって厳密に定義されます。これは、現在の位置です(粒子の位置は、平面が通過する点です)。
Y
平面上のカメラのベクトルの投影を正規化することにより、クワッドの「高さ」を計算します。次の計算により、射影されたベクトルを取得できます。H = cam.Y - normal * (cam.Y dot normal)
計算により、クワッドの「幅」を作成しますW = H cross normal
4つのポイント/ベクトルを返します。{position+H+W,position+H-W,position-H-W,position-H+W}
しかし、すべてのスプライトがそのように機能するわけではなく、一部は垂直ではありません。たとえば、衝撃波リングスプライト、またはフライングスパーク/スモークトレイル:
各スプライトは独自の「看板」を提供する必要がありました。ところで、スモークトレイルとフライングスプライトスパークの計算も少し困難でした。別の抽象クラスを作成しました。これを次のように呼びますLineSprite
。ここでの説明はスキップします。ここでコードを確認できます:LineSprite
。
さて、この最初の試みは素晴らしかったが、予期しない問題があった。これが問題を説明するスクリーンショットです。
ご覧のとおり、スプライトは互いに交差しているため、交差する2つのスプライトを見ると、1番目のスプライトの一部が2番目のスプライトの後ろにあり、別の部分が前にあります。 2番目のスプライト。これにより、交差点の線が表示される奇妙なレンダリングが発生しました。を無効glDepthMask
にしても、パーティクルをレンダリングすると、各スプライトで異なるブレンドが行われるため、結果には交差線が表示されることに注意してください。そのため、どういうわけかスプライトが交差しないようにする必要がありました。私たちが持っていたアイデアは本当にクールでした。
あなたはこれらすべての本当にクールな3Dストリートアートを知っていますか?これがその考えを強調する画像です:

このアイデアはゲームに実装できると考えたので、スプライトは互いに交差しません。これがアイデアを説明するための画像です:

基本的に、すべてのスプライトを平行な平面上に配置したため、交差は発生しませんでした。そして、それは同じままだったので、目に見えるデータには影響しませんでした。他のすべての角度からは、それは引き伸ばされたように見えますが、カメラの観点からは、それでも素晴らしく見えました。したがって、実装の場合:
クワッドビルボードを表す4つのベクトルとパーティクルの位置を取得する場合、元のクワッドビルボードを表す4つのベクトルの新しいセットを出力する必要があります。これを行う方法のアイデアは、ここでうまく説明されています:平面と線の交点。カメラの位置によって定義される「線」と、4つのベクトルのそれぞれがあります。カメラZ
ベクトルを法線として使用できるため、平面とパーティクルの位置があります。また、スプライトを並べ替えるための比較関数に小さな変更が加えられます。これで、カメラの正規直交基底によって定義される同次行列を使用する必要があります。実際、計算は計算と同じくらい簡単です。cam.getZ_Vector().getX()*pos.getX() + cam.getZ_Vector().getY()*pos.getY() + cam.getZ_Vector().getZ()*pos.getZ();
。もう1つ注意しなければならないのは、パーティクルがカメラの視野角から外れている場合、つまりカメラの後ろにある場合、パーティクルを表示したくないことです。特に、パーティクルの投影を計算したくない場合があります(可能性があります)。いくつかの非常に奇妙でサイケデリックスな効果をもたらします...)。あとは最終Sprite
クラスを表示するだけです
結果は非常に良いです:

お役に立てば幸いです。この「記事」(またはゲーム:}についてコメントをお寄せください。探索、フォーク、使用が可能です...)