Ejemplo n.º 1
0
        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);
        }