这是我的第一个问题,所以我希望我能做对。 我目前正在为一个学校项目用 C 语言编写一个简单的光线追踪器。 该程序似乎按预期运行,因为它使用学校提供的库在窗口上显示像素来显示基本形状(平面、球体和圆柱体)。
我确实有一个奇怪的问题,几天后我仍然无法弄清楚。
这是一个简单的场景,可以正确显示一盏灯(始终只有一盏灯)、一个球体和一个平面:
但是事情变得有点奇怪。
当我向场景中添加一个圆柱体时,我有圆柱体的投影阴影,但不再有球体的投影:
这里我们再次看到了圆柱体的阴影,但没有球体:
最后,光线穿过右侧的平面,因此所有形状都应该处于阴影中:
我很难理解这个问题。我还是 C 初学者,尤其是 3D 编程。
从相机创建光线后,我会检查是否找到与场景中任何形状的交叉点:
bool shapes_intersect(t_shape *shapes, t_inter *inter)
{
bool hit;
int i;
hit = false;
i = 0;
while (i < shapes->plane_nb)
{
if (hit_pl(inter, &shapes->planes[i]))
hit = true;
i++;
}
i = 0;
while (i < shapes->sphere_nb)
{
if (hit_sp(inter, &shapes->spheres[i]))
hit = true;
i++;
}
i = 0;
while (i < shapes->cyl_nb)
{
if (hit_cy(inter, &shapes->cylindres[i]))
hit = true;
i++;
}
return (hit);
}
一旦找到交点,我们就会追踪从该交点到光点的另一条光线,并通过相同的函数(shapes_intersect)来确定该交点是否被点亮:
static bool in_shadow(t_data *d, t_inter inter, t_vec light)
{
t_inter shadow;
shadow.ray.pos = vecs_multf(inter.normal, 0.0001);
shadow.ray.pos = vecs_add(inter.pos, shadow.ray.pos);
shadow.ray.axe = normalized(vecs_sus(light, shadow.ray.pos));
shadow.ray.tMAX = RAY_T_MAX;
return (shapes_intersect(&d->shapes, &shadow));
}
void ray_trace(t_data *d)
{
int x;
int y;
t_ray ray;
t_inter inter;
uint32_t curr_pixel;
bool visible;
x = 0;
y = 0;
while ((uint32_t)x < d->img->width)
{
while ((uint32_t)y < d->img->height)
{
ray = make_ray(&d->cam, vec2_init(((2.0f * x) / d->img->width) - 1.0f, ((-2.0f * y) / d->img->height) + 1.0f));
inter = inter_cpy_ray(&ray);
if (shapes_intersect(&d->shapes, &inter))
{
curr_pixel = color_prod(inter.rgb, color_scale(d->amb.rgb, d->amb.ratio));
visible = !in_shadow(d, inter, d->lum.pos);
curr_pixel = color_add(curr_pixel, visible * color_comp(&d->lum, inter));
mlx_put_pixel(d->img, x, y, curr_pixel);
}
else
{
curr_pixel = 255;
mlx_put_pixel(d->img, x, y, curr_pixel);
}
y++;
}
y = 0;
x++;
}
这是我无法解决这个问题的主要原因。正确找到了交叉点,我们可以看到形状甚至一些阴影,但由于某种原因,当场景中有圆柱体时,无法检测到平面和球体阴影。
有人知道这里发生了什么吗?
感谢您的宝贵时间。
没有深入分析或测试,但快速浏览一下:
我在您的 shapes_intersect
函数中没有看到
点击的距离排序。您应该选择最接近的对象命中,而不是具有最大索引的对象的命中...
由于圆柱体是最后测试的,因此它们具有最高优先级,因此如果您的射线击中任何圆柱体,则忽略任何其他物体的击中...
如果你击中球体(其次进行测试),那么平面将被忽略......
因此,如果您的
hit == true
您应该仅在交点比已选择的交点更近(沿射线方向的符号距离)时更新您的 inter
...