Float RealisticCamera::GenerateRay(const CameraSample &sample, Ray *ray) const { ProfilePhase prof(Prof::GenerateCameraRay); ++totalRays; // Find point on film, _pFilm_, corresponding to _sample.pFilm_ Point2f s(sample.pFilm.x / film->fullResolution.x, sample.pFilm.y / film->fullResolution.y); Point2f pFilm2 = film->GetPhysicalExtent().Lerp(s); Point3f pFilm(-pFilm2.x, pFilm2.y, 0); // Trace ray from _pFilm_ through lens system Float exitPupilBoundsArea; Point3f pRear = SampleExitPupil(Point2f(pFilm.x, pFilm.y), sample.pLens, &exitPupilBoundsArea); Ray rFilm(pFilm, pRear - pFilm, Infinity, Lerp(sample.time, shutterOpen, shutterClose)); if (!TraceLensesFromFilm(rFilm, ray)) { ++vignettedRays; return 0; } // Finish initialization of _RealisticCamera_ ray *ray = CameraToWorld(*ray); ray->d = Normalize(ray->d); ray->medium = medium; // Return weighting for _RealisticCamera_ ray Float cosTheta = Normalize(rFilm.d).z; Float cos4Theta = (cosTheta * cosTheta) * (cosTheta * cosTheta); if (simpleWeighting) return cos4Theta; else return (shutterClose - shutterOpen) * (cos4Theta * exitPupilBoundsArea) / (LensRearZ() * LensRearZ()); }
// EnvironmentCamera Method Definitions EnvironmentCamera:: EnvironmentCamera(const Transform &world2cam, float hither, float yon, float sopen, float sclose, Film *film) : Camera(world2cam, hither, yon, sopen, sclose, film) { rayOrigin = CameraToWorld(Point(0,0,0)); }
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 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; }
// OrthographicCamera Definitions Float OrthographicCamera::GenerateRay(const CameraSample &sample, Ray *ray) const { ProfilePhase prof(Prof::GenerateCameraRay); // Compute raster and camera sample positions Point3f pFilm = Point3f(sample.pFilm.x, sample.pFilm.y, 0); Point3f pCamera = RasterToCamera(pFilm); *ray = Ray(pCamera, Vector3f(0, 0, 1)); // Modify ray for depth of field if (lensRadius > 0) { // Sample point on lens Point2f pLens = lensRadius * ConcentricSampleDisk(sample.pLens); // Compute point on plane of focus Float ft = focalDistance / ray->d.z; Point3f pFocus = (*ray)(ft); // Update ray for effect of lens ray->o = Point3f(pLens.x, pLens.y, 0); ray->d = Normalize(pFocus - ray->o); } ray->time = Lerp(sample.time, shutterOpen, shutterClose); ray->medium = medium; *ray = CameraToWorld(*ray); return 1; }
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::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; }
// EnvironmentCamera Method Definitions float EnvironmentCamera::GenerateRay(const CameraSample &sample, Ray *ray) const { float time = Lerp(sample.time, shutterOpen, shutterClose); // Compute environment camera ray direction float theta = M_PI * sample.imageY / film->yResolution; float phi = 2 * M_PI * sample.imageX / film->xResolution; Vector dir(sinf(theta) * cosf(phi), cosf(theta), sinf(theta) * sinf(phi)); *ray = Ray(Point(0,0,0), dir, 0.f, INFINITY, time); CameraToWorld(*ray, ray); return 1.f; }
Spectrum PerspectiveCamera::Sample_Wi(const Interaction &ref, const Point2f &u, Vector3f *wi, Float *pdf, Point2f *pRaster, VisibilityTester *vis) const { // Uniformly sample a lens interaction _lensIntr_ Point2f pLens = lensRadius * ConcentricSampleDisk(u); Point3f pLensWorld = CameraToWorld(ref.time, Point3f(pLens.x, pLens.y, 0)); Interaction lensIntr(pLensWorld, ref.time, medium); lensIntr.n = Normal3f(CameraToWorld(ref.time, Vector3f(0, 0, 1))); // Populate arguments and compute the importance value *vis = VisibilityTester(ref, lensIntr); *wi = lensIntr.p - ref.p; Float dist = wi->Length(); *wi /= dist; // Compute PDF for importance arriving at _ref_ // Compute lens area of perspective camera Float lensArea = lensRadius != 0 ? (Pi * lensRadius * lensRadius) : 1; *pdf = (dist * dist) / (AbsDot(lensIntr.n, *wi) * lensArea); return We(lensIntr, -*wi, pRaster); }
Float OrthographicCamera::GenerateRayDifferential(const CameraSample &sample, RayDifferential *ray) const { ProfilePhase prof(Prof::GenerateCameraRay); // Compute main orthographic viewing ray // Compute raster and camera sample positions Point3f pFilm = Point3f(sample.pFilm.x, sample.pFilm.y, 0); Point3f pCamera = RasterToCamera(pFilm); *ray = RayDifferential(pCamera, Vector3f(0, 0, 1)); // Modify ray for depth of field if (lensRadius > 0) { // Sample point on lens Point2f pLens = lensRadius * ConcentricSampleDisk(sample.pLens); // Compute point on plane of focus Float ft = focalDistance / ray->d.z; Point3f pFocus = (*ray)(ft); // Update ray for effect of lens ray->o = Point3f(pLens.x, pLens.y, 0); ray->d = Normalize(pFocus - ray->o); } // Compute ray differentials for _OrthographicCamera_ if (lensRadius > 0) { // Compute _OrthographicCamera_ ray differentials accounting for lens // Sample point on lens Point2f pLens = lensRadius * ConcentricSampleDisk(sample.pLens); Float ft = focalDistance / ray->d.z; Point3f pFocus = pCamera + dxCamera + (ft * Vector3f(0, 0, 1)); ray->rxOrigin = Point3f(pLens.x, pLens.y, 0); ray->rxDirection = Normalize(pFocus - ray->rxOrigin); pFocus = pCamera + dyCamera + (ft * Vector3f(0, 0, 1)); ray->ryOrigin = Point3f(pLens.x, pLens.y, 0); ray->ryDirection = Normalize(pFocus - ray->ryOrigin); } else { ray->rxOrigin = ray->o + dxCamera; ray->ryOrigin = ray->o + dyCamera; ray->rxDirection = ray->ryDirection = ray->d; } ray->time = Lerp(sample.time, shutterOpen, shutterClose); ray->hasDifferentials = true; ray->medium = medium; *ray = CameraToWorld(*ray); return 1; }
Float PerspectiveCamera::GenerateRayDifferential(const CameraSample &sample, RayDifferential *ray) const { ProfilePhase prof(Prof::GenerateCameraRay); // Compute raster and camera sample positions Point3f pFilm = Point3f(sample.pFilm.x, sample.pFilm.y, 0); Point3f pCamera = RasterToCamera(pFilm); Vector3f dir = Normalize(Vector3f(pCamera.x, pCamera.y, pCamera.z)); *ray = RayDifferential(Point3f(0, 0, 0), dir); // Modify ray for depth of field if (lensRadius > 0) { // Sample point on lens Point2f pLens = lensRadius * ConcentricSampleDisk(sample.pLens); // Compute point on plane of focus Float ft = focalDistance / ray->d.z; Point3f pFocus = (*ray)(ft); // Update ray for effect of lens ray->o = Point3f(pLens.x, pLens.y, 0); ray->d = Normalize(pFocus - ray->o); } // Compute offset rays for _PerspectiveCamera_ ray differentials if (lensRadius > 0) { // Compute _PerspectiveCamera_ ray differentials accounting for lens // Sample point on lens Point2f pLens = lensRadius * ConcentricSampleDisk(sample.pLens); Vector3f dx = Normalize(Vector3f(pCamera + dxCamera)); Float ft = focalDistance / dx.z; Point3f pFocus = Point3f(0, 0, 0) + (ft * dx); ray->rxOrigin = Point3f(pLens.x, pLens.y, 0); ray->rxDirection = Normalize(pFocus - ray->rxOrigin); Vector3f dy = Normalize(Vector3f(pCamera + dyCamera)); ft = focalDistance / dy.z; pFocus = Point3f(0, 0, 0) + (ft * dy); ray->ryOrigin = Point3f(pLens.x, pLens.y, 0); ray->ryDirection = Normalize(pFocus - ray->ryOrigin); } else { ray->rxOrigin = ray->ryOrigin = ray->o; ray->rxDirection = Normalize(Vector3f(pCamera) + dxCamera); ray->ryDirection = Normalize(Vector3f(pCamera) + dyCamera); } ray->time = Lerp(sample.time, shutterOpen, shutterClose); ray->medium = medium; *ray = CameraToWorld(*ray); ray->hasDifferentials = true; return 1; }
float EnvironmentCamera::GenerateRay(const Sample &sample, Ray *ray) const { ray->o = rayOrigin; // Generate environment camera ray direction float theta = M_PI * sample.imageY / film->yResolution; float phi = 2 * M_PI * sample.imageX / film->xResolution; Vector dir(sinf(theta) * cosf(phi), cosf(theta), sinf(theta) * sinf(phi)); CameraToWorld(dir, &ray->d); // Set ray time value ray->time = Lerp(sample.time, ShutterOpen, ShutterClose); ray->mint = ClipHither; ray->maxt = ClipYon; 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; }
float RealisticCamera::GenerateRay(const CameraSample &sample, Ray *ray) const { // Generate raster and back lens samples Point Praster(sample.imageX, sample.imageY, 0.f); Point Pcamera; RasterToCamera(Praster, &Pcamera); const Lens &backLens = lensgroup.back(); float lensU, lensV, lensZ; // Get Sample Pback (lensU, lensV, -distToBack) // Method 1: pbrt-v2 provide ConcentricSampleDisk(sample.lensU, sample.lensV, &lensU, &lensV); lensU *= backLensAperture; lensV *= backLensAperture; lensZ = -distToBack; // Method 2: textbook, r = \sqrt{lensU}, theta = 2 \pi lensV //float r = sqrtf(sample.lensU), theta = 2 * M_PI * sample.lensV; //lensU = backLens.aperture * r * cosf(theta); //lensV = backLens.aperture * r * sinf(theta); //lensZ = -distToBack; // Method 3: textbook refer common error sampling, r = lensU, theta = 2 \pi lensV //float r = sample.lensU, theta = 2 * M_PI * sample.lensV; //lensU = backLens.aperture * r * cosf(theta); //lensV = backLens.aperture * r * sinf(theta); //lensZ = -distToBack; // camera -> inner lens -> outer lens // hit point on the surface of the inner lens ray->o = Pcamera; ray->d = Normalize(Point(lensU, lensV, lensZ) - Pcamera); ray->time = Lerp(sample.time, shutterOpen, shutterClose); ray->mint = 0.f; // iterator over the lens components from inner to outer for (int i = lensgroup.size() - 1; i >= 0; i--) { if (lensgroup[i].end) { // ray run pass aperture (not lens) float deltaZ = lensgroup[i].z - ray->o.z; ray->o = ray->o + (deltaZ / ray->d.z) * ray->d; if (lensgroup[i].outOfRange(ray->o.x, ray->o.y)) return 0.f; } else { float n = (i == 0) ? 1.f : lensgroup[i-1].n; if (!lensgroup[i].Refraction(ray, n)) return 0.f; } } // set exposure weight float cosTheta = Dot(Normalize(ray->o - Pcamera), Vector(0, 0, 1)); float Z = filmdistance; float weight = (backLens.aperture * backLens.aperture * M_PI) / ( Z * Z); weight = weight * cosTheta * cosTheta * cosTheta * cosTheta; ray->maxt = (yon - hither) / ray->d.z; CameraToWorld(*ray, ray); ray->d = Normalize(ray->d); return weight; }