Browse Source

Add possibility to play with focal length and aperture to the camera. Not enabled by default.

Godzil 4 years ago
parent
commit
61ce9d3543
4 changed files with 36 additions and 9 deletions
  1. 24 7
      source/camera.cpp
  2. 6 2
      source/include/camera.h
  3. 1 0
      source/include/math_helper.h
  4. 5 0
      source/math_helper.cpp

+ 24 - 7
source/camera.cpp

@@ -15,10 +15,11 @@
 #include <stdio.h>
 #include <renderstat.h>
 
-Camera::Camera(uint32_t hsize, uint32_t vsize, double fov) : verticalSize(vsize), horizontalSize(hsize), fieldOfView(fov)
+Camera::Camera(uint32_t hsize, uint32_t vsize, double fov, double focal, double aperture, uint32_t rayCount) : verticalSize(vsize),
+               horizontalSize(hsize), fieldOfView(fov), focalDistance(focal), apertureSize(aperture), rayCount(rayCount)
 {
     double aspectRatio = (double)hsize / (double)vsize;
-    double halfView = tan(fov / 2.0);
+    double halfView = tan(fov / 2.0) * this->focalDistance;
 
     if (aspectRatio >= 1)
     {
@@ -42,7 +43,7 @@ void Camera::setTransform(Matrix transform)
     this->inverseTransform = transform.inverse();
 }
 
-Ray Camera::rayForPixel(uint32_t pixelX, uint32_t pixelY)
+Ray Camera::rayForPixel(uint32_t pixelX, uint32_t pixelY, double horzOffset, double vertOffset)
 {
     double xOffset = ((double)pixelX + 0.5) * this->pixelSize;
     double yOffset = ((double)pixelY + 0.5) * this->pixelSize;
@@ -50,8 +51,8 @@ Ray Camera::rayForPixel(uint32_t pixelX, uint32_t pixelY)
     double worldX = this->halfWidth - xOffset;
     double worldY = this->halfHeight - yOffset;
 
-    Tuple pixel = this->inverseTransform * Point(worldX, worldY, -1);
-    Tuple origin = this->inverseTransform * Point(0, 0, 0);
+    Tuple pixel = this->inverseTransform * Point(worldX, worldY, -this->focalDistance);
+    Tuple origin = this->inverseTransform * Point(horzOffset,  vertOffset, 0);
     Tuple direction = (pixel - origin).normalise();
 
     stats.addCastedRay();
@@ -70,9 +71,25 @@ Canvas Camera::render(World world, uint32_t depth)
         {
             for (x = 0 ; x < this->horizontalSize ; x++)
             {
-                Ray r = this->rayForPixel(x, y);
-                Tuple colour = world.colourAt(r, depth);
+                Tuple colour;
+                if (this->apertureSize > 0)
+                {
+                    int i;
+                    for (i = 0 ; i < this->rayCount ; i++)
+                    {
+                        double horz = frandclip(-this->apertureSize/2, this->apertureSize / 2);
+                        double vert = frandclip(-this->apertureSize/2, this->apertureSize / 2);
+                        Ray r = this->rayForPixel(x, y, horz, vert);
+                        colour = colour + world.colourAt(r, depth);
+                    }
 
+                    colour = colour / this->rayCount;
+                }
+                else
+                {
+                    Ray r = this->rayForPixel(x, y);
+                    colour = world.colourAt(r, depth);
+                }
                 stats.addPixel();
                 image.putPixel(x, y, colour);
             }

+ 6 - 2
source/include/camera.h

@@ -21,6 +21,10 @@ private:
     double halfWidth;
     double halfHeight;
 public:
+    double focalDistance;
+    double apertureSize;
+    uint32_t rayCount;
+
     uint32_t verticalSize;
     uint32_t horizontalSize;
     double fieldOfView;
@@ -29,9 +33,9 @@ public:
     Matrix inverseTransform;
 
 public:
-    Camera(uint32_t hsize, uint32_t vsize, double fov);
+    Camera(uint32_t hsize, uint32_t vsize, double fov, double focal = 1, double aperture = 0, uint32_t rayCount = 1);
     void setTransform(Matrix transform);
-    Ray rayForPixel(uint32_t pixelX, uint32_t pixelY);
+    Ray rayForPixel(uint32_t pixelX, uint32_t pixelY, double horzOffset = 0, double vertOffset = 0);
     Canvas render(World w, uint32_t depth = 5);
 };
 

+ 1 - 0
source/include/math_helper.h

@@ -22,6 +22,7 @@ double min3(double a, double b, double c);
 double max3(double a, double b, double c);
 
 double frand();
+double frandclip(double min, double max);
 
 static double modulo(double a, double b)
 {

+ 5 - 0
source/math_helper.cpp

@@ -68,4 +68,9 @@ double max3(double a, double b, double c)
 double frand()
 {
     return rand() / ((double) RAND_MAX);
+}
+
+double frandclip(double min, double max)
+{
+    return (frand() * (max - min)) + min;
 }