《光线跟踪算法技术》代码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.vres
与vp.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 }
当p
和q
取值如下表时,对应的pp.x
和pp.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) |
而如果不进行均匀采样的话,当c
,r
为0时,对应的ray.o
的x,y分量为 (-49.5,-49.5) 。即程序清单3.12中的计算方式。也即对应于表格中的pp.x
和pp.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}