В настоящее время я работаю над диссертацией о гидродинамике с использованием SPH в Unity3D, и у меня уже работает базовый алгоритм.
Сейчас я пытаюсь оптимизировать его с помощью 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, в то время как гравитация работает просто отлично, столкновение между частицами не работает, частицы просто проходили друг через друга.