Advertisement
pasholnahuy

Untitled

Nov 2nd, 2024
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.44 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 IntersectionInfo {
  27. Intersection intersection;
  28. const Material* material;
  29. };
  30. std::optional<IntersectionInfo> SceneIntersection(const Ray& ray, const Scene& scene) {
  31. Intersection intersection{Vector(1, 0, 0), Vector(1, 0, 0),
  32. std::numeric_limits<double>::infinity()};
  33. const Material* material = nullptr;
  34. Vector normal;
  35. for (const auto& obj : scene.GetSphereObjects()) {
  36. std::optional<Intersection> cur_inter = GetIntersection(ray, obj.sphere);
  37. if (cur_inter.has_value() && cur_inter->GetDistance() < intersection.GetDistance()) {
  38. intersection = *cur_inter;
  39. material = obj.material;
  40. }
  41. }
  42. for (const auto& obj : scene.GetObjects()) {
  43. std::optional<Intersection> cur_inter = GetIntersection(ray, obj.polygon);
  44. if (cur_inter.has_value() && cur_inter->GetDistance() < intersection.GetDistance()) {
  45. intersection = *cur_inter;
  46. material = obj.material;
  47. if (obj.GetNormal(0) != nullptr) {
  48. Vector bars = GetBarycentricCoords(obj.polygon, cur_inter->GetPosition());
  49. normal = *(obj.GetNormal(0)) * bars[0] + *(obj.GetNormal(1)) * bars[1] +
  50. *(obj.GetNormal(2)) * bars[2];
  51. intersection =
  52. Intersection(intersection.GetPosition(), normal, intersection.GetDistance());
  53. }
  54. }
  55. }
  56. if (!material) {
  57. return {};
  58. }
  59. return IntersectionInfo{intersection, material};
  60. }
  61.  
  62. Vector GetColor(const Ray& ray, const Scene& scene) {
  63. constexpr double kEps = 1e-6;
  64. std::optional<IntersectionInfo> inter_info_optional = SceneIntersection(ray, scene);
  65. if (!inter_info_optional.has_value()) {
  66. return {0, 0, 0};
  67. }
  68. return {1, 1, 1};
  69. IntersectionInfo& inter_info = *inter_info_optional;
  70. Intersection intersection = inter_info.intersection;
  71. const Material* material = inter_info.material;
  72. Vector color;
  73. Vector light_color;
  74. for (const auto& light : scene.GetLights()) {
  75. auto to_light = light.position - intersection.GetPosition();
  76. auto sect = SceneIntersection(
  77. {intersection.GetPosition() + kEps * intersection.GetNormal(), to_light}, scene);
  78. if (sect && Length(to_light) > sect->intersection.GetDistance()) {
  79. continue;
  80. }
  81. return Vector(1, 1, 1);
  82. auto diffuse_part = DotProduct(to_light.Normalize(), intersection.GetNormal());
  83. auto specular_part =
  84. DotProduct(ray.GetDirection(),
  85. Reflect(to_light.Normalize(), intersection.GetNormal()).Normalize());
  86.  
  87. light_color +=
  88. light.intensity * (material->diffuse_color * std::max(0.0, diffuse_part) +
  89. material->specular_color * std::pow(std::max(0.0, specular_part),
  90. material->specular_exponent));
  91. }
  92. color = material->ambient_color + material->intensity + material->albedo[0] * light_color;
  93. return color;
  94. }
  95.  
  96. Image Render(const std::filesystem::path& path, const CameraOptions& camera_options,
  97. const RenderOptions& render_options) {
  98. Image image = Image(camera_options.screen_width, camera_options.screen_height);
  99. Scene scene = ReadScene(path);
  100. std::unordered_map<std::string, Material> materials = scene.GetMaterials();
  101. double half_pixel_size = Length(camera_options.look_to - camera_options.look_from) *
  102. std::tan(camera_options.fov / 2) / camera_options.screen_height;
  103. std::vector<std::vector<double>> min_dists(camera_options.screen_width,
  104. std::vector<double>(camera_options.screen_height));
  105. for (int x = 0; x < camera_options.screen_width; ++x) {
  106. for (int y = 0; y < camera_options.screen_height; ++y) {
  107. double cur_x = (-camera_options.screen_width + 1 + 2 * x) * half_pixel_size;
  108. double cur_y = (-camera_options.screen_height + 1 + 2 * y) * half_pixel_size;
  109. auto [right, up] = ScreenVectors(camera_options.look_from, camera_options.look_to);
  110. Vector pixel_coord = cur_x * right + cur_y * up + camera_options.look_to;
  111. Ray ray = Ray(camera_options.look_from, pixel_coord - camera_options.look_from);
  112. if (render_options.mode == RenderMode::kFull) {
  113. Vector color = GetColor(ray, scene);
  114. RGB rgb{static_cast<int>(color[0] * 255), static_cast<int>(color[1] * 255),
  115. static_cast<int>(color[2] * 255)};
  116. image.SetPixel(rgb, y, x);
  117. }
  118. }
  119. }
  120.  
  121. return image;
  122. }
  123.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement