public Direction(Vector vector, Basis basis) { this.vector = vector; // assumed to be normalized this.cosTheta = Math.Max(0, Vector.Dot(basis.Normal, vector)); }
public Vector Emittance(Direction outgoing, Basis basis) { return(emittance); }
public static Vector Radiance(Ray ray) { const int MAX_BOUNCES = 10; Vector weights = new Vector(1.0f, 1.0f, 1.0f); Vector radiance = Vector.Zero; for (int bounce = 0; bounce < MAX_BOUNCES; ++bounce) { float distance; int hitSphere; if (!Intersect(ray, out hitSphere, out distance)) { break; } Sphere sphere = geometry[hitSphere]; IMaterial material = materials[hitSphere]; var hitPoint = Ray.PointAt(ray, distance); var basis = new Basis(sphere.Normal(hitPoint)); var outgoing = new Direction(-ray.Direction, basis); /* Include object emittance as light path */ radiance += weights * material.Emittance(outgoing, basis); /* Include point light source light paths */ foreach (var light in lights) { var pointToLight = light.position - hitPoint; var lightDistance = pointToLight.Length(); if (!Occlude(new Ray(hitPoint, pointToLight), 1e-4f, lightDistance)) { Direction incomimg = new Direction(pointToLight / lightDistance, basis); radiance += weights * material.BRDF(incomimg, outgoing, basis) * incomimg.CosTheta * light.intensity / (lightDistance * lightDistance); } } /* Russian roulette */ Vector weight = material.WeightPDF(outgoing, basis); float p = Math.Max(weight.X, Math.Max(weight.Y, weight.Z)); if (bounce > 2) { if (random.NextDouble() <= p) { weight /= p; } else { break; } } /* Update light path weights and prepare for next bounce */ weights *= weight; var newDir = material.SamplePDF(outgoing, basis, random); ray = new Ray(hitPoint, newDir); } return(radiance); }
public Vector SamplePDF(Direction outgoing, Basis basis, Random random) { return(2 * basis.Normal * outgoing.CosTheta - outgoing.Vector); }
public Vector WeightPDF(Direction outgoing, Basis basis) { return(this.reflection); }
public Vector BRDF(Direction incoming, Direction outgoing, Basis basis) { return(this.albedo / (float)Math.PI); }
public Vector WeightPDF(Direction outgoing, Basis basis) { return(this.albedo); }
public Vector BRDF(Direction incoming, Direction outgoing, Basis basis) { return(Vector.Zero); }