《光线跟踪算法技术》代码4.1解释
Table of Contents
请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
首先上代码:
void World::render_scene(void) const {
RGBColor pixel_color;
Ray ray;
float zw = 100.0;
int n = (int)sqrt((float)vp.num_samples);
Point2D pp; // sample point on a pixel
open_window(vp.hres,vp.vres);
ray.d = Vector3D(0,0,-1);
for (int r = 0; r < vp.vres; r++) // up
for (int c = 0; c < vp.hres; c++) { // across
pixel_color = black;
for (int p = 0; p < n; p++) // up pixel
for (int q = 0; q < n; q++) { // across pixel
pp.x = vp.s * (c - 0.5 * vp.hres + (q + 0.5) / n);
pp.y = vp.s * (r - 0.5 * vp.vres + (p + 0.5) / n);
ray.o = Point3D(pp.x,pp.y,zw);
pixel_color += tracer_ptr->trace_ray(ray);
}
pixel_color /= vp.num_samples;
display_pixel(r, c, pixel_color);
}
}
假设令采样列与采样行值n
为5,vp.vres
与vp.hres
为100,令像素大小vp.s
为1,那么,当r
为0,c
为0时,上述代码中,代入具体数值后,用来进行采样的双重循环的代码段如下:
for (int p = 0; p < n; p++) // up pixel
for (int q = 0; q < n; q++) { // across pixel
pp.x = -50 + (q + 0.5)/5;
pp.y = -50 + (p + 0.5)/5;
ray.o = Point3D(pp.x,pp.y,zw);
pixel_color += tracer_ptr->trace_ray(ray);
}
当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中的计算方式的代码如下:
void World::render_scene(void) const{
RGBColor pixel_color;
Ray ray;
double zw = 100.0; // hard wired int
double x , y;
open_window(vp.hres,vp.vres);
ray.d = Vector3D(0,0,-1);
for(int r = 0; r < vp.vres; r++)
for(int c = 0; c <= vp.hres; c++){
x = vp.s * (c-0.5*(vp.hres-1.0));
y = vp.s * (c-0.5*(vp.vres-1.0));
ray.o = Point3D(x,y,zw);
pixel_color = trace_ptr->trace_ray(ray);
display_pixel(r,c,pixel_color);
}
}