2012-10-17 46 views
2

我正在使用基於GPU的粒子系統。 通過在x,y,z位置傳遞1024 * 1024紋理上的rgb值來計算一百萬個粒子。他們的速度也一樣。從一個點移動到一個點上球體

我試圖讓他們從任意點移動到球體上的點。

我用於計算的我當前的着色器正在直接從一個點移動到另一個點。

我不使用的質量或速度紋理此刻

// 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被鼠標指針爲float(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)的剩餘一個問題

回答

1

幾年前我寫了這個GPU顆粒着色器的原始版本(現在@:https://github.com/num3ric/Cinder-Particles)。這裏是一個可能的方法到你的問題。

我會從一個片段着色器開始,將一個彈力施加到這些粒子上,這樣它們或多或少都會被約束到一個球體的表面。事情是這樣的:

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); 
} 

然後,我會通過一個新的vec3uniform爲鼠標位置上交叉相同的半徑(以煤渣着色器外完成)的球體。

現在,結合這與以前的軟彈簧約束。你可以爲這個吸引點增加一個切向力。以簡單的(mousePos - p)加速開始,然後找出一種方法,使用交叉產品完全切線。

我不確定球面座標方法在這裏如何工作。

X =Rsinφcosθ

Y =Rsinφsinθ

Z =Rcosφ

你從哪裏得到φ和θ?紋理以笛卡爾座標存儲位置和速度。另外,來回轉換並不是真正的選擇。

如果您對矢量不熟悉,我的解釋可能會過於高級。不幸的是,着色器和粒子動畫本質上是非常數學的。

+0

感謝您的回覆。我其實有點工作。角度的計算在着色器中通過trig - 計算從當前粒子位置到鼠標pos(作爲球體的中心)的一條線,並移向與該線相交的球體上的點。令人驚歎的煤渣代碼工作BTW。我發現煤渣的工作環境要比openframeworks更清潔。但正如我剛剛說的,剛開始使用OpenGL – thepaperboy

+0

酷,那麼你應該在這裏發佈你的着色器作爲你的問題的答案(它甚至可能是部分工作)。我完全有興趣查看/測試使用球座標的方法。 – num3ric

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箇中心點和半徑。 粒子在開始時隨機位置設置,並移動到陣列中映射到位置數組的alpha值的數字。

我的目標是從openCV傳入blob數據,並將這些球體映射到攝像頭上的人物。

目前它在視覺上確實很沒趣,因此需要使用速度紋理來增加粒子的行爲。

+0

剛剛意識到我並沒有在這個版本中使用球座標,它比這更簡單。我確實有一個版本,我在哪裏! – thepaperboy

相關問題