Advertisement
pasholnahuy

Untitled

Nov 2nd, 2024
10
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. #pragma once
  2.  
  3. #include "options/camera_options.h"
  4. #include "options/render_options.h"
  5. #include "image.h"
  6.  
  7. #include <filesystem>
  8. #include <object.h>
  9. #include <scene.h>
  10. #include <intersection.h>
  11. #include <geometry.h>
  12.  
  13. std::pair<Vector, Vector> ScreenVectors(Vector from, Vector to) {
  14. Vector forward = to - from;
  15. Vector right = CrossProduct(Vector(0, -1, 0), forward);
  16. if (right[0] == 0 && right[1] == 0 && right[2] == 0) {
  17. right = Vector(1, 0, 0);
  18. } else {
  19. right.Normalize();
  20. }
  21. Vector up = CrossProduct(forward, right);
  22. up.Normalize();
  23. return {right, up};
  24. }
  25.  
  26. struct DebugInfo {
  27. double min_dist;
  28. double max_dist;
  29. Vector normal;
  30. };
  31. constexpr double kDoubleInf = std::numeric_limits<double>::max();
  32. DebugInfo ObjectProcessing(const std::vector<Object>& objects,
  33. const std::vector<SphereObject>& sphere_objects, const Ray& ray) {
  34. double min_dist = kDoubleInf;
  35. double max_dist = 0;
  36. Vector normal;
  37. for (const auto& obj : sphere_objects) {
  38. std::optional<Intersection> inter = GetIntersection(ray, obj.sphere);
  39. if (inter.has_value()) {
  40. double dist = inter->GetDistance();
  41. if (dist < min_dist) {
  42. max_dist = dist;
  43. min_dist = dist;
  44. normal = inter->GetNormal();
  45. assert(std::isfinite(normal[0]) && std::isfinite(normal[1]) &&
  46. std::isfinite(normal[2]));
  47. }
  48. }
  49. }
  50. for (const auto& obj : objects) {
  51. std::optional<Intersection> inter = GetIntersection(ray, obj.polygon);
  52. if (inter.has_value()) {
  53. double dist = inter->GetDistance();
  54. if (dist < min_dist) {
  55. max_dist = dist;
  56. min_dist = dist;
  57. normal = inter->GetNormal();
  58. assert(std::isfinite(normal[0]) && std::isfinite(normal[1]) &&
  59. std::isfinite(normal[2]));
  60. if (obj.GetNormal(0) != nullptr) {
  61. Vector bars = GetBarycentricCoords(obj.polygon, inter->GetPosition());
  62. normal = *(obj.GetNormal(0)) * bars[0] + *(obj.GetNormal(1)) * bars[1] +
  63. *(obj.GetNormal(2)) * bars[2];
  64. }
  65. }
  66. }
  67. }
  68. return {min_dist, max_dist, normal};
  69. }
  70.  
  71. Image Render(const std::filesystem::path& path, const CameraOptions& camera_options,
  72. const RenderOptions& render_options) {
  73. Image image = Image(camera_options.screen_width, camera_options.screen_height);
  74. Scene scene = ReadScene(path);
  75. std::vector<Object> objects = scene.GetObjects();
  76. std::vector<SphereObject> sphere_objects = scene.GetSphereObjects();
  77. std::vector<Light> lights = scene.GetLights();
  78. std::unordered_map<std::string, Material> materials = scene.GetMaterials();
  79. double half_pixel_size = Length(camera_options.look_to - camera_options.look_from) *
  80. std::tan(camera_options.fov / 2) / camera_options.screen_height;
  81. double max_dist = 0;
  82. std::vector<std::vector<double>> min_dists(camera_options.screen_width,
  83. std::vector<double>(camera_options.screen_height));
  84. for (int x = 0; x < camera_options.screen_width; ++x) {
  85. for (int y = 0; y < camera_options.screen_height; ++y) {
  86. double cur_x = (-camera_options.screen_width + 1 + 2 * x) * half_pixel_size;
  87. double cur_y = (-camera_options.screen_height + 1 + 2 * y) * half_pixel_size;
  88. auto [right, up] = ScreenVectors(camera_options.look_from, camera_options.look_to);
  89. Vector pixel_coord = cur_x * right + cur_y * up + camera_options.look_to;
  90. Ray ray = Ray(camera_options.look_from, pixel_coord - camera_options.look_from);
  91. if (render_options.mode == RenderMode::kDepth ||
  92. render_options.mode == RenderMode::kNormal) {
  93. auto [min_dist, max_dist_cur, normal] =
  94. ObjectProcessing(objects, sphere_objects, ray);
  95. max_dist = std::max(max_dist, max_dist_cur);
  96. min_dists[x][y] = min_dist;
  97. if (render_options.mode == RenderMode::kNormal) {
  98. if (min_dist == kDoubleInf) {
  99. image.SetPixel({0, 0, 0}, y, x);
  100. } else {
  101. RGB val{};
  102. assert(std::isfinite(normal[0]) && std::isfinite(normal[1]) &&
  103. std::isfinite(normal[2]));
  104. normal = 0.5 * (normal + Vector(1, 1, 1));
  105. val.r = std::round(255 * normal[0]);
  106. val.g = std::round(255 * normal[1]);
  107. val.b = std::round(255 * normal[2]);
  108. image.SetPixel(val, y, x);
  109. }
  110. }
  111. }
  112. }
  113. }
  114. if (render_options.mode == RenderMode::kDepth) {
  115. for (int x = 0; x < camera_options.screen_width; ++x) {
  116. for (int y = 0; y < camera_options.screen_height; ++y) {
  117. if (min_dists[x][y] == kDoubleInf) {
  118. image.SetPixel({255, 255, 255}, y, x);
  119. } else {
  120. int c = std::round(min_dists[x][y] / max_dist * 255);
  121. image.SetPixel({c, c, c}, y, x);
  122. }
  123. }
  124. }
  125. }
  126.  
  127. return image;
  128. }
  129.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement