전 포스팅에서 진행한 곳에서 벡터의 구 방정식을 이용하여 구체를 만들어보았다.
int hit_sphere(t_point *center, double radius, t_ray *r)
{
t_vec oc;
double a;
double b;
double c;
double discriminant;
ft_vec_sub(&oc, &(r->orig), center);
a = ft_vec_dot(&(r->dir), &(r->dir));
b = 2.0 * ft_vec_dot(&oc, &(r->dir));
c = ft_vec_dot(&oc, &oc) - (radius*radius);
discriminant = b*b - 4*a*c;
return (discriminant > 0);
}
가장 기초적인 구의 방정식을 코드로 나타낸 것이고 결과는 아래에 나와 있다.
그리고 이번엔 빛을 이용해 이 구를 원하는 방향만 보이게 하고 다른 방향은 그림자 지게하는 느낌의 모양을 만들어보는 것이다.
https://www.youtube.com/watch?v=1HYhrx9bzP8&t=3438s&ab_channel=NicolasBonneel 이 유튜브를 통해 정보를 얻었고 아래와 같이 만들어보았다.
저 위에 있는 원형이 되는 공식을 바꿔서 만들었다.
double surface_hit_sphere(t_sphere *sp, t_ray *r, t_vec *P, t_vec *N)
{
t_vec oc;
t_coef var;
double t;
double t1;
double t2;
ft_vec_sub(&oc, &(r->orig), sp->center);
var.a = ft_dot_mine(&(r->dir));
var.b = 2.0 * ft_vec_dot(&oc, &(r->dir));
var.c = ft_dot_mine(&oc) - (sp->radius * sp->radius);
var.discriminant = var.b*var.b - 4*var.a*var.c;
if (var.discriminant < 0)
return (-1.0);
t1 = (-var.b - sqrt(var.discriminant))/(2*var.a);
t2 = (-var.b + sqrt(var.discriminant))/(2*var.a);
if (t2 < 0)
return (-1.0);
if (t1 > 0)
t = t1;
else
t = t2;
ft_ray_at(P, r, t);
ft_vec_sub(N, P, sp->center);
ft_vec_unit(N, N);
return (var.discriminant);
}
t_color *ft_ray_sphere(t_color *new_ray, t_ray *r)
{
double t;
double intensite_lumi;
t_vec intersite_pixel;
t_sp_var var;
// surface_hit_sphere create
intensite_lumi = 6000;
init_sphere(&var.sp, ft_vec_create(&var.v,0,0,-55), 10, ft_vec_create(&var.albedo, 1, 0, 0));
ft_vec_create(&var.lumi, -15, -70, 30); //빛의 방향을 의미
ft_zero_vec(&intersite_pixel);
ft_zero_vec(&var.P);
ft_zero_vec(&var.N1);
t = surface_hit_sphere(&var.sp, r, &var.P, &var.N1);
if (t > 0.0)
{
ft_vec_sub(&var.nvec, &var.lumi, &var.P);
ft_vec_sub(&var.nvec2, &var.lumi, &var.P);
ft_vec_unit(&var.nvec, &var.nvec);
ft_vec_multi_double(&intersite_pixel, var.sp.albedo, (intensite_lumi * FT_MAX(0, ft_vec_dot(&var.nvec,&var.N1)) / ft_dot_mine(&var.nvec2)));
ft_vec_dup(new_ray, &intersite_pixel);
return (new_ray);
}
return (ft_vec_create(new_ray, 0,0,0));
}
<빛 위>
<빛 아래>
<빛 오른쪽>
<빛 왼쪽>