Guest User

Untitled

a guest
Nov 22nd, 2017
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.50 KB | None | 0 0
  1. typedef struct doge_sphere
  2. {
  3. struct doge_sphere *next;
  4. doge_vec3_t pos;
  5. float radius;
  6. doge_vec3_t color;
  7. }doge_sphere_t;
  8.  
  9. typedef struct doge_ray
  10. {
  11. doge_vec3_t start;
  12. doge_vec3_t dir;
  13. }doge_ray_t;
  14.  
  15. typedef struct doge_point_light
  16. {
  17. doge_vec3_t pos;
  18. struct doge_point_light *next;
  19. }doge_point_light_t;
  20.  
  21. typedef struct doge_world
  22. {
  23. doge_point_light_t *light_head;
  24. doge_sphere_t *sphere_head;
  25. }doge_world_t;
  26.  
  27. typedef struct doge_camera
  28. {
  29. doge_vec3_t pos;
  30. }doge_camera_t;
  31.  
  32. typedef struct doge_hit_point
  33. {
  34. doge_vec3_t pos;
  35. doge_vec3_t normal;
  36. doge_vec3_t color;
  37. float dist;
  38. }doge_hit_point_t;
  39.  
  40. int doge_sphere_hit_by_ray(doge_sphere_t sphere, doge_ray_t ray, doge_hit_point_t *hit)
  41. {
  42. hit->color = doge_vec3_create(0, 0, 0);
  43. hit->dist = 1e8;
  44. hit->normal = doge_vec3_create(0, 0, 0);
  45. hit->pos = doge_vec3_create(0, 0, 0);
  46.  
  47. doge_vec3_t l = doge_vec3_sub(sphere.pos, ray.start);
  48.  
  49. float tca = doge_vec3_dot(l, ray.dir);
  50.  
  51. if(tca < 0)
  52. {
  53. return 0;
  54. }
  55.  
  56. float d = (float)sqrt(doge_vec3_len_sq(l) - tca * tca);
  57. if(d > sphere.radius)
  58. {
  59. return 0;
  60. }
  61.  
  62. float thc = (float)sqrt(sphere.radius * sphere.radius - d * d);
  63.  
  64. float t0 = tca - thc;
  65. float t1 = tca + thc;
  66.  
  67. if (t1 < t0)
  68. hit->dist = t1;
  69. else
  70. hit->dist = t0;
  71.  
  72. hit->pos = doge_vec3_add(ray.start, doge_vec3_scaled(ray.dir, hit->dist));
  73. hit->color = sphere.color;
  74. hit->normal = doge_vec3_normalized(doge_vec3_sub(hit->pos, sphere.pos));
  75. return 1;
  76. }
  77.  
  78. doge_vec3_t doge_ray_trace(doge_ray_t ray, doge_world_t *world)
  79. {
  80. doge_hit_point_t hit_point;
  81. doge_hit_point_t best_hit;
  82.  
  83. doge_sphere_t *spheres = world->sphere_head;
  84. doge_sphere_t *sphere_hit = NULL;
  85.  
  86. best_hit.color = doge_vec3_create(1,1,1);
  87. best_hit.dist = 1e8;
  88.  
  89. while(spheres)
  90. {
  91. if(doge_sphere_hit_by_ray(*spheres, ray, &hit_point))
  92. {
  93. if(hit_point.dist < best_hit.dist)
  94. {
  95. best_hit = hit_point;
  96. sphere_hit = spheres;
  97. }
  98. }
  99. spheres = spheres->next;
  100. }
  101.  
  102. if(!sphere_hit)
  103. return best_hit.color;
  104.  
  105.  
  106. int inside = 0;
  107. if(doge_vec3_dot(ray.dir, best_hit.normal) > 0)
  108. inside = 1;
  109. float bias = 1e-4;
  110. // lambert diffuse
  111. doge_point_light_t *light = world->light_head;
  112. spheres = world->sphere_head;
  113. float lambert = 0;
  114.  
  115. while (light)
  116. {
  117. doge_vec3_t direction = doge_vec3_normalized(doge_vec3_sub(light->pos, best_hit.pos));
  118. doge_ray_t shadow_ray = doge_ray_create(best_hit.pos, direction);
  119. int is_in_shadow = 0;
  120. while (spheres)
  121. {
  122. if(doge_sphere_hit_by_ray(*spheres, shadow_ray, &hit_point))
  123. {
  124. is_in_shadow = 1;
  125. break;
  126. }
  127. spheres = spheres->next;
  128. }
  129.  
  130. if (!is_in_shadow)
  131. {
  132. float max = 0;
  133. float dot = doge_vec3_dot(direction, best_hit.normal);
  134. if(dot >= 0)
  135. {
  136. max = dot;
  137. }
  138. lambert += max;
  139. }
  140. light = light->next;
  141. }
  142.  
  143. best_hit.color = doge_vec3_scaled(best_hit.color, lambert);
  144.  
  145. return best_hit.color;
  146. }
  147.  
  148. // in main loop
  149. float fov_y = 60.0f;
  150. float vertical_size = (float)tan(3.1415296 / 180 * fov_y / 2);
  151. float horizontal_size = current_window.aspect_ratio * vertical_size;
  152.  
  153. for(int y = 0; y < current_window.height; y++)
  154. {
  155. for(int x = 0; x < current_window.width; x++)
  156. {
  157. float cam_space_x = (2 * (x / (float)current_window.width) - 1) * horizontal_size;
  158. float cam_space_y = (-2 * (y / (float)current_window.height) + 1) * vertical_size;
  159.  
  160. doge_vec3_t point = doge_vec3_create(cam_space_x, cam_space_y, 1);
  161.  
  162. doge_vec3_t direction = doge_vec3_normalized(point);
  163.  
  164. doge_ray_t ray = doge_ray_create(cam.pos, direction);
  165.  
  166. doge_vec3_t color = doge_ray_trace(ray, &world);
  167.  
  168. //clamp colors
  169. if(color.x > 1)
  170. color.x = 1;
  171.  
  172. if(color.y > 1)
  173. color.y = 1;
  174.  
  175. if(color.z > 1)
  176. color.z = 1;
  177.  
  178. doge_window_put_pixel(&current_window, x, y, (unsigned char)(color.x * 255), (unsigned char)(color.y * 255), (unsigned char)(color.z * 255));
  179. }
  180. }
Add Comment
Please, Sign In to add comment