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 是作为浮点数的鼠标指针 (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 )。这是解决您的问题的一种可能方法

我将从片段着色器开始,将弹力施加到粒子上,以便它们或多或少地被约束到球体的表面。像这样的东西:

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 个中心点和半径的浮点数。粒子在开始时设置为随机位置,并朝着映射到位置数组的 alpha 值的数组中的数字移动。

我的目标是从 openCV 传递 blob 数据,并将球体映射到相机源上的人。

目前在视觉上真的很无趣,因此需要使用速度纹理来添加粒子的行为。

于 2012-11-04T17:16:01.783 回答