Index: src/librt/mkbundle.c
===================================================================
--- src/librt/mkbundle.c	(revision 63934)
+++ src/librt/mkbundle.c	(working copy)
@@ -288,8 +293,8 @@
     VMOVE(b_dir, b_vec);
     VUNITIZE(b_dir);
 
-    for (y = -b_length; y <= b_length; y += db) {
-	for (x = -a_length; x <= a_length; x += da) {
+    for (y = -b_length; y < b_length - BN_TOL_DIST; y += db) {
+	for (x = -a_length; x < a_length - BN_TOL_DIST; x += da) {
 	    BU_ALLOC(xrayp, struct xrays);
 	    VJOIN2(xrayp->ray.r_pt, orig_start, x, a_dir, y, b_dir);
 	    VMOVE(xrayp->ray.r_dir, dir);
Index: src/rt/worker.c
===================================================================
--- src/rt/worker.c	(revision 63934)
+++ src/rt/worker.c	(working copy)
@@ -153,7 +153,7 @@
 
 
 void
-do_pixel(int cpu, int pat_num, int pixelnum)
+do_pixel(int cpu, int pat_num, int pixelnum, struct xray *rays)
 {
     struct application a;
     struct pixel_ext pe;
@@ -285,9 +285,10 @@
 		VSUB2(pe.corner[3].r_dir, pe.corner[3].r_pt, eye_model);
 	    }
 	} else {
-	    VMOVE(a.a_ray.r_pt, point);
-	    VMOVE(a.a_ray.r_dir, APP.a_ray.r_dir);
-
+	    a.a_ray = rays[a.a_y * width + a.a_x];
+	    if (jitter & JITTER_CELL) {
+		jitter_start_pt(a.a_ray.r_pt, &a, samplenum, pat_num);
+	    }
 	    if (a.a_rt_i->rti_prismtrace) {
 		VMOVE(pe.corner[0].r_dir, a.a_ray.r_dir);
 		VMOVE(pe.corner[1].r_dir, a.a_ray.r_dir);
@@ -315,7 +316,7 @@
 		VUNITIZE(a.a_ray.r_dir);
 		VADD2(a.a_ray.r_pt, eye_model, left_eye_delta);
 	    } else {
-		VMOVE(a.a_ray.r_pt, stereo_point);
+		VSUB2(a.a_ray.r_pt, a.a_ray.r_pt, left_eye_delta);
 	    }
 	    a.a_level = 0;		/* recursion level */
 	    a.a_purpose = "left eye ray";
@@ -365,9 +366,10 @@
 		    VSUB2(pe.corner[3].r_dir, pe.corner[3].r_pt, eye_model);
 		}
 	    } else {
-		VMOVE(a.a_ray.r_pt, point);
-		VMOVE(a.a_ray.r_dir, APP.a_ray.r_dir);
-
+		a.a_ray = rays[a.a_y * width + a.a_x];
+		if (jitter & JITTER_CELL) {
+		    jitter_start_pt(a.a_ray.r_pt, &a, samplenum, pat_num);
+		}
 		if (a.a_rt_i->rti_prismtrace) {
 		    VMOVE(pe.corner[0].r_dir, a.a_ray.r_dir);
 		    VMOVE(pe.corner[1].r_dir, a.a_ray.r_dir);
@@ -395,7 +397,7 @@
 		    VUNITIZE(a.a_ray.r_dir);
 		    VADD2(a.a_ray.r_pt, eye_model, left_eye_delta);
 		} else {
-		    VMOVE(a.a_ray.r_pt, stereo_point);
+		    VSUB2(a.a_ray.r_pt, a.a_ray.r_pt, left_eye_delta);
 		}
 		a.a_level = 0;		/* recursion level */
 		a.a_purpose = "left eye ray";
@@ -460,11 +462,12 @@
  * For a general-purpose version, see LIBRT rt_shoot_many_rays()
  */
 void
-worker(int cpu, void *UNUSED(arg))
+worker(int cpu, void *arg)
 {
     int pixel_start;
     int pixelnum;
     int pat_num = -1;
+    struct xray *rays = (struct xray *) arg;
 
     /* The more CPUs at work, the bigger the bites we take */
     if (per_processor_chunk <= 0) per_processor_chunk = npsw;
@@ -510,7 +513,7 @@
 		if (pixelnum < last_pixel)
 		    return;
 
-		do_pixel(cpu, pat_num, pixelnum);
+		do_pixel(cpu, pat_num, pixelnum, rays);
 	    }
 	}
     } else if (random_mode) {
@@ -521,7 +524,7 @@
 	       with multi-threaded RNG */
 	    pixelnum = rand()*1.0/RAND_MAX*(last_pixel + 1);
 	    if (pixelnum >= last_pixel) pixelnum = last_pixel;
-	    do_pixel(cpu, pat_num, pixelnum);
+	    do_pixel(cpu, pat_num, pixelnum, rays);
 	}
 
     } else {
@@ -539,7 +542,7 @@
 		if (pixelnum > last_pixel)
 		    return;
 
-		do_pixel(cpu, pat_num, pixelnum);
+		do_pixel(cpu, pat_num, pixelnum, rays);
 	    }
 	}
     }
@@ -700,6 +703,37 @@
 {
     int cpu;
 
+    struct xray *rays = (struct xray *)bu_calloc(1, sizeof(struct xray), "ray bundle");
+
+    if (rt_perspective <= 0.0) {
+	struct xray center_ray;
+	struct xrays xrays;
+	struct xrays *ray;
+
+	vect_t w, h;
+	int i = 0;
+
+	BU_LIST_INIT(&(xrays.l));
+
+	VSCALE(w, dx_model, width / 2);
+	VSCALE(h, dy_model, height / 2);
+	VJOIN2(center_ray.r_pt, viewbase_model, width / 2, dx_model, height / 2, dy_model);
+	VMOVE(center_ray.r_dir, APP.a_ray.r_dir);
+	rt_gen_rect(&xrays, &center_ray, w, h, MAGNITUDE(dx_model), MAGNITUDE(dy_model));
+	i = bu_list_len(&(xrays.l));
+	if (i == 0) {
+	    /* No rays to shoot, so just exit */
+	    return;
+	}
+	rays = (struct xray *)bu_calloc(i, sizeof(struct xray), "ray bundle");
+	i--;
+	while (BU_LIST_WHILE(ray, xrays, &(xrays.l))) {
+	    BU_LIST_DEQUEUE(&(ray->l));
+	    rays[i--] = ray->ray;
+	    bu_free(ray, "bundled ray");
+	}
+    }
+
 #ifdef USE_FORKED_THREADS
     int pid, wpid;
     int waitret;
@@ -723,7 +757,7 @@
 	 * SERIAL case -- one CPU does all the work.
 	 */
 	npsw = 1;
-	worker(0, NULL);
+	worker(0, (void *)rays);
     } else {
 	/*
 	 * Parallel case.
@@ -747,7 +781,7 @@
 	} else if (pid == 0) {
 #endif
 
-	    bu_parallel(worker, npsw, NULL);
+	    bu_parallel(worker, npsw, (void *)rays);
 
 #ifdef USE_FORKED_THREADS
 	    /* send raytrace instance data back to the parent */
Index: include/raytrace.h
===================================================================
--- include/raytrace.h	(revision 63934)
+++ include/raytrace.h	(working copy)
@@ -2661,7 +2661,10 @@
  * right, respectively; their magnitudes determine the extent of the
  * grid (the grid extends from -a_vec to a_vec in the up-direction and
  * from -b_vec to b_vec in the right direction).  da and db are the
- * offset between rays in the a and b directions respectively.
+ * offset between rays in the a and b directions respectively.  This
+ * generated grid includes the rays with points center_ray.r_pt -
+ * a_vec and center_ray.r_pt - b_vec, but excludes the rays
+ * center_ray.r_pt + a_vec and center_ray.r_pt + b_vec.
  */
 RT_EXPORT extern int rt_gen_rect(struct xrays *rays,
 				 const struct xray *center_ray,
