C语言简易光线追踪器阴影显示异常问题求助
问题排查与修复方案
你的阴影异常问题核心出在两个关键逻辑上:阴影射线的有效范围限制缺失,以及相交检测函数没有过滤无效的交点。
问题1:阴影射线的tMAX设置错误
当前in_shadow函数中,阴影射线的tMAX被设为全局的RAY_T_MAX,这意味着射线会检测整个场景中所有物体的相交,包括光源后方的物体。当场景中有圆柱时,球体的阴影射线可能会误检测到光源后方的圆柱,错误判定球体处于阴影中,导致球体阴影消失。
问题2:shapes_intersect未过滤无效交点
原函数只要检测到物体相交就返回true,但没有判断相交点的t值是否在射线的有效范围内(对于阴影射线,t必须大于0且小于阴影起点到光源的距离)。同时,函数会用后检测到的相交覆盖之前的结果,不管这个交点是否更近或是否在有效范围内。
修复步骤
1. 修正in_shadow函数,限制阴影射线的有效范围
计算阴影起点到光源的实际距离,将其设为射线的tMAX,确保只检测两者之间的物体:
static bool in_shadow(t_data *d, t_inter inter, t_vec light) { t_inter shadow; float t_light; t_vec light_dir; // 偏移起点,避免与自身表面相交的精度问题 shadow.ray.pos = vecs_add(inter.pos, vecs_multf(inter.normal, 0.0001)); // 计算从阴影起点到光源的向量 light_dir = vecs_sub(light, shadow.ray.pos); // 计算向量长度,作为射线的最大有效t值 t_light = vec_norm(light_dir); shadow.ray.axe = normalized(light_dir); shadow.ray.tMAX = t_light; // 替换全局RAY_T_MAX为实际有效距离 return (shapes_intersect(&d->shapes, &shadow)); }
注意:修正了代码中的笔误vecs_sus为vecs_sub,否则射线方向会完全反向。
2. 重写shapes_intersect函数,只保留有效且最近的交点
修改函数逻辑,仅当交点的t值在0.0001(避免自身相交)到当前射线tMAX之间时,才判定为有效相交,并且始终保留最近的交点:
bool shapes_intersect(t_shape *shapes, t_inter *inter) { bool hit = false; int i; float closest_t = inter->ray.tMAX; t_inter temp_inter; // 检测平面 i = 0; while (i < shapes->plane_nb) { temp_inter = *inter; if (hit_pl(&temp_inter, &shapes->planes[i])) { if (temp_inter.t > 0.0001 && temp_inter.t < closest_t) { *inter = temp_inter; closest_t = temp_inter.t; hit = true; } } i++; } // 检测球体 i = 0; while (i < shapes->sphere_nb) { temp_inter = *inter; if (hit_sp(&temp_inter, &shapes->spheres[i])) { if (temp_inter.t > 0.0001 && temp_inter.t < closest_t) { *inter = temp_inter; closest_t = temp_inter.t; hit = true; } } i++; } // 检测圆柱 i = 0; while (i < shapes->cyl_nb) { temp_inter = *inter; if (hit_cy(&temp_inter, &shapes->cylindres[i])) { if (temp_inter.t > 0.0001 && temp_inter.t < closest_t) { *inter = temp_inter; closest_t = temp_inter.t; hit = true; } } i++; } return hit; }
额外检查点
- 确认
hit_cy函数的相交计算正确,特别是圆柱的上下底面相交检测是否正确处理了t值范围,避免误判无效交点。 - 检查
normalized函数是否正确返回单位向量,方向错误会导致阴影射线偏离光源。
内容的提问来源于stack exchange,提问作者Johann
相关产品推荐
相关产品推荐

