float OrthoCamera::GenerateRayDifferential(const CameraSample &sample, RayDifferential *ray) const { // Compute main orthographic viewing ray // Generate raster and camera samples PbrtPoint Pras(sample.imageX, sample.imageY, 0); PbrtPoint Pcamera; RasterToCamera(Pras, &Pcamera); *ray = RayDifferential(Pcamera, Vector(0,0,1), 0., INFINITY); // Modify ray for depth of field if (lensRadius > 0.) { // Sample point on lens float lensU, lensV; ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); lensU *= lensRadius; lensV *= lensRadius; // Compute point on plane of focus float ft = focalDistance / ray->d.z; PbrtPoint Pfocus = (*ray)(ft); // Update ray for effect of lens ray->o = PbrtPoint(lensU, lensV, 0.f); ray->d = Normalize(Pfocus - ray->o); } ray->time = Lerp(sample.time, shutterOpen, shutterClose); ray->rxOrigin = ray->o + dxCamera; ray->ryOrigin = ray->o + dyCamera; ray->rxDirection = ray->ryDirection = ray->d; ray->hasDifferentials = true; CameraToWorld(*ray, ray); return 1.f; }
double PerspectiveCamera::generateRay(const CameraSample &sample, Ray *ray) const { auto cameraLength = 1.0_um; // Generate raster and camera samples Point3D Pras(sample.imageX*cameraLength, sample.imageY*cameraLength, 0); Point3D Pcamera; RasterToCamera(Pras, &Pcamera); *ray = Ray(Point3D(), normalize(Length3D(Pcamera))); // Modify ray for depth of field if (lensRadius > 0.0_um) { // Sample point on lens double lensU, lensV; concentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); Length x = lensU * lensRadius; Length y = lensV * lensRadius; // Compute point on plane of focus double ft = focalDistance / ray->m_direction.z; Point3D Pfocus = (*ray)(ft); // Update ray for effect of lens ray->m_origin = Point3D(x, y, 0.0_um); ray->m_direction = normalize(Pfocus - ray->m_origin); } ray->m_time = sample.time; CameraToWorld(*ray, ray); return 1.f; }
float PerspectiveCamera::GenerateRayDifferential(const CameraSample &sample, RayDifferential *ray) const { // Generate raster and camera samples Point Pras(sample.imageX, sample.imageY, 0); Point Pcamera; RasterToCamera(Pras, &Pcamera); Vector dir = Normalize(Vector(Pcamera.x, Pcamera.y, Pcamera.z)); *ray = RayDifferential(Point(0,0,0), dir, 0.f, INFINITY); // Modify ray for depth of field if (lensRadius > 0.) { // Sample point on lens float lensU, lensV; ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); lensU *= lensRadius; lensV *= lensRadius; // Compute point on plane of focus float ft = focalDistance / ray->d.z; Point Pfocus = (*ray)(ft); // Update ray for effect of lens ray->o = Point(lensU, lensV, 0.f); ray->d = Normalize(Pfocus - ray->o); } // Compute offset rays for _PerspectiveCamera_ ray differentials ray->rxOrigin = ray->ryOrigin = ray->o; ray->rxDirection = Normalize(Vector(Pcamera) + dxCamera); ray->ryDirection = Normalize(Vector(Pcamera) + dyCamera); ray->time = Lerp(sample.time, shutterOpen, shutterClose); CameraToWorld(*ray, ray); ray->hasDifferentials = true; return 1.f; }
float PerspectiveCamera::GenerateRay(const CameraSample &sample, Ray *ray) const { // Generate raster and camera samples Point Pras(sample.imageX, sample.imageY, 0); Point Pcamera; RasterToCamera(Pras, &Pcamera); *ray = Ray(Point(0,0,0), Normalize(Vector(Pcamera)), 0.f, INFINITY); // Modify ray for depth of field if (lensRadius > 0.) { // Sample point on lens float lensU, lensV; ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); lensU *= lensRadius; lensV *= lensRadius; // Compute point on plane of focus float ft = focalDistance / ray->d.z; Point Pfocus = (*ray)(ft); // Update ray for effect of lens ray->o = Point(lensU, lensV, 0.f); ray->d = Normalize(Pfocus - ray->o); } ray->time = Lerp(sample.time, shutterOpen, shutterClose); CameraToWorld(*ray, ray); return 1.f; }
float OrthoCamera::GenerateRay(const Sample &sample, Ray *ray) const { // Generate raster and camera samples Point Pras(sample.imageX, sample.imageY, 0); Point Pcamera; RasterToCamera(Pras, &Pcamera); ray->o = Pcamera; ray->d = Vector(0,0,1); // Set ray time value ray->time = Lerp(sample.time, ShutterOpen, ShutterClose); // Modify ray for depth of field if (LensRadius > 0.) { // Sample point on lens float lensU, lensV; ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); lensU *= LensRadius; lensV *= LensRadius; // Compute point on plane of focus float ft = (FocalDistance - ClipHither) / ray->d.z; Point Pfocus = (*ray)(ft); // Update ray for effect of lens ray->o.x += lensU * (FocalDistance - ClipHither) / FocalDistance; ray->o.y += lensV * (FocalDistance - ClipHither) / FocalDistance; ray->d = Pfocus - ray->o; } ray->mint = 0.; ray->maxt = ClipYon - ClipHither; ray->d = Normalize(ray->d); CameraToWorld(*ray, ray); return 1.f; }
float RealisticCamera::GenerateRay(const CameraSample &sample, Ray *ray) const { // STEP 1 - generate first ray // use sample->imageX and sample->imageY to get raster-space coordinates of the sample point on the film. Point Pras(sample.imageX, sample.imageY, 0); Point Pcamera; RasterToCamera(Pras, &Pcamera); // use sample->lensU and sample->lensV to get a sample position on the lens float lensU, lensV; ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); lensU *= lens[lensnum - 1].apradius; lensV *= lens[lensnum - 1].apradius; float pfz = lens[lensnum - 1].centerz + sqrtf(lens[lensnum - 1].radiusSquard - lensU * lensU - lensV * lensV); Point Pfocus = Point(lensU, lensV, pfz); Vector Rdir = Normalize(Pfocus - Pcamera); ray->o = Pcamera; ray->d = Rdir; ray->time = Lerp(sample.time, shutteropen, shutterclose); // STEP 2 - ray through the lens Point Plens; for (int i = 0; i < lensnum; i++) { lensData ls = lens[i]; if ( ls.plane ){ float t = (ls.centerz - ray->o.z) / ray->d.z; float x = ray->o.x + t * ray->d.x; float y = ray->o.y + t * ray->d.y; if (x * x + y * y > ls.apradiusSquared) return 0.f; } else { // Find the intersection point Vector oc = ray->o - Point(0.f, 0.f, ls.centerz); float l1 = oc.LengthSquared(); float rz = Dot(oc, ray->d); float l2 = rz *rz - l1 + ls.radiusSquard; if (l2 < 0.f) return 0.f; float t = (ls.radius > 0.f) ? (-rz + sqrtf(l2)) : (-rz - sqrtf(l2)); Plens = ray->o + t * ray->d; if (Plens.x*Plens.x + Plens.y*Plens.y > ls.apradiusSquared) return 0.f; // calculate the refraction Vector N = (ls.radius > 0.f) ? Normalize(Point(0.f, 0.f, ls.centerz) - Plens) : Normalize(Plens - Point(0.f, 0.f, ls.centerz)); Vector I = ray->d; float c1, c2; c1 = -Dot(I, N); c2 = ls.nratioSquared - 1.f + c1 * c1; if (c2 < 0.f) return 0.f; c2 = c1 - sqrtf(c2); Vector T = (I + c2 * N) / ls.nratio; ray->o = Plens; ray->d = Normalize(T); } } ray->mint = cliphiter; ray->maxt = (clipyon - cliphiter) / ray->d.z; // STEP 3 - output the ray and weight CameraToWorld(*ray, ray); float weight = Dot(Normalize(Plens - Pcamera), Vector(0, 0, 1)); weight *= weight / totallength; weight *= weight * (lens[lensnum - 1].apradiusSquared * M_PI); return weight; }