// OrthographicCamera Definitions OrthoCamera::OrthoCamera(const AnimatedTransform &cam2world, const float screenWindow[4], float sopen, float sclose, float lensr, float focald, Film *f) : ProjectiveCamera(cam2world, Orthographic(0., 1.), screenWindow, sopen, sclose, lensr, focald, f) { // Compute differential changes in origin for ortho camera rays dxCamera = RasterToCamera(Vector(1, 0, 0)); dyCamera = RasterToCamera(Vector(0, 1, 0)); }
// PerspectiveCamera Method Definitions PerspectiveCamera:: PerspectiveCamera(const AnimatedTransform &cam2world, const float screenWindow[4], float sopen, float sclose, float lensr, float focald, float fov, Film *f) : ProjectiveCamera(cam2world, Perspective(fov, 1e-2f, 1000.f), screenWindow, sopen, sclose, lensr, focald, f) { // Compute differential changes in origin for perspective camera rays dxCamera = RasterToCamera(Point(1,0,0)) - RasterToCamera(Point(0,0,0)); dyCamera = RasterToCamera(Point(0,1,0)) - RasterToCamera(Point(0,0,0)); }
// PerspectiveCamera Method Definitions PerspectiveCamera:: PerspectiveCamera(const Transform &cam2world, const Rectangle &screenWindow, photonflow::Time sopen, photonflow::Time sclose, photonflow::Length lensr, photonflow::Length focald, double fov, std::shared_ptr<Film> f) : ProjectiveCamera(cam2world, perspective(fov, 1e-2f, 1000.0), screenWindow, sopen, sclose, lensr, focald, f) { // Compute differential changes in origin for perspective camera rays dxCamera = RasterToCamera(Point3D(1.0_um,0.0_um,0.0_um)) - RasterToCamera(Point3D(0.0_um,0.0_um,0.0_um)); dyCamera = RasterToCamera(Point3D(0.0_um,1.0_um,0.0_um)) - RasterToCamera(Point3D(0.0_um,0.0_um,0.0_um)); }
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::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 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; }
// PerspectiveCamera Method Definitions PerspectiveCamera::PerspectiveCamera(const AnimatedTransform &CameraToWorld, const Bounds2f &screenWindow, Float shutterOpen, Float shutterClose, Float lensRadius, Float focalDistance, Float fov, Film *film, const Medium *medium) : ProjectiveCamera(CameraToWorld, Perspective(fov, 1e-2f, 1000.f), screenWindow, shutterOpen, shutterClose, lensRadius, focalDistance, film, medium) { // Compute differential changes in origin for perspective camera rays dxCamera = (RasterToCamera(Point3f(1, 0, 0)) - RasterToCamera(Point3f(0, 0, 0))); dyCamera = (RasterToCamera(Point3f(0, 1, 0)) - RasterToCamera(Point3f(0, 0, 0))); // Compute image plane bounds at $z=1$ for _PerspectiveCamera_ Point2i res = film->fullResolution; Point3f pMin = RasterToCamera(Point3f(0, 0, 0)); Point3f pMax = RasterToCamera(Point3f(res.x, res.y, 0)); pMin /= pMin.z; pMax /= pMax.z; A = std::abs((pMax.x - pMin.x) * (pMax.y - pMin.y)); }
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; }