diff --git a/source/camera.cpp b/source/camera.cpp index 5b97421..7c93765 100644 --- a/source/camera.cpp +++ b/source/camera.cpp @@ -15,10 +15,11 @@ #include #include -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); } diff --git a/source/include/camera.h b/source/include/camera.h index 96c0b2f..5415e99 100644 --- a/source/include/camera.h +++ b/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); }; diff --git a/source/include/math_helper.h b/source/include/math_helper.h index cde096c..d90f446 100644 --- a/source/include/math_helper.h +++ b/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) { diff --git a/source/math_helper.cpp b/source/math_helper.cpp index f1f78a2..ba8588f 100644 --- a/source/math_helper.cpp +++ b/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; } \ No newline at end of file