You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:35:19