我正在用C编写光线跟踪器,但我无法完善锥体上的阴影。我认为我遇到的问题是计算交叉点处锥体的法线。 Here是对我目前所拥有的内容的渲染。
场景描述如下:
resolution: 500, 500
scene:
{
light:
{
position: 0, -10, -40
intensity: 20000
color: white
}
camera:
{
position: -5, -7, -40
direction: 0, 0, 1
fov: 50
}
plane:
{
position: 0, 0, 0
direction: 0, 0, 1
color: white
}
cone:
{
position: 0, 0, -2.5
direction: -5, -8, 0
color: white
radius: 5
height: 20
}
cylinder:
{
position: 10, 0, 0
direction: -5, -8, 0
color: white
radius: 5
height: 20
}
}
请注意,灯光位于物体和相机之间。 问题在于,我认为锥体应该更加照亮,至少在某些区域,就像右边的圆柱体一样。
我根据this post's answer计算了法线,如下所示:
static void get_cone_normal(t_raytracing_tools *r, t_ray *ray, t_object *obj)
{
//nhit is the normal at hit point.
ray->nhit.x = (ray->hit.x - obj->pos.x) * (obj->height / obj->rad);
ray->nhit.y = obj->rad / obj->height;
ray->nhit.z = (ray->hit.z - obj->pos.z) * (obj->height / obj->rad);
ray->nhit = v_norm(ray->nhit);
}
我还想到了法线的方向,取决于光线被光线击中的哪一侧。在我求解二次方程并得到两个可能的答案之后,我测试每一个以确定它是否在我的有限锥内(参数方程是无限锥)并且根据光线如何击中圆锥,我有一个int变量n_dir这是1或-1,如果射线击中锥体的内部,我用它来反转法线。以下是该部分的代码:
bool get_finite_cone_intersection(t_raytracing_tools *r, t_ray *ray, t_object *obj, t_intersection_tools *i)
{
bool r1_too_low;
bool r1_too_high;
bool r2_too_low;
bool r2_too_high;
//i->r1 and i->r2 are the two roots (solutions of quadratic eq.)
r1_too_low = lower_than_min(i->r1, i, obj, ray);
r1_too_high = higher_than_max(i->r1, i, obj, ray);
r2_too_low = lower_than_min(i->r2, i, obj, ray);
r2_too_high = higher_than_max(i->r2, i, obj, ray);
if (r1_too_low)
{
i->r1 = NAN; //I set roots to NAN if they are not valid solutions
if (r2_too_low || r2_too_high)
i->r2 = NAN;
else
i->n_dir = 1;
}
else if (r1_too_high)
{
i->r1 = NAN;
if (r2_too_low || r2_too_high)
i->r2 = NAN;
else
i->n_dir = -1;
}
else if (!r1_too_low && !r1_too_high)
{
i->r2 = NAN;
if (r2_too_low)
i->n_dir = -1;
else
i->n_dir = 1;
}
return (true);
}
bool lower_than_min(double r, t_intersection_tools *i, t_object *obj, t_ray *ray)
{
if (r > 0)
{
if (v_dot(obj->dir, v_sub(v_add(ray->origin, v_scale(ray->dir, r)), obj->pos)) < 0.0)
return (true);
}
return (false);
}
bool higher_than_max(double r, t_intersection_tools *i, t_object *obj, t_ray *ray)
{
if (r > 0)
{
if (v_dot(obj->dir, v_sub(v_add(ray->origin, v_scale(ray->dir, r)),
v_add(obj->pos, v_scale(obj->dir, obj->height)))) > 0.0)
return (true);
}
return (false);
}
另外,这是什么,这是我的锥形交叉点的代码:
bool get_cone_intersection(t_raytracing_tools *r, t_ray *ray, t_object *cone)
{
t_intersection_tools i;
t_vec3 ori_cen;
double k;
int n_dir;
i.n_dir = 1;
k = tan(cone->angle);
ori_cen = v_sub(ray->origin, cone->pos);
i.q.x = v_dot(ray->dir, ray->dir) - (1.0 + k * k) * powf(v_dot(ray->dir, cone->dir), 2.0);
i.q.y = 2 * (v_dot(ray->dir, ori_cen) - (1.0 + k * k) * v_dot(ray->dir, cone->dir)
* v_dot(ori_cen, cone->dir));
i.q.z = v_dot(ori_cen, ori_cen) - (1.0 + k * k) * powf(v_dot(ori_cen,
cone->dir), 2.0);
if (!solve_quadratic(i.q, &i.r1, &i.r2))
return (0);
(i.r2 < i.r1) ? ft_swapd(&i.r1, &i.r2) : 0;
get_finite_cone_intersection(r, ray, cone, &i);
if (i.r1 < 0 || isnan(i.r1)) //the smallest one is negative, thus take the other one
{
i.r1 = i.r2;
}
if (i.r1 < 0 || isnan(i.r1))
return (false);
if (r->t > i.r1)
{
ray->t = i.r1;
if (ray->type == R_PRIMARY)
{
ray->hit_obj = cone;
ray->hit_type = T_CONE;
ray->n_dir = i.n_dir;
}
}
return (true);
}
希望一下子不要太多信息!再一次,如果有人可以对这种情况有所了解(haha),那就太喜欢了。