camera.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include "camera.hpp"
  2. #include <Eigen/Dense>
  3. #include "warping.hpp"
  4. using namespace Eigen;
  5. struct hit{
  6. Vector3f pos;
  7. Vector3f normal;
  8. Vector3f indir;
  9. Vector3f outdir;
  10. const material& mat;
  11. };
  12. std::vector<Eigen::Vector3f> camera::get_image(const scene& sc, size_t n, sampler _rng)const{
  13. using namespace Eigen;
  14. std::vector<Eigen::Vector3f> img(n * n, Eigen::Vector3f(0,0,0));
  15. const Eigen::Vector3f lookray = (look_at - pos).normalized();
  16. const Eigen::Vector3f left = lookray.cross(up).normalized();
  17. const Eigen::Vector3f realup = left.cross(lookray);
  18. const int n2 = n / 2;
  19. size_t raycasts = 0;
  20. #pragma omp parallel
  21. {
  22. sampler rng;
  23. std::uniform_real_distribution<float> pert_dis(-0.5,0.5);
  24. #pragma omp for collapse(2) schedule(guided) reduction(+:raycasts)
  25. for(int j = 0;j < n;j++){
  26. for(int i = 0;i < n;i++){
  27. Eigen::Vector3d accum(0,0,0);
  28. std::vector<hit> hits;
  29. hits.reserve(6);
  30. for(size_t smp = 0;smp < 512;smp++){
  31. Eigen::Vector3f di = lookray + (left * ((pert_dis(rng.m_rng) + float(i - n2)) / n2 / 1.5)) + realup * ((pert_dis(rng.m_rng) + float(j - n2)) / n2 / 1.5);
  32. di.normalize();
  33. struct RTCRayHit rayhit;
  34. rayhit.ray.org_x = pos.x();
  35. rayhit.ray.org_y = pos.y();
  36. rayhit.ray.org_z = pos.z();
  37. rayhit.ray.dir_x = di.x();
  38. rayhit.ray.dir_y = di.y();
  39. rayhit.ray.dir_z = di.z();
  40. Vector3f hitpos = pos;
  41. Vector3f transport(1,1,1);
  42. hits.clear();
  43. for(size_t bounces = 0;bounces < 6;bounces++){
  44. struct RTCIntersectContext context;
  45. rtcInitIntersectContext(&context);
  46. rayhit.ray.tnear = 0.001f;
  47. rayhit.ray.tfar = std::numeric_limits<float>::infinity();
  48. rayhit.ray.mask = -1;
  49. rayhit.ray.flags = 0;
  50. rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
  51. rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
  52. rtcIntersect1(sc.m_scene, &context, &rayhit);
  53. raycasts++;
  54. if(rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID){
  55. if(sc.emitters.contains(rayhit.hit.geomID)){
  56. Eigen::Vector3d transport(sc.added_objects[sc.geom_id_to_object_index_map.find(rayhit.hit.geomID)->second]->mat.tex->eval(0,0).cast<double>());
  57. for(auto it = hits.rbegin();it != hits.rend();it++){
  58. transport.array() *= it->outdir.dot(it->normal);
  59. for(const auto& pl : sc.pointlight){
  60. struct RTCIntersectContext sh_context;
  61. rtcInitIntersectContext(&sh_context);
  62. Vector3f sh_ray(pl.pos - it->pos);
  63. if(sh_ray.dot(it->normal) < 0)continue;
  64. float sh_ray_length = sh_ray.norm();
  65. sh_ray /= sh_ray_length;
  66. RTCRay rsh_ray;
  67. rsh_ray.org_x = it->pos.x();
  68. rsh_ray.org_y = it->pos.y();
  69. rsh_ray.org_z = it->pos.z();
  70. rsh_ray.dir_x = sh_ray.x();
  71. rsh_ray.dir_y = sh_ray.y();
  72. rsh_ray.dir_z = sh_ray.z();
  73. rsh_ray.tnear = 0.001f;
  74. rsh_ray.tfar = sh_ray_length;
  75. rsh_ray.mask = -1;
  76. rsh_ray.flags = 0;
  77. raycasts++;
  78. rtcOccluded1(sc.m_scene, &sh_context, &rsh_ray);
  79. if(rsh_ray.tfar > 0){
  80. transport += pl.color.cast<double>() * std::abs(sh_ray.dot(it->normal)) * (1.0 / double(sh_ray_length * sh_ray_length));
  81. }
  82. }
  83. }
  84. accum += transport;
  85. goto inner;
  86. }
  87. rayhit.ray.org_x += rayhit.ray.dir_x * rayhit.ray.tfar;
  88. rayhit.ray.org_y += rayhit.ray.dir_y * rayhit.ray.tfar;
  89. rayhit.ray.org_z += rayhit.ray.dir_z * rayhit.ray.tfar;
  90. Vector3f hitnormal = Vector3f(rayhit.hit.Ng_x, rayhit.hit.Ng_y, rayhit.hit.Ng_z).normalized();
  91. Vector3f newdir = uniform_sphere(rng.next2D());
  92. if(newdir.dot(hitnormal) <= 0){
  93. newdir *= -1.0f;
  94. }
  95. hits.push_back(hit{
  96. Vector3f(rayhit.ray.org_x, rayhit.ray.org_y, rayhit.ray.org_z),
  97. hitnormal,
  98. Vector3f(rayhit.ray.dir_x, rayhit.ray.dir_y, rayhit.ray.dir_z),
  99. newdir,
  100. (sc.added_objects[sc.geom_id_to_object_index_map.find(rayhit.hit.geomID)->second]->mat)
  101. });
  102. transport *= newdir.dot(hitnormal);
  103. rayhit.ray.dir_x = newdir.x();
  104. rayhit.ray.dir_y = newdir.y();
  105. rayhit.ray.dir_z = newdir.z();
  106. }
  107. else{
  108. Eigen::Vector3d transport(0,0,0);
  109. for(auto it = hits.rbegin();it != hits.rend();it++){
  110. transport.array() *= it->outdir.dot(it->normal);
  111. for(const auto& pl : sc.pointlight){
  112. struct RTCIntersectContext sh_context;
  113. rtcInitIntersectContext(&sh_context);
  114. Vector3f sh_ray(pl.pos - it->pos);
  115. if(sh_ray.dot(it->normal) < 0)continue;
  116. float sh_ray_length = sh_ray.norm();
  117. sh_ray.normalize();
  118. RTCRay rsh_ray;
  119. rsh_ray.org_x = it->pos.x();
  120. rsh_ray.org_y = it->pos.y();
  121. rsh_ray.org_z = it->pos.z();
  122. rsh_ray.dir_x = sh_ray.x();
  123. rsh_ray.dir_y = sh_ray.y();
  124. rsh_ray.dir_z = sh_ray.z();
  125. rsh_ray.tnear = 0.001f;
  126. rsh_ray.tfar = sh_ray_length;
  127. rsh_ray.mask = -1;
  128. rsh_ray.flags = 0;
  129. raycasts++;
  130. rtcOccluded1(sc.m_scene, &sh_context, &rsh_ray);
  131. if(rsh_ray.tfar > 0){
  132. transport += pl.color.cast<double>() * std::abs(sh_ray.dot(it->normal)) * 1 / (sh_ray_length * sh_ray_length);
  133. }
  134. }
  135. }
  136. accum += transport;
  137. goto inner;
  138. }
  139. }
  140. {
  141. Eigen::Vector3d transport(0,0,0);
  142. for(auto it = hits.rbegin();it != hits.rend();it++){
  143. transport.array() *= it->outdir.dot(it->normal);
  144. for(const auto& pl : sc.pointlight){
  145. struct RTCIntersectContext sh_context;
  146. rtcInitIntersectContext(&sh_context);
  147. Vector3f sh_ray(pl.pos - it->pos);
  148. if(sh_ray.dot(it->normal) < 0)continue;
  149. float sh_ray_length = sh_ray.norm();
  150. sh_ray.normalize();
  151. RTCRay rsh_ray;
  152. rsh_ray.org_x = it->pos.x();
  153. rsh_ray.org_y = it->pos.y();
  154. rsh_ray.org_z = it->pos.z();
  155. rsh_ray.dir_x = sh_ray.x();
  156. rsh_ray.dir_y = sh_ray.y();
  157. rsh_ray.dir_z = sh_ray.z();
  158. rsh_ray.tnear = 0.001f;
  159. rsh_ray.tfar = sh_ray_length;
  160. rsh_ray.mask = -1;
  161. rsh_ray.flags = 0;
  162. raycasts++;
  163. rtcOccluded1(sc.m_scene, &sh_context, &rsh_ray);
  164. if(rsh_ray.tfar > 0){
  165. transport += pl.color.cast<double>() * std::abs(sh_ray.dot(it->normal)) * 1 / (sh_ray_length * sh_ray_length);
  166. }
  167. }
  168. }
  169. accum += transport;
  170. }
  171. inner:
  172. (void)0;
  173. }
  174. img[j * n + i] = (accum.cast<float>() / 512.0f).array().pow(0.5f).matrix();
  175. }
  176. }
  177. }
  178. std::cout << std::to_string(raycasts) + " Raycasts\n";
  179. return img;
  180. }
  181. camera::camera(const Eigen::Vector3f& loc, const Eigen::Vector3f& look, const Eigen::Vector3f& u) : pos(loc), look_at(look), up(u){
  182. }