我正在使用基于GPU的粒子系统。 通过将x,y,z位置作为rgb值传递到1024 * 1024纹理来计算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)仍然存在问题
答案 0 :(得分: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φ
你在哪里获得φ和θ?纹理以笛卡尔坐标存储位置和速度。另外,来回转换不是一个真正的选择。
如果你对矢量感到不舒服,我的解释可能会太高级了。不幸的是,着色器和粒子动画本质上是非常数学的。
答案 1 :(得分: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数据并将球体映射到相机Feed上的人物。
此刻在视觉上真的无趣,所以需要使用速度纹理来增加粒子的行为。