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 }