camera.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * DoRayMe - a quick and dirty Raytracer
  3. * Camera implementation
  4. *
  5. * Created by Manoël Trapier
  6. * Copyright (c) 2020 986-Studio.
  7. *
  8. */
  9. #include <matrix.h>
  10. #include <stdint.h>
  11. #include <math.h>
  12. #include <ray.h>
  13. #include <camera.h>
  14. #include <stdio.h>
  15. #include <renderstat.h>
  16. Camera::Camera(uint32_t hsize, uint32_t vsize, double fov) : verticalSize(vsize),
  17. horizontalSize(hsize), fieldOfView(fov), focalDistance(1), apertureSize(0), rayCount(1)
  18. {
  19. double aspectRatio = (double)hsize / (double)vsize;
  20. double halfView = tan(fov / 2.0) * this->focalDistance;
  21. if (aspectRatio >= 1)
  22. {
  23. this->halfWidth = halfView;
  24. this->halfHeight = halfView / aspectRatio;
  25. }
  26. else
  27. {
  28. this->halfWidth = halfView * aspectRatio;
  29. this->halfHeight = halfView;
  30. }
  31. this->pixelSize = (this->halfWidth * 2) / this->horizontalSize;
  32. this->setTransform(Matrix4().identity());
  33. }
  34. void Camera::setTransform(Matrix transform)
  35. {
  36. this->transformMatrix = transform;
  37. this->inverseTransform = transform.inverse();
  38. }
  39. Ray Camera::rayForPixel(uint32_t pixelX, uint32_t pixelY, double horzOffset, double vertOffset)
  40. {
  41. double xOffset = ((double)pixelX + 0.5) * this->pixelSize;
  42. double yOffset = ((double)pixelY + 0.5) * this->pixelSize;
  43. double worldX = this->halfWidth - xOffset;
  44. double worldY = this->halfHeight - yOffset;
  45. Tuple pixel = this->inverseTransform * Point(worldX, worldY, -this->focalDistance);
  46. Tuple origin = this->inverseTransform * Point(horzOffset, vertOffset, 0);
  47. Tuple direction = (pixel - origin).normalise();
  48. stats.addCastedRay();
  49. return Ray(origin, direction);
  50. }
  51. Canvas Camera::render(World world, uint32_t depth)
  52. {
  53. uint32_t x, y;
  54. Canvas image = Canvas(this->horizontalSize, this->verticalSize);
  55. #pragma omp parallel default(shared) private(x, y) shared(image, stats)
  56. {
  57. #pragma omp for schedule(dynamic, 5)
  58. for (y = 0 ; y < this->verticalSize ; y++)
  59. {
  60. for (x = 0 ; x < this->horizontalSize ; x++)
  61. {
  62. Tuple colour;
  63. if (this->apertureSize > 0)
  64. {
  65. int i;
  66. for (i = 0 ; i < this->rayCount ; i++)
  67. {
  68. double horz = frandclip(-this->apertureSize/2, this->apertureSize / 2);
  69. double vert = frandclip(-this->apertureSize/2, this->apertureSize / 2);
  70. Ray r = this->rayForPixel(x, y, horz, vert);
  71. colour = colour + world.colourAt(r, depth);
  72. }
  73. colour = colour / this->rayCount;
  74. }
  75. else
  76. {
  77. Ray r = this->rayForPixel(x, y);
  78. colour = world.colourAt(r, depth);
  79. }
  80. stats.addPixel();
  81. image.putPixel(x, y, colour);
  82. }
  83. }
  84. }
  85. stats.printStats();
  86. return image;
  87. }