Пример #1
0
        /// <summary>
        /// Generates a ray from a position in the image into the scene
        /// </summary>
        /// <param name="filmPos">
        ///     Position on the film plane: integer pixel coordinates and fractional position within
        /// </param>
        /// <param name="rng">
        ///     Random number generator used to sample additional decisions (lens position for depth of field)
        /// </param>
        /// <returns>The sampled camera ray and related information like PDF and contribution</returns>
        public override CameraRaySample GenerateRay(Vector2 filmPos, RNG rng)
        {
            Debug.Assert(Width != 0 && Height != 0);

            // Transform the direction from film to world space.
            // The view space is vertically flipped compared to the film.
            var view     = new Vector3(2 * filmPos.X / Width - 1, 1 - 2 * filmPos.Y / Height, 0);
            var localDir = Vector3.Transform(view, viewToCamera);
            var dirHomo  = Vector4.Transform(new Vector4(localDir, 0), cameraToWorld);
            var dir      = new Vector3(dirHomo.X, dirHomo.Y, dirHomo.Z);

            // Compute the camera position
            var pos = Vector3.Transform(new Vector3(0, 0, 0), cameraToWorld);

            var ray = new Ray {
                Direction = Vector3.Normalize(dir), MinDistance = 0, Origin = pos
            };

            // Sample depth of field
            float pdfLens = 1;

            if (lensRadius > 0)
            {
                var lensSample = rng.NextFloat2D();
                var lensPos    = lensRadius * SampleWarp.ToConcentricDisc(lensSample);

                // Intersect ray with focal plane
                var focalPoint = ray.ComputePoint(focalDistance / ray.Direction.Z);

                // Update the ray
                ray.Origin    = new Vector3(lensPos, 0);
                ray.Direction = Vector3.Normalize(focalPoint - ray.Origin);

                pdfLens = 1 / (MathF.PI * lensRadius * lensRadius);
            }

            return(new CameraRaySample {
                Ray = ray,
                Weight = RgbColor.White,
                Point = new SurfacePoint {
                    Position = Position, Normal = Direction
                },
                PdfRay = SolidAngleToPixelJacobian(pos + dir) * pdfLens,
                PdfConnect = pdfLens
            });
        }