camera.cpp 12 KB

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