SPH粒子的某些属性未在Compute Shader中更新

时间:2019-05-11 09:27:35

标签: c# unity3d compute-shader

我目前正在研究Unity3D中使用SPH进行流体动力学的论文,并且已经使基本算法起作用。

现在,我正尝试使用Compute Shader对其进行优化。

每个粒子都需要相邻的粒子来更新其密度和压力。使用基本的单线程算法,粒子按原样流动。但是,当我将代码移至计算着色器时,每个粒子之间都不会发生冲突。

这是我的工作单线程代码

// Working Single Thread
for (int i = 0; i < particles.Length; i++)
{
    particles[i].density = 0.0f;

    for (int j = 0; j < particles.Length; j++)
    {
        Vector3 rij = particles[j].position - particles[i].position;
        float r2 = rij.sqrMagnitude;

        if (r2 < parameters.smoothingRadiusSq)
        {
            particles[i].density += parameters.particleMass * (315.0f / (64.0f * Mathf.PI * Mathf.Pow(parameters.smoothingRadius, 9.0f))) * Mathf.Pow(parameters.smoothingRadiusSq - r2, 3.0f);
        }
    }

    particles[i].pressure = GAS_CONST * (particles[i].density - parameters.restDensity);
}

这些是我使用计算着色器进行的优化尝试

// file.cs
void InitBuffer(){
    kernel = densityPressureComputation.FindKernel("ComputeDensityPressure");
    buffer = new ComputeBuffer(particles.Length, 56);

    buffer.SetData(particles);

    densityPressureComputation.SetBuffer(kernel, "Result", buffer);
    densityPressureComputation.SetFloat("GAS_CONST", GAS_CONST);
    densityPressureComputation.SetFloat("smoothingRadius", parameters.smoothingRadius);
    densityPressureComputation.SetFloat("smoothingRadiusSq", parameters.smoothingRadiusSq);
    densityPressureComputation.SetFloat("restDensity", parameters.restDensity);
    densityPressureComputation.SetFloat("particleMass", parameters.particleMass);
}

void Update(){
    buffer.SetData(particles);
    densityPressureComputation.Dispatch(kernel,16,16,1);        
    buffer.GetData(particles);
}
// file.compute
int currID = id.x + id.y * (16*16);
Result[currID].density = 0.0;
for (int j = 0; j < Result.Length; j++)
{
    float3 rij = Result[j].position - Result[currID].position;
    float r2 = rij * rij;

    if (r2 < smoothingRadiusSq)
    {
        Result[currID].density += particleMass * (315.0 / (64.0 * 3.14 * pow(smoothingRadius, 9))) * pow(smoothingRadiusSq - r2, 3);
    } 
}
Result[currID].pressure = GAS_CONST * (Result[currID].density - restDensity);

使用有效的单线程代码,模拟将按预期进行,碰撞正在起作用,重力在起作用,等等。

但是使用Compute Shader代码,虽然重力工作得很好,但每个粒子之间的碰撞却不起作用,粒子只是相互穿过。

0 个答案:

没有答案