《光线跟踪算法技术》代码4.1解释

首先上代码:

 1void World::render_scene(void) const {
 2    RGBColor pixel_color;
 3    Ray ray;
 4    float zw = 100.0;
 5    int n = (int)sqrt((float)vp.num_samples);
 6    Point2D pp; // sample point on a pixel
 7
 8    open_window(vp.hres,vp.vres);
 9    ray.d = Vector3D(0,0,-1);
10 
11    for (int r = 0; r < vp.vres; r++)       // up
12        for (int c = 0; c < vp.hres; c++) { // across
13            pixel_color = black; 
14
15            for (int p = 0; p < n; p++)         // up pixel
16                for (int q = 0; q < n; q++) {   // across pixel
17                    pp.x = vp.s * (c - 0.5 * vp.hres + (q + 0.5) / n); 
18                    pp.y = vp.s * (r - 0.5 * vp.vres + (p + 0.5) / n);
19                    ray.o = Point3D(pp.x,pp.y,zw);
20                    pixel_color += tracer_ptr->trace_ray(ray);
21                }
22
23            pixel_color /= vp.num_samples;
24            display_pixel(r, c, pixel_color);
25        } 
26}

假设令采样列与采样行值n为5,vp.vresvp.hres为100,令像素大小vp.s为1,那么,当r为0,c为0时,上述代码中,代入具体数值后,用来进行采样的双重循环的代码段如下:

1for (int p = 0; p < n; p++)         // up pixel
2    for (int q = 0; q < n; q++) {   // across pixel
3        pp.x = -50 + (q + 0.5)/5;
4        pp.y = -50 + (p + 0.5)/5;
5        ray.o = Point3D(pp.x,pp.y,zw);
6        pixel_color += tracer_ptr->trace_ray(ray);
7    }

pq取值如下表时,对应的pp.xpp.y的取值如下:

pp.x\pp.y 0 1 2 3 4
0 (-49.9,-49.9) (-49.7,-49.9) (-49.5,-49.9) (-49.3,-49.9) (-49.1,-49.9)
1 (-49.9,-49.7) (-49.7,-49.7) (-49.5,-49.7) (-49.3,-49.7) (-49.1,-49.7)
2 (-49.9,-49.5) (-49.7,-49.5) (-49.5,-49.5) (-49.3,-49.5) (-49.1,-49.5)
3 (-49.9,-49.3) (-49.7,-49.3) (-49.5,-49.3) (-49.3,-49.3) (-49.1,-49.3)
4 (-49.9,-49.1) (-49.7,-49.1) (-49.5,-49.1) (-49.3,-49.1) (-49.1,-49.1)

而如果不进行均匀采样的话,当cr为0时,对应的ray.o的x,y分量为 (-49.5,-49.5) 。即程序清单3.12中的计算方式。也即对应于表格中的pp.xpp.y都等于2时的取值,简而言之,就是说,均匀采样,就是把采样格子再划分得细点儿。如下图所示:

如果不执行均匀采样的话,那么向(-49.5,-49.5)处投射光线,是无法和红色的三角形相交的,对应的像素点采样的就不会产生着色。而如果使用均匀采样的话,将会对原来的“一格”像素格,再划分25格进行光线相交检测显然,有部分的“细分像素格”是和红色三角形相交的,故而,这个像素格应该会产生着色。颜色值就是这25个颜色格的颜色和的平均值。

程序清单3.12中的计算方式的代码如下:

 1void World::render_scene(void) const{
 2    RGBColor pixel_color;
 3    Ray ray;
 4    double zw = 100.0;      // hard wired int
 5    double x , y;
 6
 7    open_window(vp.hres,vp.vres);
 8    ray.d = Vector3D(0,0,-1);
 9    
10    for(int r = 0; r < vp.vres; r++)
11        for(int c = 0; c <= vp.hres; c++){
12            x = vp.s * (c-0.5*(vp.hres-1.0));
13            y = vp.s * (c-0.5*(vp.vres-1.0));
14            ray.o = Point3D(x,y,zw);
15            pixel_color = trace_ptr->trace_ray(ray);
16            display_pixel(r,c,pixel_color);
17        }
18}