我过去曾写过两个传统的光线跟踪器,但现在我想编写一个反向光线跟踪器,它可以跟踪从光源到眼点的光子。在过去几天阅读关于这个主题的文章后,我知道我不应该尝试,但无论如何我想要这样做。我现在面临的问题是如何计算我想要生成的图像中每个像素的值。
在正常光线追踪中,我正在从眼点通过图像平面中的像素拍摄光线到场景中,并且在跟踪了光线树的这个分支之后,我最终得到了分配给该像素的颜色值。我想不出一种扭转这个过程的方法。如果我测试每条光线是否只与图像平面相交,那么我会在图像平面上得到一个180度的视野和一个焦点(一个模糊的混乱)。所以我必须测试每条光线是否与图像平面和眼点相交。但由于眼点只是一个无限小的点,光线击中它的几率应该(几乎)为零,这将导致根本没有图像。
所以我的问题是:如何通过追踪光源中的光子来计算要渲染的图像的像素值?
提前致谢,
扬
答案 0 :(得分:1)
您需要进行“最终聚集”才能生成图像。如果您的光线树从光源分支出来,这将有效地“装饰”光线树的叶子,并附加一条光线到眼睛。
当然,并非每一条这样的光线都是有效的:如果表面背离眼睛,或者它被遮挡,那么它应该被拒绝。请注意,这种生成光线的方法类似于在常规光线跟踪中确定照明所需的“阴影”光线。
另一个问题是,您接收的光线将是随机图案,而不是传统光线跟踪提供的常规或分布均匀的图案。这意味着您需要对相机接收的光线进行平均和/或插值,以获得像素值。
我相信您的像素颜色将取决于样本密度和样本的颜色值;如果是这样,您将需要确保平均/插值方法提供该行为。初始近似可能只是将输入样本添加到最近的像素;一个更好的可能是为每个进入的样品“喷溅”一个简单的添加剂贴花。更复杂的方法可以根据样品的局部密度按比例缩放贴花的大小 - 同时保持总的集成亮度与样品亮度成比例。
编辑:给定传入的“眼睛”光线,您仍需要确定传入光线对应的屏幕位置。为此,您需要计算用于光栅化的相机的“ViewProjection”矩阵。这实际上是用于传统光线追踪的过程的逆:
conventional ray tracing:
// find direction vector for given screen coordinates (x,y)
homog4vector homog_clip_coords( (x - x_offset) / x_resolution,
(y - y_offset) / y_resolution,
1.0, // z-coordinate
1.0); // w-coordinate
homog4vector homog_world_coords = InverseViewProjectionMatrix * homog_clip_coords
ray_vector_x = homog_world_coords.x / homog_world_coords.w - eye_x;
ray_vector_y = homog_world_coords.y / homog_world_coords.w - eye_y;
ray_vector_z = homog_world_coords.z / homog_world_coords.w - eye_z;
rasterization or "reverse" ray tracing:
// find screen coordinates for given source point "p"
homog4vector eye_ray_source(p.x, p.y, p.z, 1.0);
homog4vector homog_clip_coords = ViewProjectionMatrix * homog4vector(x,y,z,1);
screen_coords.x = x_offset + x_resolution * homog_clip_coords.x / homog_clip_coords.w
screen_coords.y = y_offset + y_resolution * homog_clip_coords.y / homog_c.ip_coords.w
当然,并非所有传入的光线都会出现在屏幕上。确保丢弃从后面进入相机的光线:
if (homog_clip_coords.z < 0 || homog_clip_coords.w < 0)
{ /* reject ray */ }