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()); }
real_t OrthoCamera::generateRay(const CameraSample &sample, HRay *ray) const { // generate raster and camera sample positions ponos::Point3 pFilm(sample.pFilm.x, sample.pFilm.y, 0); ponos::Point3 pCamera = rasterToCamera(pFilm); *ray = HRay(pCamera, ponos::vec3(0, 0, 1)); // modify ray for depth of field if (lensRadius > 0.) { // TODO pg 315 // sample point on lens // compute point on plane of focus // update ray for effect of lens } ray->time = ponos::lerp(sample.time, shutterOpen, shutterClose); // TODO ENABLE ray->medium = medium; cameraToWorld(*ray, ray); return 1; }
void RealisticCamera::TestExitPupilBounds() const { Float filmDiagonal = film->diagonal; static RNG rng; Float u = rng.UniformFloat(); Point3f pFilm(u * filmDiagonal / 2, 0, 0); Float r = pFilm.x / (filmDiagonal / 2); int pupilIndex = std::min((int)exitPupilBounds.size() - 1, (int)std::floor(r * (exitPupilBounds.size() - 1))); Bounds2f pupilBounds = exitPupilBounds[pupilIndex]; if (pupilIndex + 1 < (int)exitPupilBounds.size()) pupilBounds = Union(pupilBounds, exitPupilBounds[pupilIndex + 1]); // Now, randomly pick points on the aperture and see if any are outside // of pupil bounds... for (int i = 0; i < 1000; ++i) { Point2f pd = ConcentricSampleDisk( Point2f(rng.UniformFloat(), rng.UniformFloat())); pd *= RearElementRadius(); Ray testRay(pFilm, Point3f(pd.x, pd.y, 0.f) - pFilm); Ray testOut; if (!TraceLensesFromFilm(testRay, &testOut)) continue; if (!Inside(pd, pupilBounds)) { fprintf(stderr, "Aha! (%f,%f) went through, but outside bounds (%f,%f) - " "(%f,%f)\n", pd.x, pd.y, pupilBounds.pMin[0], pupilBounds.pMin[1], pupilBounds.pMax[0], pupilBounds.pMax[1]); RenderExitPupil( (Float)pupilIndex / exitPupilBounds.size() * filmDiagonal / 2.f, 0.f, "low.exr"); RenderExitPupil((Float)(pupilIndex + 1) / exitPupilBounds.size() * filmDiagonal / 2.f, 0.f, "high.exr"); RenderExitPupil(pFilm.x, 0.f, "mid.exr"); exit(0); } } fprintf(stderr, "."); }
void RealisticCamera::RenderExitPupil(Float sx, Float sy, const char *filename) const { Point3f pFilm(sx, sy, 0); const int nSamples = 2048; Float *image = new Float[3 * nSamples * nSamples]; Float *imagep = image; for (int y = 0; y < nSamples; ++y) { Float fy = (Float)y / (Float)(nSamples - 1); Float ly = Lerp(fy, -RearElementRadius(), RearElementRadius()); for (int x = 0; x < nSamples; ++x) { Float fx = (Float)x / (Float)(nSamples - 1); Float lx = Lerp(fx, -RearElementRadius(), RearElementRadius()); Point3f pRear(lx, ly, LensRearZ()); if (lx * lx + ly * ly > RearElementRadius() * RearElementRadius()) { *imagep++ = 1; *imagep++ = 1; *imagep++ = 1; } else if (TraceLensesFromFilm(Ray(pFilm, pRear - pFilm), nullptr)) { *imagep++ = 0.5f; *imagep++ = 0.5f; *imagep++ = 0.5f; } else { *imagep++ = 0.f; *imagep++ = 0.f; *imagep++ = 0.f; } } } WriteImage(filename, image, Bounds2i(Point2i(0, 0), Point2i(nSamples, nSamples)), Point2i(nSamples, nSamples)); delete[] image; }
Bounds2f RealisticCamera::BoundExitPupil(Float pFilmX0, Float pFilmX1) const { Bounds2f pupilBounds; // Sample a collection of points on the rear lens to find exit pupil const int nSamples = 1024 * 1024; int nExitingRays = 0; // Compute bounding box of projection of rear element on sampling plane Float rearRadius = RearElementRadius(); Bounds2f projRearBounds(Point2f(-1.5f * rearRadius, -1.5f * rearRadius), Point2f(1.5f * rearRadius, 1.5f * rearRadius)); for (int i = 0; i < nSamples; ++i) { // Find location of sample points on $x$ segment and rear lens element Point3f pFilm(Lerp((i + 0.5f) / nSamples, pFilmX0, pFilmX1), 0, 0); Float u[2] = {RadicalInverse(0, i), RadicalInverse(1, i)}; Point3f pRear(Lerp(u[0], projRearBounds.pMin.x, projRearBounds.pMax.x), Lerp(u[1], projRearBounds.pMin.y, projRearBounds.pMax.y), LensRearZ()); // Expand pupil bounds if ray makes it through the lens system if (Inside(Point2f(pRear.x, pRear.y), pupilBounds) || TraceLensesFromFilm(Ray(pFilm, pRear - pFilm), nullptr)) { pupilBounds = Union(pupilBounds, Point2f(pRear.x, pRear.y)); ++nExitingRays; } } // Return entire element bounds if no rays made it through the lens system if (nExitingRays == 0) { Info("Unable to find exit pupil in x = [%f,%f] on film.", pFilmX0, pFilmX1); return projRearBounds; } // Expand bounds to account for sample spacing pupilBounds = Expand(pupilBounds, 2 * projRearBounds.Diagonal().Length() / std::sqrt(nSamples)); return pupilBounds; }