Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
catinjar committed Nov 16, 2021
0 parents commit a72eb4f
Show file tree
Hide file tree
Showing 72 changed files with 11,998 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cmake-build-debug
cmake-build-release
.idea
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.20)
project(RayTracer)

set(CMAKE_CXX_STANDARD 20)

add_executable(RayTracer src/main.cpp src/Vector3.cpp src/Vector3.hpp src/Ray.hpp src/HitRecord.hpp src/Hitable.hpp src/Sphere.cpp src/Sphere.hpp src/HitableList.cpp src/HitableList.hpp src/Camera.cpp src/Camera.hpp src/Material.hpp src/Lambertian.cpp src/Lambertian.hpp src/MathHelpers.cpp src/MathHelpers.hpp src/Metal.cpp src/Metal.hpp src/Dielectric.cpp src/Dielectric.hpp src/AABB.cpp src/AABB.hpp src/BvhNode.cpp src/BvhNode.hpp src/Texture.hpp src/ConstantTexture.cpp src/ConstantTexture.hpp src/CheckerTexture.cpp src/CheckerTexture.hpp src/Perlin.cpp src/Perlin.hpp src/NoiseTexture.cpp src/NoiseTexture.hpp src/ImageHelpers.cpp src/ImageHelpers.hpp src/ImageTexture.cpp src/ImageTexture.hpp src/DiffuseLight.cpp src/DiffuseLight.hpp src/Rect.hpp src/Scene.cpp src/Scene.hpp src/FlipNormals.cpp src/FlipNormals.hpp src/Box.cpp src/Box.hpp src/Translate.cpp src/Translate.hpp src/RotateY.cpp src/RotateY.hpp src/Isotropic.cpp src/Isotropic.hpp src/ConstantMedium.cpp src/ConstantMedium.hpp src/OrthoNormalBasis.cpp src/OrthoNormalBasis.hpp src/Pdf.hpp src/CosinePdf.cpp src/CosinePdf.hpp src/HitablePdf.cpp src/HitablePdf.hpp src/MixturePdf.cpp src/MixturePdf.hpp src/ScatterRecord.h src/ColorHelpers.cpp src/ColorHelpers.h)
30 changes: 30 additions & 0 deletions src/AABB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "AABB.hpp"

bool AABB::Hit(const Ray &ray, float minT, float maxT) const
{
for (int axisIndex = 0; axisIndex < 3; axisIndex++)
{
float inversedDirection = 1 / ray.direction[axisIndex];

float t0 = (min[axisIndex] - ray.origin[axisIndex]) * inversedDirection;
float t1 = (max[axisIndex] - ray.origin[axisIndex]) * inversedDirection;

if (inversedDirection < 0)
std::swap(t0, t1);

minT = t0 > minT ? t0 : minT;
maxT = t1 < maxT ? t1 : maxT;

if (maxT <= minT)
return false;
}

return true;
}

AABB SurroundingBox(AABB box1, AABB box2)
{
const Vector3 min(std::min(box1.min.x, box2.min.x), std::min(box1.min.y, box2.min.y), std::min(box1.min.z, box2.min.z));
const Vector3 max(std::max(box1.max.x, box2.max.x), std::max(box1.max.y, box2.max.y), std::max(box1.max.z, box2.max.z));
return { min, max };
}
22 changes: 22 additions & 0 deletions src/AABB.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef RAYTRACER_AABB_HPP
#define RAYTRACER_AABB_HPP


#include "Vector3.hpp"
#include "Ray.hpp"

class AABB
{
public:
AABB() = default;
AABB(const Vector3& min, const Vector3& max) : min(min), max(max) {}

bool Hit(const Ray& ray, float minT, float maxT) const;

Vector3 min;
Vector3 max;
};

AABB SurroundingBox(AABB box1, AABB box2);

#endif //RAYTRACER_AABB_HPP
26 changes: 26 additions & 0 deletions src/Box.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "Box.hpp"

#include "Rect.hpp"
#include "FlipNormals.hpp"

Box::Box(const Vector3 &min, const Vector3 &max, std::shared_ptr<Material> material)
: min(min), max(max)
{
sides.Add<XYRect>(min.x, max.x, min.y, max.y, max.z, material);
sides.Add<FlipNormals>(std::make_shared<XYRect>(min.x, max.x, min.y, max.y, min.z, material));
sides.Add<XZRect>(min.x, max.x, min.z, max.z, max.y, material);
sides.Add<FlipNormals>(std::make_shared<XZRect>(min.x, max.x, min.z, max.z, min.y, material));
sides.Add<YZRect>(min.y, max.y, min.z, max.z, max.x, material);
sides.Add<FlipNormals>(std::make_shared<YZRect>(min.y, max.y, min.z, max.z, min.x, material));
}

bool Box::Hit(const Ray &ray, float minT, float maxT, HitRecord &hitRecord) const
{
return sides.Hit(ray, minT, maxT, hitRecord);
}

bool Box::BoundingBox(AABB &box, float timeStart, float timeEnd) const
{
box = { min, max };
return true;
}
21 changes: 21 additions & 0 deletions src/Box.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef RAYTRACER_BOX_HPP
#define RAYTRACER_BOX_HPP


#include "HitableList.hpp"

class Box : public Hitable
{
public:
Box(const Vector3 &min, const Vector3 &max, std::shared_ptr<Material> material);

bool Hit(const Ray &ray, float minT, float maxT, HitRecord &hitRecord) const override;
bool BoundingBox(AABB &box, float timeStart, float timeEnd) const override;

Vector3 min;
Vector3 max;
HitableList sides;
};


#endif //RAYTRACER_BOX_HPP
106 changes: 106 additions & 0 deletions src/BvhNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include "BvhNode.hpp"

#include <iostream>
#include <algorithm>

#include "MathHelpers.hpp"

template<int axis>
struct BoxCompare
{
bool operator()(const std::shared_ptr<Hitable>& left, const std::shared_ptr<Hitable>& right)
{
AABB boxLeft {};
AABB boxRight {};

if (!left->BoundingBox(boxLeft, 0, 0) || !right->BoundingBox(boxRight, 0, 0))
std::cerr << "No bounding box in BvhNode constructor" << std::endl;

return boxLeft.min[axis] < boxRight.min[axis];
}
};

BvhNode::BvhNode(std::vector<std::shared_ptr<Hitable>>& hitables, int start, int end, float timeStart, float timeEnd)
{
const int sortAxis = int(3 * Random01());

switch (sortAxis)
{
case 0:
std::sort(hitables.begin() + start, hitables.begin() + end, BoxCompare<0>());
break;

case 1:
std::sort(hitables.begin() + start, hitables.begin() + end, BoxCompare<1>());
break;

default:
std::sort(hitables.begin() + start, hitables.begin() + end, BoxCompare<2>());
break;
}

const std::size_t count = end - start;

if (count == 1)
{
left = right = hitables[start];
}
else if (count == 2)
{
left = hitables[start];
right = hitables[start + 1];
}
else
{
left = std::make_shared<BvhNode>(hitables, start, start + (end - start) / 2, timeStart, timeEnd);
right = std::make_shared<BvhNode>(hitables , start + (end - start) / 2, end, timeStart, timeEnd);
}

AABB boxLeft {};
AABB boxRight {};

if (!left->BoundingBox(boxLeft, timeStart, timeEnd) || !right->BoundingBox(boxRight, timeStart, timeEnd))
std::cerr << "No bounding box in BvhNode constructor" << std::endl;

boundingBox = SurroundingBox(boxLeft, boxRight);
}

bool BvhNode::Hit(const Ray &ray, float minT, float maxT, HitRecord &hitRecord) const
{
if (boundingBox.Hit(ray, minT, maxT))
{
HitRecord leftHitRecord {};
HitRecord rightHitRecord {};

bool hitLeft = left->Hit(ray, minT, maxT, leftHitRecord);
bool hitRight = right->Hit(ray, minT, maxT, rightHitRecord);

if (hitLeft && hitRight)
{
hitRecord = leftHitRecord.t < rightHitRecord.t ? leftHitRecord : rightHitRecord;
return true;
}
else if (hitLeft)
{
hitRecord = leftHitRecord;
return true;
}
else if (hitRight)
{
hitRecord = rightHitRecord;
return true;
}
else
{
return false;
}
}

return false;
}

bool BvhNode::BoundingBox(AABB &box, float timeStart, float timeEnd) const
{
box = boundingBox;
return true;
}
24 changes: 24 additions & 0 deletions src/BvhNode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef RAYTRACER_BVHNODE_HPP
#define RAYTRACER_BVHNODE_HPP

#include <vector>

#include "Hitable.hpp"

class BvhNode : public Hitable
{
public:
BvhNode() = default;
BvhNode(std::vector<std::shared_ptr<Hitable>>& hitables, int start, int end, float timeStart, float timeEnd);

bool Hit(const Ray &ray, float minT, float maxT, HitRecord &hitRecord) const override;
bool BoundingBox(AABB &box, float timeStart, float timeEnd) const override;

std::shared_ptr<Hitable> left {};
std::shared_ptr<Hitable> right {};

AABB boundingBox {};
};


#endif //RAYTRACER_BVHNODE_HPP
35 changes: 35 additions & 0 deletions src/Camera.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "Camera.hpp"

#include <numbers>

#include "MathHelpers.hpp"

Camera::Camera(const Vector3& lookFrom, const Vector3& lookAt, const Vector3& viewUp, float verticalFov, float aspect, float aperture, float focusDistance, float timeStart, float timeEnd)
{
const float theta = verticalFov * (float)std::numbers::pi / 180;
const float halfHeight = std::tan(theta / 2);
const float halfWidth = aspect * halfHeight;

origin = lookFrom;

w = (lookFrom - lookAt).Normalized();
u = Cross(viewUp, w).Normalized();
v = Cross(w, u);

lowerLeft = origin - halfWidth * focusDistance * u - halfHeight * focusDistance * v - focusDistance * w;
horizontal = 2 * halfWidth * focusDistance * u;
vertical = 2 * halfHeight * focusDistance * v;

lensRadius = aperture / 2;

this->timeStart = timeStart;
this->timeEnd = timeEnd;
}

Ray Camera::GetRay(float s, float t) const
{
const auto randomPoint = lensRadius * GetRandomPointInUnitDisk();
const auto offset = u * randomPoint.x + v * randomPoint.y;
const float time = timeStart + Random01() * (timeEnd - timeStart);
return { origin + offset, lowerLeft + s * horizontal + t * vertical - origin - offset, time };
}
31 changes: 31 additions & 0 deletions src/Camera.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef RAYTRACER_CAMERA_HPP
#define RAYTRACER_CAMERA_HPP


#include "Vector3.hpp"
#include "Ray.hpp"

class Camera
{
public:
Camera() = default;
Camera(const Vector3& lookFrom, const Vector3& lookAt, const Vector3& viewUp, float verticalFov, float aspect, float aperture, float focusDistance, float timeStart, float timeEnd);

Ray GetRay(float s, float t) const;

Vector3 origin {};
Vector3 lowerLeft {};
Vector3 horizontal {};
Vector3 vertical {};

Vector3 u {};
Vector3 v {};
Vector3 w {};

float lensRadius = 0;
float timeStart = 0;
float timeEnd = 1;
};


#endif //RAYTRACER_CAMERA_HPP
10 changes: 10 additions & 0 deletions src/CheckerTexture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include "CheckerTexture.hpp"

Vector3 CheckerTexture::Value(float u, float v, const Vector3 &point) const
{
const float sines = std::sin(10 * point.x) * std::sin(10 * point.y) * std::sin(10 * point.z);

return sines < 0
? odd->Value(u, v, point)
: even->Value(u, v, point);
}
22 changes: 22 additions & 0 deletions src/CheckerTexture.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef RAYTRACER_CHECKERTEXTURE_HPP
#define RAYTRACER_CHECKERTEXTURE_HPP


#include <utility>

#include "Texture.hpp"

class CheckerTexture : public Texture
{
public:
CheckerTexture() = default;
CheckerTexture(std::shared_ptr<Texture> even, std::shared_ptr<Texture> odd) : odd(std::move(odd)), even(std::move(even)) {}

Vector3 Value(float u, float v, const Vector3 &point) const override;

std::shared_ptr<Texture> even;
std::shared_ptr<Texture> odd;
};


#endif //RAYTRACER_CHECKERTEXTURE_HPP
22 changes: 22 additions & 0 deletions src/ColorHelpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "ColorHelpers.h"

Vector3 DeNan(const Vector3 &color)
{
auto temp = color;

if (temp.r != temp.r)
temp.r = 0;

if (temp.g != temp.g)
temp.g = 0;

if (temp.b != temp.b)
temp.b = 0;

return temp;
}

Vector3 GammaCorrect(const Vector3 &color)
{
return { std::sqrt(color.r), std::sqrt(color.g), std::sqrt(color.b) };
}
10 changes: 10 additions & 0 deletions src/ColorHelpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef RAYTRACER_COLORHELPERS_H
#define RAYTRACER_COLORHELPERS_H


#include "Vector3.hpp"

Vector3 DeNan(const Vector3 &color);
Vector3 GammaCorrect(const Vector3 &color);

#endif //RAYTRACER_COLORHELPERS_H
Loading

0 comments on commit a72eb4f

Please sign in to comment.