Example #1
0
        public override float GenerateRay(CameraSample sample, out Ray ray)
        {
            // Generate raster and camera samples
            Point Pras = new Point(sample.ImageX, sample.ImageY, 0);
            Point Pcamera = RasterToCamera.TransformPoint(ref Pras);
            ray = new Ray(new Point(0, 0, 0), Vector.Normalize((Vector) Pcamera), 0.0f);
            // Modify ray for depth of field
            if (LensRadius > 0.0f)
            {
                // Sample point on lens
                float lensU, lensV;
                MonteCarloUtilities.ConcentricSampleDisk(sample.LensU, sample.LensV, out lensU, out lensV);
                lensU *= LensRadius;
                lensV *= LensRadius;

                // Compute point on plane of focus
                float ft = FocalDistance / ray.Direction.Z;
                Point Pfocus = ray.Evaluate(ft);

                // Update ray for effect of lens
                ray.Origin = new Point(lensU, lensV, 0.0f);
                ray.Direction = Vector.Normalize(Pfocus - ray.Origin);
            }
            ray.Time = sample.Time;
            ray = CameraToWorld.TransformRay(ray);
            return 1.0f;
        }
Example #2
0
        private void DoIntersect(Ray ray, Func<GridVoxel, bool> callback)
        {
            // Check ray against overall grid bounds
            float rayT;
            if (_bounds.Inside(ray.Evaluate(ray.MinT)))
                rayT = ray.MinT;
            else if (!_bounds.TryIntersect(ray, out rayT))
                return;
            Point gridIntersect = ray.Evaluate(rayT);

            // Set up 3D DDA for ray
            float[] NextCrossingT = new float[3], DeltaT = new float[3];
            int[] Step = new int[3], Out = new int[3], Pos = new int[3];
            for (int axis = 0; axis < 3; ++axis)
            {
                // Compute current voxel for axis
                Pos[axis] = PosToVoxel(ref gridIntersect, axis);
                if (ray.Direction[axis] >= 0)
                {
                    // Handle ray with positive direction for voxel stepping
                    NextCrossingT[axis] = rayT + (VoxelToPos(Pos[axis] + 1, axis) - gridIntersect[axis]) / ray.Direction[axis];
                    DeltaT[axis] = _width[axis] / ray.Direction[axis];
                    Step[axis] = 1;
                    Out[axis] = _numVoxels[axis];
                }
                else
                {
                    // Handle ray with negative direction for voxel stepping
                    NextCrossingT[axis] = rayT + (VoxelToPos(Pos[axis], axis) - gridIntersect[axis]) / ray.Direction[axis];
                    DeltaT[axis] = -_width[axis] / ray.Direction[axis];
                    Step[axis] = -1;
                    Out[axis] = -1;
                }
            }

            // Walk ray through voxel grid
            while (true)
            {
                // Check for intersection in current voxel and advance to next
                var voxel = _voxels[Offset(Pos[0], Pos[1], Pos[2])];
                if (voxel != null)
                    if (callback(voxel))
                        break;

                // Advance to next voxel

                // Find _stepAxis_ for stepping to next voxel
                int bits = (((NextCrossingT[0] < NextCrossingT[1]) ? 1 : 0) << 2) +
                    (((NextCrossingT[0] < NextCrossingT[2]) ? 1 : 0) << 1) +
                    (((NextCrossingT[1] < NextCrossingT[2]) ? 1 : 0));
                int stepAxis = CmpToAxis[bits];
                if (ray.MaxT < NextCrossingT[stepAxis])
                    break;
                Pos[stepAxis] += Step[stepAxis];
                if (Pos[stepAxis] == Out[stepAxis])
                    break;
                NextCrossingT[stepAxis] += DeltaT[stepAxis];
            }
        }
Example #3
0
        public virtual float Pdf(Point p, Vector wi)
        {
            // Intersect sample ray with area light geometry
            var ray = new Ray(p, wi, 1e-3f);
            ray.Depth = -1; // temporary hack to ignore alpha mask
            float thit, rayEpsilon;
            DifferentialGeometry dgLight;
            if (!TryIntersect(ray, out thit, out rayEpsilon, out dgLight))
                return 0.0f;

            // Convert light sample weight to solid angle measure
            float pdf = Point.DistanceSquared(p, ray.Evaluate(thit)) / (Normal.AbsDot(dgLight.Normal, -wi) * Area);
            if (float.IsInfinity(pdf))
                pdf = 0.0f;
            return pdf;
        }
Example #4
0
        public override Point Sample(Point p, float u1, float u2, out Normal ns)
        {
            // Compute coordinate system for sphere sampling
            Point Pcenter = ObjectToWorld.TransformPoint(Point.Zero);
            Vector wc = Vector.Normalize(Pcenter - p);
            Vector wcX, wcY;
            Vector.CoordinateSystem(wc, out wcX, out wcY);

            // Sample uniformly on sphere if $\pt{}$ is inside it
            if (Point.DistanceSquared(p, Pcenter) - _radius * _radius < 1e-4f)
                return Sample(u1, u2, out ns);

            // Sample sphere uniformly inside subtended cone
            float sinThetaMax2 = _radius * _radius / Point.DistanceSquared(p, Pcenter);
            float cosThetaMax = MathUtility.Sqrt(Math.Max(0.0f, 1.0f - sinThetaMax2));
            DifferentialGeometry dgSphere;
            float thit, rayEpsilon;
            Point ps;
            Ray r = new Ray(p, MonteCarloUtilities.UniformSampleCone(u1, u2, cosThetaMax, ref wcX, ref wcY, ref wc),
                1e-3f);
            if (!TryIntersect(r, out thit, out rayEpsilon, out dgSphere))
                thit = Vector.Dot(Pcenter - p, Vector.Normalize(r.Direction));
            ps = r.Evaluate(thit);
            ns = (Normal) Vector.Normalize(ps - Pcenter);
            if (ReverseOrientation)
                ns *= -1.0f;
            return ps;
        }