2

GPU ベースのパーティクル システムを使用しています。1024*1024 テクスチャの RGB 値として x、y、z 位置を渡すことによって計算された 100 万個のパーティクルがあります。速度についても同じことが行われています。

それらを任意の点から球上の点に移動させようとしています。

計算に使用している現在のシェーダーは、あるポイントから別のポイントに直接移動しています。

現在、質量または速度のテクスチャは使用していません。

// float mass   = texture2D( posArray, texCoord.st).a;
vec3 p      = texture2D( posArray, texCoord.st).rgb;
// vec3 v       = texture2D( velArray, texCoord.st).rgb;

// map into 'cinder space'
p = (p * - 1.0) + 0.5;

// vec3 acc = -0.0002*p; // Centripetal force
// vec3 ayAcc  = 0.00001*normalize(cross(vec3(0, 1 ,0),p)); // Angular force
// vec3 new_v  = v + mass*(acc+ayAcc);

vec3 new_p = p + ((moveToPos - p) / duration);

// map out of 'cinder space'
new_p = (new_p - 0.5) * -1.0;

gl_FragData[0] = vec4(new_p.x, new_p.y, new_p.z, mass);
//gl_FragData[1] = vec4(new_v.x, new_v.y, new_v.z, 1.0);

moveToPos は、浮動小数点 (0.0f > 1.0f) としてのマウス ポインターです。座標系は (0.5,0.5 > -0.5,-0.5) から (0.0,0.0 > 1.0,1.0) に変換されます。

私はベクトル数学にまったく慣れていないので、計算が混乱しています。次の式を使用する必要があることはわかっています。

x=Rsinϕcosθ

y=Rsinφsinθ

z=Rcosφ

しかし、 moveToPos(xyz) > p(xyz) から角度を計算することは問題のままです

4

2 に答える 2

1

この GPU パーティクル シェーダのオリジナル バージョンは数年前に作成しました (現在は @: https://github.com/num3ric/Cinder-Particles )。これがあなたの問題に対する1つの可能なアプローチです。

フラグメント シェーダーでパーティクルにスプリング フォースを適用することから始めて、パーティクルが多かれ少なかれ球の表面に拘束されるようにします。このようなもの:

uniform sampler2D posArray;
uniform sampler2D velArray;
varying vec4 texCoord;

void main(void)
{   
    float mass  = texture2D( posArray, texCoord.st).a;
    vec3 p      = texture2D( posArray, texCoord.st).rgb;
    vec3 v      = texture2D( velArray, texCoord.st).rgb;

    float x0    = 0.5; //distance from center of sphere to be maintaned
    float x     = distance(p, vec3(0,0,0)); // current distance
    vec3 acc    = -0.0002*(x - x0)*p; //apply spring force (hooke's law)

    vec3 new_v  = v + mass*(acc);
    new_v = 0.999*new_v; // friction to slow down velocities over time
    vec3 new_p  = p + new_v;

    //Render to positions texture
    gl_FragData[0] = vec4(new_p.x, new_p.y, new_p.z, mass);
    //Render to velocities texture
    gl_FragData[1] = vec4(new_v.x, new_v.y, new_v.z, 1.0);
}

vec3 uniform次に、同じ半径の球と交差するマウス位置に新しい値を渡します (Cinder のシェーダーの外側で行われます)。

これを前のソフト スプリング コンストレイントと組み合わせます。この引力点に向かって接線力を追加できます。単純な加速度から始めて、(mousePos - p)クロス積を使用してこの力を完全に接線にする方法を見つけます。

ここで球座標アプローチがどのように機能するかはわかりません。

x=Rsinϕcosθ

y=Rsinϕsinθ

z=Rcosφ

ϕ と θ はどこで得られますか? テクスチャは、デカルト座標で位置と速度を保存します。さらに、前後に変換することは実際にはオプションではありません。

ベクトルに慣れていない場合、私の説明は高度すぎる可能性があります。残念ながら、シェーダーとパーティクル アニメーションは本質的に非常に数学的です。

于 2012-10-21T11:47:40.143 に答える
1

これが私が解決した解決策です - それは機能しますが、球体の中心点をそれら自身の境界の外に移動すると、粒子が失われます。

#define NPEOPLE 5

uniform sampler2D posArray;
uniform sampler2D velArray;

uniform vec3 centerPoint[NPEOPLE];
uniform float radius[NPEOPLE];
uniform float duration;

varying vec4 texCoord;

void main(void) {

    float personToGet   = texture2D( posArray, texCoord.st).a;
    vec3 p              = texture2D( posArray, texCoord.st).rgb;

    float mass          = texture2D( velArray, texCoord.st).a;
    vec3 v              = texture2D( velArray, texCoord.st).rgb;

    // map into 'cinder space'
    p = (p * - 1.0) + 0.5;

    vec3 vec_p = p - centerPoint[int(personToGet)];
    float len_vec_p = sqrt( ( vec_p.x * vec_p.x ) + (vec_p.y * vec_p.y) + (vec_p.z * vec_p.z) );
    vec_p = ( ( radius[int(personToGet)] /* mass */ ) / len_vec_p ) * vec_p;
    vec3 new_p = ( vec_p + centerPoint[int(personToGet)] );
    new_p = p + ( (new_p - p) / (duration) );

    // map out of 'cinder space'
    new_p = (new_p - 0.5) * -1.0;

    vec3 new_v = v;

    gl_FragData[0] = vec4(new_p.x, new_p.y, new_p.z, personToGet);
    gl_FragData[1] = vec4(new_v.x, new_v.y, new_v.z, mass);
}

5 つの vec3f の配列と、5 つの中心点と半径としてマップされた float を渡しています。パーティクルは最初にランダムな位置で設定され、位置配列のアルファ値にマップされた配列内の数値に向かって移動します。

私の目的は、openCV からブロブ データを渡し、その球体をカメラ フィード上の人物にマッピングすることです。

現時点では視覚的にまったく面白くないので、Velocity テクスチャを使用してパーティクルの動作を追加する必要があります。

于 2012-11-04T17:16:01.783 に答える