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 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 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; }
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; }
// 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; }
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; }
Spectrum InfiniteAreaLight::Sample_L(const Point2f &u1, const Point2f &u2, Float time, Ray *ray, Normal3f *nLight, Float *pdfPos, Float *pdfDir) const { // Compute direction for infinite light sample ray Point2f lightSample = u1; // Find $(u,v)$ sample coordinates in infinite light texture Float mapPdf; Point2f uv = distribution->SampleContinuous(lightSample, &mapPdf); if (mapPdf == 0.f) return Spectrum(0.f); Float theta = uv[1] * Pi, phi = uv[0] * 2.f * Pi; Float cosTheta = std::cos(theta), sinTheta = std::sin(theta); Float sinPhi = std::sin(phi), cosPhi = std::cos(phi); Vector3f d = -LightToWorld(Vector3f(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta)); *nLight = (Normal3f)d; // Compute origin for infinite light sample ray Vector3f v1, v2; CoordinateSystem(-d, &v1, &v2); Point2f cd = ConcentricSampleDisk(u2); Point3f Pdisk = worldCenter + worldRadius * (cd.x * v1 + cd.y * v2); *ray = Ray(Pdisk + worldRadius * -d, d, Infinity, time); // Compute _InfiniteAreaLight_ ray PDF *pdfDir = mapPdf / (2 * Pi * Pi * sinTheta); *pdfPos = 1 / (Pi * worldRadius * worldRadius); if (sinTheta == 0) *pdfDir = 0; return Spectrum(Lmap->Lookup(uv), SpectrumType::Illuminant); }
Vector3D ParticleGenerator::sampleDir(int index) { index %= 256; double u = static_cast<double>(index % sample_div) / sample_div; double v = static_cast<double>(index / sample_div) / sample_div; double dx, dy; ConcentricSampleDisk(u, v, dx, dy); return nz + (dx * nx + dy * ny) * distri_r; }
bool Disk::Sample(const Point2f &sample, Interaction *it) const { Point2f pd = ConcentricSampleDisk(sample); Point3f pObj(pd.x * radius, pd.y * radius, height); it->n = Normalize((*ObjectToWorld)(Normal3f(0, 0, 1))); if (ReverseOrientation) it->n *= -1.f; Vector3f pObjError(0.f, 0.f, MachineEpsilon * height); it->p = (*ObjectToWorld)(pObj, pObjError, &it->pError); return true; }
Point Disk::Sample(float u1, float u2, Normal *Ns) const { Point p; ConcentricSampleDisk(u1, u2, &p.x, &p.y); p.x *= radius; p.y *= radius; p.z = height; *Ns = Normalize((*ObjectToWorld)(Normal(0,0,1))); if (ReverseOrientation) *Ns *= -1.f; return (*ObjectToWorld)(p); }
Spectrum DistantLight::Sample_L(const Point2f &sample1, const Point2f &sample2, Float time, Ray *ray, Normal3f *Ns, Float *pdfPos, Float *pdfDir) const { // Choose point on disk oriented toward infinite light direction Vector3f v1, v2; CoordinateSystem(wLight, &v1, &v2); Point2f cd = ConcentricSampleDisk(sample1); Point3f Pdisk = worldCenter + worldRadius * (cd.x * v1 + cd.y * v2); // Set ray origin and direction for infinite light ray *ray = Ray(Pdisk + worldRadius * wLight, -wLight, Infinity, time); *Ns = (Normal3f)ray->d; *pdfPos = 1.f / (Pi * worldRadius * worldRadius); *pdfDir = 1.f; return L; }
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, "."); }
Spectrum DistantLight::Sample_L(const Scene *scene, const LightSample &ls, float u1, float u2, float time, Ray *ray, Normal *Ns, float *pdf) const { // Choose point on disk oriented toward infinite light direction Point worldCenter; float worldRadius; scene->WorldBound().BoundingSphere(&worldCenter, &worldRadius); Vector v1, v2; CoordinateSystem(lightDir, &v1, &v2); float d1, d2; ConcentricSampleDisk(ls.uPos[0], ls.uPos[1], &d1, &d2); Point Pdisk = worldCenter + worldRadius * (d1 * v1 + d2 * v2); // Set ray origin and direction for infinite light ray *ray = Ray(Pdisk + worldRadius * lightDir, -lightDir, 0.f, INFINITY, time); *pdf = 1.f / (M_PI * worldRadius * worldRadius); return L; }
Spectrum DistantLight::Sample_L(const Scene *scene, float u1, float u2, float u3, float u4, Ray *ray, float *pdf) const { // Choose point on disk oriented toward infinite light direction Point worldCenter; float worldRadius; scene->WorldBound().BoundingSphere(&worldCenter, &worldRadius); Vector v1, v2; CoordinateSystem(lightDir, &v1, &v2); float d1, d2; ConcentricSampleDisk(u1, u2, &d1, &d2); Point Pdisk = worldCenter + worldRadius * (d1 * v1 + d2 * v2); // Set ray origin and direction for infinite light ray ray->o = Pdisk + worldRadius * lightDir; ray->d = -lightDir; *pdf = 1.f / (M_PI * worldRadius * worldRadius); return L; }
Vec3 PointLight::sampleDir() { //Amostrar ponto no globo Vec3 tempDir = UniformSampleHemisphere(drand48(), drand48()); float px, py; ConcentricSampleDisk(drand48(), drand48(), &px, &py); float prob = drand48(); Vec3 nn; if(prob < 0.5f) nn = Vec3(0.0, 1.0, 0.0); else nn = Vec3(0.0, -1.0, 0.0); Vec3 dpdu(-py, px, 0.f); Vec3 sn = normalize(dpdu); Vec3 tn = cross(nn, sn); //Local to world return Vec3(sn.x*tempDir.x + tn.x*tempDir.y + nn.x*tempDir.z, sn.y*tempDir.x + tn.y*tempDir.y + nn.y*tempDir.z, sn.z*tempDir.x + tn.z*tempDir.y + nn.z*tempDir.z); }
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 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; }
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; }