1. 程式人生 > >PBRT_V2 總結記錄 <17> GenerateRay 和 Depth Of Field

PBRT_V2 總結記錄 <17> GenerateRay 和 Depth Of Field

這次主要是記錄 PerspectiveCamera : GenerateRay 函式的思路:


// Ray : RasterToCamera -> CameraToWorld , 所以 得到的Ray是World Space
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;
		// P667
		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
		// 這裡就是從Camera的原點Point(0.f, 0.f, 0.f); 變成 Point(lensU, lensV, 0.f);
		ray->o = Point(lensU, lensV, 0.f);
		ray->d = Normalize(Pfocus - ray->o);
	}
	ray->time = sample.time;
	CameraToWorld(*ray, ray);
	return 1.f;
}

這個方法主要的作用就是 從一個 取樣點 CameraSample 生成一條 Ray。

細節:

a.

Point Pras(sample.imageX, sample.imageY, 0); Point Pcamera; RasterToCamera(Pras, &Pcamera); *ray = Ray(Point(0, 0, 0), Normalize(Vector(Pcamera)), 0.f, INFINITY);

作用:把 Image Plane 的 取樣點  Pras(sample.imageX, sample.imageY, 0) 變換到 Camera Space 中 Point Pcamera;,生成一條射線  *ray = Ray(Point(0, 0, 0), Normalize(Vector(Pcamera)), 0.f, INFINITY); 這條射線 是在 Camera Space 中的,那就是 

上面的程式碼就是在 Camera Space 中 生成一條 射線,這條射線的 原點 是 (0,0,0),方向是  (Pcamera - (0,0,0)),也就是射線的方向是 ” 原點 指向 取樣點 “。

 CameraToWorld(*ray, ray);

 最後再把 這條在 Camera Space 的ray 變換到 World Space 中。

b.景深

1. 思路:

(在 Focal plane 上的點,是可以 完美聚焦,但是不在 Focal plane的點,就會導致 模糊)

Real-world cameras have a lens with finite aperture(光圈) and lens(透鏡) controls that adjust the lens position with respect to the film plane. Because the aperture is finite, objects in the scene aren’t all imaged onto the film in perfect focus. Here, the point p1 doesn’t lie on the plane of points in perfect focus, so it images to an area p‘1 on the film and is blurred. The point p2 does lie on the focal plane, so it images to a point p’2 and is in focus.

Either increasing the aperture size or increasing an object’s distance from the focal plane will increase an out-of-focus object’s blurriness.

(先計算 利用 B點(the center of the lens)和A點 做一條射線,計算出 這條射線在 Focal plane 上的交點 C,然後 在  D點(the lens position sample)和C點再形成一條新的射線來進行 光線追蹤, 這樣,如果在 Focal plane 的點,與 新的射線相交的話,依然可以求出 與舊射線一樣的交點,但是不在 Focal plane 的點與新的射線相交的話,求出的相交點與舊的射線的相交點不一樣,所以模糊了,而且,隨著Pixel的取樣點數目越高,越模糊)

(a) For a pinhole camera model, a single camera ray is associated with each point on the film plane (filled circle), given by the ray that passes through the single point of the pinhole lens (empty circle). (b) For a camera model with a finite aperture, we sample a point (filled circle) on the disk-shaped lens for each ray. We can also compute the ray that passes through the center of the lens (corresponding to the pinhole model) and the point where it intersects the focal plane (solid line). We know that all objects in the focal plane must be in focus, regardless of the lens sample position. Therefore, the ray corresponding to the lens position sample (dashed line) is given by the ray starting on the lens sample point and passing through the computed intersection point on the focal plane.

It is generally necessary to trace many rays for each image pixel in order to adequately sample the lens for smooth depth of field.

2. 細節

float lensRadius, focalDistance;

作用:(一個是控制 透鏡的半徑,一個是控制 Focal Plane的距離,只有的 Focal Plane上的點才可以 完美聚焦,其他會模糊)

one sets the size of the lens aperture, and the other sets the focal distance.

if (lensRadius > 0.) {
		// Sample point on lens
		float lensU, lensV;
		// P667
		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
		// 這裡就是從Camera的原點Point(0.f, 0.f, 0.f); 變成 Point(lensU, lensV, 0.f);
		ray->o = Point(lensU, lensV, 0.f);
		ray->d = Normalize(Pfocus - ray->o);
	}

ConcentricSampleDisk() function:

作用:

(利用 sample.lensU, sample.lensV 取樣點資料,得到 均勻分佈的 lensU, lensV,lensU, lensV 都是[-1,1])

The ConcentricSampleDisk() function, defined in Chapter 13, takes a (u, v) sample position in [0, 1] and maps it to a 2D unit disk centered at the origin (0, 0). To turn this into a point on the lens, these coordinates are scaled by the lens radius. The CameraSample class provides the (u, v) lens-sampling parameters in the CameraSample::lensU and CameraSample::lensV fields.

Peter Shirley (1997) developed a “concentric” mapping from the unit square to the unit circle that avoids this problem. The concentric mapping takes points in the square [−1, 1] to the unit disk by uniformly mapping concentric squares to concentric circles

float ft = focalDistance / ray->d.z;

Point Pfocus = (*ray)(ft);

作用:

Compute point on plane of focus

ray->o = Point(lensU, lensV, 0.f);
ray->d = Normalize(Pfocus - ray->o);

作用:

這裡就是從Camera的原點Point(0.f, 0.f, 0.f); 變成 Point(lensU, lensV, 0.f);