miniRT 진행(4) 빛 반사된 공 만들기

naranghae·2021년 1월 12일
0

miniRT

목록 보기
6/10
post-thumbnail

https://velog.io/@naranghae/miniRT-%EC%A7%84%ED%96%894-%EB%B0%B1%ED%84%B0-%EC%97%B0%EC%82%B0-%EA%B4%91%EC%84%A0-%EC%B9%B4%EB%A9%94%EB%9D%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0

전 포스팅에서 진행한 곳에서 벡터의 구 방정식을 이용하여 구체를 만들어보았다.

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));
}

<빛 위>

<빛 아래>

<빛 오른쪽>

<빛 왼쪽>

profile
오늘보다 더 나은 내일

0개의 댓글