Я пытаюсь портировать smallpt: Global Illumination в 99 строк C ++ на C#, и я получаю эту странную ошибку, когда свет отражается от рассеянной поверхности. У кого-нибудь есть идея, откуда может возникнуть проблема?
Это то, что я получаю с 40 сэмплами
Это то, что должно выглядеть как
Это мой код для диффузных поверхностей:
if(sphere.Reflection == Sphere.ReflectionType.DIFFUSE)
{
double angleRand = random.NextDouble(seed) *2f*Math.PI;
double distanceRand = random.NextDouble(seed);
double distanceRandSqtr = Math.Sqrt(distanceRand);
Vector3 w = surfaceNormal;
Vector3 u = Vector3.Normalize(Vector3.Cross(Math.Abs(w.X) > .1 ? new Vector3(0f, 1f, 0f) : new Vector3(1f, 0f, 0f), w));
Vector3 v = Vector3.Cross(w, u);
Vector3 ref1 = Vector3.Multiply(u, (float)Math.Cos(angleRand));
ref1 = Vector3.Multiply(ref1, (float)distanceRandSqtr);
Vector3 ref2 = Vector3.Multiply(v, (float)Math.Sin(angleRand));
ref2 = Vector3.Multiply(ref2, (float)distanceRandSqtr);
Vector3 ref3 = Vector3.Multiply(w, (float)Math.Sqrt(1 - distanceRand));
Vector3 ref4 = Vector3.Add(ref1, ref2);
ref4 = Vector3.Add(ref4, ref3);
Vector3 reflectionRayRand = Vector3.Normalize(ref4);
Vector3 nextRadiance = ComputeRadiance(new Ray(intersectionPoint, reflectionRayRand), depth, seed);
Vector3 result = Vector3.Multiply(color, nextRadiance);
result = Vector3.Add(sphere.Emission, result);
if (float.IsNaN(result.X) || float.IsNaN(result.Y) || float.IsNaN(result.Z))
{
throw new Exception();
}
return result;
}
А это оригинал:
if (obj.refl == DIFF){ // Ideal DIFFUSE reflection
double r1=2*M_PI*erand48(Xi), r2=erand48(Xi), r2s=sqrt(r2);
Vec w=nl, u=((fabs(w.x)>.1?Vec(0,1):Vec(1))%w).norm(), v=w%u;
Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm();
return obj.e + f.mult(radiance(Ray(x,d),depth,Xi));}