ray.c
  1  /* ************************************************************************** */
  2  /*                                                                            */
  3  /*                                                        :::      ::::::::   */
  4  /*   ray.c                                              :+:      :+:    :+:   */
  5  /*                                                    +:+ +:+         +:+     */
  6  /*   By: gychoi <gychoi@student.42seoul.kr>         +#+  +:+       +#+        */
  7  /*                                                +#+#+#+#+#+   +#+           */
  8  /*   Created: 2023/05/12 18:11:15 by gychoi            #+#    #+#             */
  9  /*   Updated: 2023/05/18 20:08:43 by gychoi           ###   ########.fr       */
 10  /*                                                                            */
 11  /* ************************************************************************** */
 12  
 13  #include "pracrt.h"
 14  #include "ray.h"
 15  #include "hit.h"
 16  #include "list.h"
 17  #include "texture.h"
 18  
 19  t_ray	ray(t_point3 start, t_vec3 dir)
 20  {
 21  	t_ray	ray;
 22  
 23  	ray.start = start;
 24  	ray.dir = dir;
 25  	return (ray);
 26  }
 27  
 28  t_ray	ray_primary(t_camera cam, double u, double v)
 29  {
 30  	t_ray	ray;
 31  
 32  	ray.start = cam.orig;
 33  	ray.dir = vunit(vsub(vadd(vadd(cam.left_bottom, vmults(cam.horizontal, u)), vmults(cam.vertical, v)), cam.orig));
 34  	return (ray);
 35  }
 36  
 37  t_color3	trace_ray(t_ray pixel_ray, t_obj_list *list, t_light light, int recursive_level)
 38  {
 39  	t_hit		hit;
 40  	double		dif;
 41  	t_point3	dir_to_light;
 42  	double		spec;
 43  	t_point3	reflect_dir;
 44  	t_ray		shadow_ray;
 45  	t_color3	point_color;
 46  	t_color3	final_color;
 47  	t_point3	reflected_dir;
 48  	t_ray		reflection_ray;
 49  	double		ior;
 50  	double		eta;
 51  	t_vec3		normal;
 52  
 53  	if (recursive_level < 0)
 54  		return (color3(0.0f, 0.0f, 0.0f));
 55  	hit = find_closest_collision(pixel_ray, list);
 56  	if (hit.d >= 0.0f)
 57  	{
 58  		final_color = color3(0.0f, 0.0f, 0.0f);
 59  
 60  		if (hit.obj.amb_texture)
 61  			point_color = vmult(hit.obj.amb, sample_point(hit.obj.amb_texture, &hit.uv));
 62  		else
 63  			point_color = hit.obj.amb;
 64  		dir_to_light = vunit(vsub(light.pos, hit.point));
 65  		shadow_ray = ray(vadd(hit.point, vmults(dir_to_light, EPSILON)), dir_to_light);
 66  
 67  		dif = fmax(vdot(hit.normal, dir_to_light), 0.0f);
 68  		reflect_dir = vsub(vmults(hit.normal, vdot(hit.normal, dir_to_light) * 2.0f), dir_to_light);
 69  		spec = pow(fmax(vdot(vunit(vmults(pixel_ray.dir, -1.0f)), reflect_dir), 0.0f), hit.obj.alpha);
 70  
 71  		t_vec3	diffuse = vmults(hit.obj.dif, dif);
 72  		t_vec3	specular = vmults(vmults(hit.obj.spec, spec), hit.obj.ks);
 73  
 74  		if (hit.obj.dif_texture)
 75  			point_color = vadd(point_color, vmult(diffuse, sample_point(hit.obj.dif_texture, &hit.uv)));
 76  		else
 77  			point_color = vadd(point_color, diffuse);
 78  		point_color = vadd(point_color, specular);
 79  
 80  		final_color = vadd(final_color, vmults(point_color, (1.0f - hit.obj.reflection - hit.obj.transparency)));
 81  
 82  		if (find_closest_collision(shadow_ray, list).d < 0.0f || find_closest_collision(shadow_ray, list).d > vlen(vsub(light.pos, hit.point)))
 83  		{
 84  			if (hit.obj.reflection > 0.0f)
 85  			{
 86  				reflected_dir = vunit(vadd(vmults(vmults(hit.normal, 2.0f), vdot(vmults(pixel_ray.dir, -1.0f), hit.normal)), pixel_ray.dir));
 87  				reflection_ray = ray(vadd(hit.point, vmults(reflected_dir, EPSILON)), reflected_dir);
 88  				final_color = vadd(final_color, vmults(trace_ray(reflection_ray, list, light, recursive_level - 1), hit.obj.reflection));
 89  			}
 90  			if (hit.obj.transparency > 0.0f)
 91  			{
 92  				ior = 1.5f;
 93  				if (vdot(pixel_ray.dir, hit.normal) < 0.0f)
 94  				{
 95  					eta = ior;
 96  					normal = hit.normal;
 97  				}
 98  				else
 99  				{
100  					eta = 1.0f / ior;
101  					normal = vmults(hit.normal, -1);
102  				}
103  				double	cos_theta1 = vdot(vmults(pixel_ray.dir, -1), normal);
104  				double	sin_theta1 = sqrt(1.0f - cos_theta1 * cos_theta1);
105  				double	sin_theta2 = sin_theta1 / eta;
106  				double	cos_theta2 = sqrt(1.0f - sin_theta2 * sin_theta2);
107  
108  				t_vec3	m = vunit(vadd(vmults(normal, vdot(normal, vmults(pixel_ray.dir, -1))), pixel_ray.dir));
109  				t_vec3	a = vmults(m, sin_theta2);
110  				t_vec3	b = vmults(vmults(normal, -1), cos_theta2);
111  				t_vec3	refracted_dir = vunit(vadd(a, b));
112  
113  				t_ray	refraction_ray = ray(vadd(hit.point, vmults(refracted_dir, 0.0001f)), refracted_dir);
114  				final_color = vadd(final_color, vmults(trace_ray(refraction_ray, list, light, recursive_level - 1), hit.obj.transparency));
115  			}
116  		}
117  		else
118  			return (vmults(final_color, 0.5f));
119  		return (final_color);
120  	}
121  	return (color3(0.0f, 0.0f, 0.0f));
122  }
123  
124  t_color3	trace_ray_2x2(t_vec3 eye_pos, t_color3 pixel_pos, double dx, int recursive_level, t_obj_list *list, t_light light)
125  {
126  	t_ray		pixel_ray;
127  	t_ray		sub_ray;
128  	double		subdx;
129  	t_color3	pixel_color;
130  	t_vec3		sub_pos;
131  
132  	if (recursive_level == 0)
133  	{
134  		pixel_ray = ray(pixel_pos, vunit(vsub(pixel_pos, eye_pos)));
135  		return (trace_ray(pixel_ray, list, light, 5));
136  	}
137  	subdx = 0.5f * dx;
138  	pixel_color = color3(0.0f, 0.0f, 0.0f);
139  
140  	for (int j = 0; j < 2; j++)
141  		for (int i = 0; i < 2; i++)
142  		{
143  			sub_pos = vec3(pixel_pos.x + (double)i * subdx, pixel_pos.y + (double)j * subdx, pixel_pos.z);
144  			sub_ray = ray(sub_pos, vunit(vsub(sub_pos, eye_pos)));
145  			pixel_color = vadd(pixel_color, trace_ray_2x2(eye_pos, sub_pos, subdx, recursive_level - 1, list, light));
146  		}
147  	return (vmults(pixel_color, 0.25f));
148  }