This commit is contained in:
2024-09-25 11:50:34 +02:00
commit 834a6f7cff
120 changed files with 55330 additions and 0 deletions

102
project/src/BRDFs.h Normal file
View File

@@ -0,0 +1,102 @@
#pragma once
#include "Maths.h"
namespace dae
{
namespace BRDF
{
/**
* \param kd Diffuse Reflection Coefficient
* \param cd Diffuse Color
* \return Lambert Diffuse Color
*/
static ColorRGB Lambert(float kd, const ColorRGB& cd)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
static ColorRGB Lambert(const ColorRGB& kd, const ColorRGB& cd)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
/**
* \brief todo
* \param ks Specular Reflection Coefficient
* \param exp Phong Exponent
* \param l Incoming (incident) Light Direction
* \param v View Direction
* \param n Normal of the Surface
* \return Phong Specular Color
*/
static ColorRGB Phong(float ks, float exp, const Vector3& l, const Vector3& v, const Vector3& n)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
/**
* \brief BRDF Fresnel Function >> Schlick
* \param h Normalized Halfvector between View and Light directions
* \param v Normalized View direction
* \param f0 Base reflectivity of a surface based on IOR (Indices Of Refrection), this is different for Dielectrics (Non-Metal) and Conductors (Metal)
* \return
*/
static ColorRGB FresnelFunction_Schlick(const Vector3& h, const Vector3& v, const ColorRGB& f0)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
/**
* \brief BRDF NormalDistribution >> Trowbridge-Reitz GGX (UE4 implemetation - squared(roughness))
* \param n Surface normal
* \param h Normalized half vector
* \param roughness Roughness of the material
* \return BRDF Normal Distribution Term using Trowbridge-Reitz GGX
*/
static float NormalDistribution_GGX(const Vector3& n, const Vector3& h, float roughness)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
/**
* \brief BRDF Geometry Function >> Schlick GGX (Direct Lighting + UE4 implementation - squared(roughness))
* \param n Normal of the surface
* \param v Normalized view direction
* \param roughness Roughness of the material
* \return BRDF Geometry Term using SchlickGGX
*/
static float GeometryFunction_SchlickGGX(const Vector3& n, const Vector3& v, float roughness)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
/**
* \brief BRDF Geometry Function >> Smith (Direct Lighting)
* \param n Normal of the surface
* \param v Normalized view direction
* \param l Normalized light direction
* \param roughness Roughness of the material
* \return BRDF Geometry Term using Smith (> SchlickGGX(n,v,roughness) * SchlickGGX(n,l,roughness))
*/
static float GeometryFunction_Smith(const Vector3& n, const Vector3& v, const Vector3& l, float roughness)
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
}
}

57
project/src/Camera.h Normal file
View File

@@ -0,0 +1,57 @@
#pragma once
#include <SDL_keyboard.h>
#include <SDL_mouse.h>
#include "Maths.h"
#include "Timer.h"
namespace dae
{
struct Camera
{
Camera() = default;
Camera(const Vector3& _origin, float _fovAngle) :
origin{ _origin },
fovAngle{ _fovAngle }
{
}
Vector3 origin{};
float fovAngle{ 90.f };
Vector3 forward{ Vector3::UnitZ };
Vector3 up{ Vector3::UnitY };
Vector3 right{ Vector3::UnitX };
float totalPitch{ 0.f };
float totalYaw{ 0.f };
Matrix cameraToWorld{};
Matrix CalculateCameraToWorld()
{
//todo: W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
void Update(Timer* pTimer)
{
const float deltaTime = pTimer->GetElapsed();
//Keyboard Input
const uint8_t* pKeyboardState = SDL_GetKeyboardState(nullptr);
//Mouse Input
int mouseX{}, mouseY{};
const uint32_t mouseState = SDL_GetRelativeMouseState(&mouseX, &mouseY);
//todo: W2
//throw std::runtime_error("Not Implemented Yet");
}
};
}

149
project/src/ColorRGB.h Normal file
View File

@@ -0,0 +1,149 @@
#pragma once
#include "MathHelpers.h"
namespace dae
{
struct ColorRGB
{
float r{};
float g{};
float b{};
void MaxToOne()
{
const float maxValue = std::max(r, std::max(g, b));
if (maxValue > 1.f)
*this /= maxValue;
}
static ColorRGB Lerp(const ColorRGB& c1, const ColorRGB& c2, float factor)
{
return { Lerpf(c1.r, c2.r, factor), Lerpf(c1.g, c2.g, factor), Lerpf(c1.b, c2.b, factor) };
}
#pragma region ColorRGB (Member) Operators
const ColorRGB& operator+=(const ColorRGB& c)
{
r += c.r;
g += c.g;
b += c.b;
return *this;
}
const ColorRGB& operator+(const ColorRGB& c)
{
return *this += c;
}
ColorRGB operator+(const ColorRGB& c) const
{
return { r + c.r, g + c.g, b + c.b };
}
const ColorRGB& operator-=(const ColorRGB& c)
{
r -= c.r;
g -= c.g;
b -= c.b;
return *this;
}
const ColorRGB& operator-(const ColorRGB& c)
{
return *this -= c;
}
ColorRGB operator-(const ColorRGB& c) const
{
return { r - c.r, g - c.g, b - c.b };
}
const ColorRGB& operator*=(const ColorRGB& c)
{
r *= c.r;
g *= c.g;
b *= c.b;
return *this;
}
const ColorRGB& operator*(const ColorRGB& c)
{
return *this *= c;
}
ColorRGB operator*(const ColorRGB& c) const
{
return { r * c.r, g * c.g, b * c.b };
}
const ColorRGB& operator/=(const ColorRGB& c)
{
r /= c.r;
g /= c.g;
b /= c.b;
return *this;
}
const ColorRGB& operator/(const ColorRGB& c)
{
return *this /= c;
}
const ColorRGB& operator*=(float s)
{
r *= s;
g *= s;
b *= s;
return *this;
}
const ColorRGB& operator*(float s)
{
return *this *= s;
}
ColorRGB operator*(float s) const
{
return { r * s, g * s,b * s };
}
const ColorRGB& operator/=(float s)
{
r /= s;
g /= s;
b /= s;
return *this;
}
const ColorRGB& operator/(float s)
{
return *this /= s;
}
#pragma endregion
};
//ColorRGB (Global) Operators
inline ColorRGB operator*(float s, const ColorRGB& c)
{
return c * s;
}
namespace colors
{
static ColorRGB Red{ 1,0,0 };
static ColorRGB Blue{ 0,0,1 };
static ColorRGB Green{ 0,1,0 };
static ColorRGB Yellow{ 1,1,0 };
static ColorRGB Cyan{ 0,1,1 };
static ColorRGB Magenta{ 1,0,1 };
static ColorRGB White{ 1,1,1 };
static ColorRGB Black{ 0,0,0 };
static ColorRGB Gray{ 0.5f,0.5f,0.5f };
}
}

181
project/src/DataTypes.h Normal file
View File

@@ -0,0 +1,181 @@
#pragma once
#include <stdexcept>
#include <vector>
#include "Maths.h"
namespace dae
{
#pragma region GEOMETRY
struct Sphere
{
Vector3 origin{};
float radius{};
unsigned char materialIndex{ 0 };
};
struct Plane
{
Vector3 origin{};
Vector3 normal{};
unsigned char materialIndex{ 0 };
};
enum class TriangleCullMode
{
FrontFaceCulling,
BackFaceCulling,
NoCulling
};
struct Triangle
{
Triangle() = default;
Triangle(const Vector3& _v0, const Vector3& _v1, const Vector3& _v2, const Vector3& _normal) :
v0{ _v0 }, v1{ _v1 }, v2{ _v2 }, normal{ _normal.Normalized() } {}
Triangle(const Vector3& _v0, const Vector3& _v1, const Vector3& _v2) :
v0{ _v0 }, v1{ _v1 }, v2{ _v2 }
{
const Vector3 edgeV0V1 = v1 - v0;
const Vector3 edgeV0V2 = v2 - v0;
normal = Vector3::Cross(edgeV0V1, edgeV0V2).Normalized();
}
Vector3 v0{};
Vector3 v1{};
Vector3 v2{};
Vector3 normal{};
TriangleCullMode cullMode{};
unsigned char materialIndex{};
};
struct TriangleMesh
{
TriangleMesh() = default;
TriangleMesh(const std::vector<Vector3>& _positions, const std::vector<int>& _indices, TriangleCullMode _cullMode) :
positions(_positions), indices(_indices), cullMode(_cullMode)
{
//Calculate Normals
CalculateNormals();
//Update Transforms
UpdateTransforms();
}
TriangleMesh(const std::vector<Vector3>& _positions, const std::vector<int>& _indices, const std::vector<Vector3>& _normals, TriangleCullMode _cullMode) :
positions(_positions), indices(_indices), normals(_normals), cullMode(_cullMode)
{
UpdateTransforms();
}
std::vector<Vector3> positions{};
std::vector<Vector3> normals{};
std::vector<int> indices{};
unsigned char materialIndex{};
TriangleCullMode cullMode{ TriangleCullMode::BackFaceCulling };
Matrix rotationTransform{};
Matrix translationTransform{};
Matrix scaleTransform{};
std::vector<Vector3> transformedPositions{};
std::vector<Vector3> transformedNormals{};
void Translate(const Vector3& translation)
{
translationTransform = Matrix::CreateTranslation(translation);
}
void RotateY(float yaw)
{
rotationTransform = Matrix::CreateRotationY(yaw);
}
void Scale(const Vector3& scale)
{
scaleTransform = Matrix::CreateScale(scale);
}
void AppendTriangle(const Triangle& triangle, bool ignoreTransformUpdate = false)
{
int startIndex = static_cast<int>(positions.size());
positions.push_back(triangle.v0);
positions.push_back(triangle.v1);
positions.push_back(triangle.v2);
indices.push_back(startIndex);
indices.push_back(++startIndex);
indices.push_back(++startIndex);
normals.push_back(triangle.normal);
//Not ideal, but making sure all vertices are updated
if (!ignoreTransformUpdate)
UpdateTransforms();
}
void CalculateNormals()
{
throw std::runtime_error("Not Implemented Yet");
}
void UpdateTransforms()
{
throw std::runtime_error("Not Implemented Yet");
//Calculate Final Transform
//const auto finalTransform = ...
//Transform Positions (positions > transformedPositions)
//...
//Transform Normals (normals > transformedNormals)
//...
}
};
#pragma endregion
#pragma region LIGHT
enum class LightType
{
Point,
Directional
};
struct Light
{
Vector3 origin{};
Vector3 direction{};
ColorRGB color{};
float intensity{};
LightType type{};
};
#pragma endregion
#pragma region MISC
struct Ray
{
Vector3 origin{};
Vector3 direction{};
float min{ 0.0001f };
float max{ FLT_MAX };
};
struct HitRecord
{
Vector3 origin{};
Vector3 normal{};
float t = FLT_MAX;
bool didHit{ false };
unsigned char materialIndex{ 0 };
};
#pragma endregion
}

123
project/src/Material.h Normal file
View File

@@ -0,0 +1,123 @@
#pragma once
#include "Maths.h"
#include "DataTypes.h"
#include "BRDFs.h"
namespace dae
{
#pragma region Material BASE
class Material
{
public:
Material() = default;
virtual ~Material() = default;
Material(const Material&) = delete;
Material(Material&&) noexcept = delete;
Material& operator=(const Material&) = delete;
Material& operator=(Material&&) noexcept = delete;
/**
* \brief Function used to calculate the correct color for the specific material and its parameters
* \param hitRecord current hitrecord
* \param l light direction
* \param v view direction
* \return color
*/
virtual ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) = 0;
};
#pragma endregion
#pragma region Material SOLID COLOR
//SOLID COLOR
//===========
class Material_SolidColor final : public Material
{
public:
Material_SolidColor(const ColorRGB& color) : m_Color(color)
{
}
ColorRGB Shade(const HitRecord& hitRecord, const Vector3& l, const Vector3& v) override
{
return m_Color;
}
private:
ColorRGB m_Color{ colors::White };
};
#pragma endregion
#pragma region Material LAMBERT
//LAMBERT
//=======
class Material_Lambert final : public Material
{
public:
Material_Lambert(const ColorRGB& diffuseColor, float diffuseReflectance) :
m_DiffuseColor(diffuseColor), m_DiffuseReflectance(diffuseReflectance) {}
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
private:
ColorRGB m_DiffuseColor{ colors::White };
float m_DiffuseReflectance{ 1.f }; //kd
};
#pragma endregion
#pragma region Material LAMBERT PHONG
//LAMBERT-PHONG
//=============
class Material_LambertPhong final : public Material
{
public:
Material_LambertPhong(const ColorRGB& diffuseColor, float kd, float ks, float phongExponent) :
m_DiffuseColor(diffuseColor), m_DiffuseReflectance(kd), m_SpecularReflectance(ks),
m_PhongExponent(phongExponent)
{
}
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
private:
ColorRGB m_DiffuseColor{ colors::White };
float m_DiffuseReflectance{ 0.5f }; //kd
float m_SpecularReflectance{ 0.5f }; //ks
float m_PhongExponent{ 1.f }; //Phong Exponent
};
#pragma endregion
#pragma region Material COOK TORRENCE
//COOK TORRENCE
class Material_CookTorrence final : public Material
{
public:
Material_CookTorrence(const ColorRGB& albedo, float metalness, float roughness) :
m_Albedo(albedo), m_Metalness(metalness), m_Roughness(roughness)
{
}
ColorRGB Shade(const HitRecord& hitRecord = {}, const Vector3& l = {}, const Vector3& v = {}) override
{
//todo: W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
private:
ColorRGB m_Albedo{ 0.955f, 0.637f, 0.538f }; //Copper
float m_Metalness{ 1.0f };
float m_Roughness{ 0.1f }; // [1.0 > 0.0] >> [ROUGH > SMOOTH]
};
#pragma endregion
}

32
project/src/MathHelpers.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <cmath>
#include <cfloat>
#include <algorithm>
namespace dae
{
/* --- CONSTANTS --- */
constexpr auto PI = 3.14159265358979323846f;
constexpr auto PI_DIV_2 = 1.57079632679489661923f;
constexpr auto PI_DIV_4 = 0.785398163397448309616f;
constexpr auto PI_2 = 6.283185307179586476925f;
constexpr auto PI_4 = 12.56637061435917295385f;
constexpr auto TO_DEGREES = (180.0f / PI);
constexpr auto TO_RADIANS(PI / 180.0f);
inline float Square(float a)
{
return a * a;
}
inline float Lerpf(float a, float b, float factor)
{
return ((1 - factor) * a) + (factor * b);
}
inline bool AreEqual(float a, float b, float epsilon = FLT_EPSILON)
{
return abs(a - b) < epsilon;
}
}

7
project/src/Maths.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include "Vector3.h"
#include "Vector4.h"
#include "Matrix.h"
#include "ColorRGB.h"
#include "MathHelpers.h"

214
project/src/Matrix.cpp Normal file
View File

@@ -0,0 +1,214 @@
#include <cassert>
#include <stdexcept>
#include <cmath>
#include "Matrix.h"
namespace dae {
Matrix::Matrix(const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis, const Vector3& t) :
Matrix({ xAxis, 0 }, { yAxis, 0 }, { zAxis, 0 }, { t, 1 })
{
}
Matrix::Matrix(const Vector4& xAxis, const Vector4& yAxis, const Vector4& zAxis, const Vector4& t)
{
data[0] = xAxis;
data[1] = yAxis;
data[2] = zAxis;
data[3] = t;
}
Matrix::Matrix(const Matrix& m)
{
data[0] = m[0];
data[1] = m[1];
data[2] = m[2];
data[3] = m[3];
}
Vector3 Matrix::TransformVector(const Vector3& v) const
{
return TransformVector(v[0], v[1], v[2]);
}
Vector3 Matrix::TransformVector(float x, float y, float z) const
{
return Vector3{
data[0].x * x + data[1].x * y + data[2].x * z,
data[0].y * x + data[1].y * y + data[2].y * z,
data[0].z * x + data[1].z * y + data[2].z * z
};
}
Vector3 Matrix::TransformPoint(const Vector3& p) const
{
return TransformPoint(p[0], p[1], p[2]);
}
Vector3 Matrix::TransformPoint(float x, float y, float z) const
{
return Vector3{
data[0].x * x + data[1].x * y + data[2].x * z + data[3].x,
data[0].y * x + data[1].y * y + data[2].y * z + data[3].y,
data[0].z * x + data[1].z * y + data[2].z * z + data[3].z,
};
}
const Matrix& Matrix::Transpose()
{
Matrix result{};
for (int r{ 0 }; r < 4; ++r)
{
for (int c{ 0 }; c < 4; ++c)
{
result[r][c] = data[c][r];
}
}
data[0] = result[0];
data[1] = result[1];
data[2] = result[2];
data[3] = result[3];
return *this;
}
Matrix Matrix::Transpose(const Matrix& m)
{
Matrix out{ m };
out.Transpose();
return out;
}
Vector3 Matrix::GetAxisX() const
{
return data[0];
}
Vector3 Matrix::GetAxisY() const
{
return data[1];
}
Vector3 Matrix::GetAxisZ() const
{
return data[2];
}
Vector3 Matrix::GetTranslation() const
{
return data[3];
}
Matrix Matrix::CreateTranslation(float x, float y, float z)
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
Matrix Matrix::CreateTranslation(const Vector3& t)
{
return { Vector3::UnitX, Vector3::UnitY, Vector3::UnitZ, t };
}
Matrix Matrix::CreateRotationX(float pitch)
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
Matrix Matrix::CreateRotationY(float yaw)
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
Matrix Matrix::CreateRotationZ(float roll)
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
Matrix Matrix::CreateRotation(const Vector3& r)
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
Matrix Matrix::CreateRotation(float pitch, float yaw, float roll)
{
return CreateRotation({ pitch, yaw, roll });
}
Matrix Matrix::CreateScale(float sx, float sy, float sz)
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return {};
}
Matrix Matrix::CreateScale(const Vector3& s)
{
return CreateScale(s[0], s[1], s[2]);
}
#pragma region Operator Overloads
Vector4& Matrix::operator[](int index)
{
assert(index <= 3 && index >= 0);
return data[index];
}
Vector4 Matrix::operator[](int index) const
{
assert(index <= 3 && index >= 0);
return data[index];
}
Matrix Matrix::operator*(const Matrix& m) const
{
Matrix result{};
Matrix m_transposed = Transpose(m);
for (int r{ 0 }; r < 4; ++r)
{
for (int c{ 0 }; c < 4; ++c)
{
result[r][c] = Vector4::Dot(data[r], m_transposed[c]);
}
}
return result;
}
const Matrix& Matrix::operator*=(const Matrix& m)
{
Matrix copy{ *this };
Matrix m_transposed = Transpose(m);
for (int r{ 0 }; r < 4; ++r)
{
for (int c{ 0 }; c < 4; ++c)
{
data[r][c] = Vector4::Dot(copy[r], m_transposed[c]);
}
}
return *this;
}
bool Matrix::operator==(const Matrix& m) const
{
return data[0] == m.data[0]
&& data[1] == m.data[1]
&& data[2] == m.data[2]
&& data[3] == m.data[3];
}
#pragma endregion
}

67
project/src/Matrix.h Normal file
View File

@@ -0,0 +1,67 @@
#pragma once
#include "Vector3.h"
#include "Vector4.h"
namespace dae {
struct Matrix
{
Matrix() = default;
Matrix(
const Vector3& xAxis,
const Vector3& yAxis,
const Vector3& zAxis,
const Vector3& t);
Matrix(
const Vector4& xAxis,
const Vector4& yAxis,
const Vector4& zAxis,
const Vector4& t);
Matrix(const Matrix& m);
Vector3 TransformVector(const Vector3& v) const;
Vector3 TransformVector(float x, float y, float z) const;
Vector3 TransformPoint(const Vector3& p) const;
Vector3 TransformPoint(float x, float y, float z) const;
const Matrix& Transpose();
Vector3 GetAxisX() const;
Vector3 GetAxisY() const;
Vector3 GetAxisZ() const;
Vector3 GetTranslation() const;
static Matrix CreateTranslation(float x, float y, float z);
static Matrix CreateTranslation(const Vector3& t);
static Matrix CreateRotationX(float pitch);
static Matrix CreateRotationY(float yaw);
static Matrix CreateRotationZ(float roll);
static Matrix CreateRotation(float pitch, float yaw, float roll);
static Matrix CreateRotation(const Vector3& r);
static Matrix CreateScale(float sx, float sy, float sz);
static Matrix CreateScale(const Vector3& s);
static Matrix Transpose(const Matrix& m);
Vector4& operator[](int index);
Vector4 operator[](int index) const;
Matrix operator*(const Matrix& m) const;
const Matrix& operator*=(const Matrix& m);
bool operator==(const Matrix& m) const;
private:
//Row-Major Matrix
Vector4 data[4]
{
{1,0,0,0}, //xAxis
{0,1,0,0}, //yAxis
{0,0,1,0}, //zAxis
{0,0,0,1} //T
};
// v0x v0y v0z v0w
// v1x v1y v1z v1w
// v2x v2y v2z v2w
// v3x v3y v3z v3w
};
}

58
project/src/Renderer.cpp Normal file
View File

@@ -0,0 +1,58 @@
//External includes
#include "SDL.h"
#include "SDL_surface.h"
//Project includes
#include "Renderer.h"
#include "Maths.h"
#include "Matrix.h"
#include "Material.h"
#include "Scene.h"
#include "Utils.h"
using namespace dae;
Renderer::Renderer(SDL_Window * pWindow) :
m_pWindow(pWindow),
m_pBuffer(SDL_GetWindowSurface(pWindow))
{
//Initialize
SDL_GetWindowSize(pWindow, &m_Width, &m_Height);
m_pBufferPixels = static_cast<uint32_t*>(m_pBuffer->pixels);
}
void Renderer::Render(Scene* pScene) const
{
Camera& camera = pScene->GetCamera();
auto& materials = pScene->GetMaterials();
auto& lights = pScene->GetLights();
for (int px{}; px < m_Width; ++px)
{
for (int py{}; py < m_Height; ++py)
{
float gradient = px / static_cast<float>(m_Width);
gradient += py / static_cast<float>(m_Width);
gradient /= 2.0f;
ColorRGB finalColor{ gradient, gradient, gradient };
//Update Color in Buffer
finalColor.MaxToOne();
m_pBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format,
static_cast<uint8_t>(finalColor.r * 255),
static_cast<uint8_t>(finalColor.g * 255),
static_cast<uint8_t>(finalColor.b * 255));
}
}
//@END
//Update SDL Surface
SDL_UpdateWindowSurface(m_pWindow);
}
bool Renderer::SaveBufferToImage() const
{
return SDL_SaveBMP(m_pBuffer, "RayTracing_Buffer.bmp");
}

35
project/src/Renderer.h Normal file
View File

@@ -0,0 +1,35 @@
#pragma once
#include <cstdint>
struct SDL_Window;
struct SDL_Surface;
namespace dae
{
class Scene;
class Renderer final
{
public:
Renderer(SDL_Window* pWindow);
~Renderer() = default;
Renderer(const Renderer&) = delete;
Renderer(Renderer&&) noexcept = delete;
Renderer& operator=(const Renderer&) = delete;
Renderer& operator=(Renderer&&) noexcept = delete;
void Render(Scene* pScene) const;
bool SaveBufferToImage() const;
private:
SDL_Window* m_pWindow{};
SDL_Surface* m_pBuffer{};
uint32_t* m_pBufferPixels{};
int m_Width{};
int m_Height{};
};
}

130
project/src/Scene.cpp Normal file
View File

@@ -0,0 +1,130 @@
#include "Scene.h"
#include "Utils.h"
#include "Material.h"
namespace dae {
#pragma region Base Scene
//Initialize Scene with Default Solid Color Material (RED)
Scene::Scene() :
m_Materials({ new Material_SolidColor({1,0,0}) })
{
m_SphereGeometries.reserve(32);
m_PlaneGeometries.reserve(32);
m_TriangleMeshGeometries.reserve(32);
m_Lights.reserve(32);
}
Scene::~Scene()
{
for (auto& pMaterial : m_Materials)
{
delete pMaterial;
pMaterial = nullptr;
}
m_Materials.clear();
}
void dae::Scene::GetClosestHit(const Ray& ray, HitRecord& closestHit) const
{
//todo W1
throw std::runtime_error("Not Implemented Yet");
}
bool Scene::DoesHit(const Ray& ray) const
{
//todo W2
throw std::runtime_error("Not Implemented Yet");
return false;
}
#pragma region Scene Helpers
Sphere* Scene::AddSphere(const Vector3& origin, float radius, unsigned char materialIndex)
{
Sphere s;
s.origin = origin;
s.radius = radius;
s.materialIndex = materialIndex;
m_SphereGeometries.emplace_back(s);
return &m_SphereGeometries.back();
}
Plane* Scene::AddPlane(const Vector3& origin, const Vector3& normal, unsigned char materialIndex)
{
Plane p;
p.origin = origin;
p.normal = normal;
p.materialIndex = materialIndex;
m_PlaneGeometries.emplace_back(p);
return &m_PlaneGeometries.back();
}
TriangleMesh* Scene::AddTriangleMesh(TriangleCullMode cullMode, unsigned char materialIndex)
{
TriangleMesh m{};
m.cullMode = cullMode;
m.materialIndex = materialIndex;
m_TriangleMeshGeometries.emplace_back(m);
return &m_TriangleMeshGeometries.back();
}
Light* Scene::AddPointLight(const Vector3& origin, float intensity, const ColorRGB& color)
{
Light l;
l.origin = origin;
l.intensity = intensity;
l.color = color;
l.type = LightType::Point;
m_Lights.emplace_back(l);
return &m_Lights.back();
}
Light* Scene::AddDirectionalLight(const Vector3& direction, float intensity, const ColorRGB& color)
{
Light l;
l.direction = direction;
l.intensity = intensity;
l.color = color;
l.type = LightType::Directional;
m_Lights.emplace_back(l);
return &m_Lights.back();
}
unsigned char Scene::AddMaterial(Material* pMaterial)
{
m_Materials.push_back(pMaterial);
return static_cast<unsigned char>(m_Materials.size() - 1);
}
#pragma endregion
#pragma endregion
#pragma region SCENE W1
void Scene_W1::Initialize()
{
//default: Material id0 >> SolidColor Material (RED)
constexpr unsigned char matId_Solid_Red = 0;
const unsigned char matId_Solid_Blue = AddMaterial(new Material_SolidColor{ colors::Blue });
const unsigned char matId_Solid_Yellow = AddMaterial(new Material_SolidColor{ colors::Yellow });
const unsigned char matId_Solid_Green = AddMaterial(new Material_SolidColor{ colors::Green });
const unsigned char matId_Solid_Magenta = AddMaterial(new Material_SolidColor{ colors::Magenta });
//Spheres
AddSphere({ -25.f, 0.f, 100.f }, 50.f, matId_Solid_Red);
AddSphere({ 25.f, 0.f, 100.f }, 50.f, matId_Solid_Blue);
//Plane
AddPlane({ -75.f, 0.f, 0.f }, { 1.f, 0.f,0.f }, matId_Solid_Green);
AddPlane({ 75.f, 0.f, 0.f }, { -1.f, 0.f,0.f }, matId_Solid_Green);
AddPlane({ 0.f, -75.f, 0.f }, { 0.f, 1.f,0.f }, matId_Solid_Yellow);
AddPlane({ 0.f, 75.f, 0.f }, { 0.f, -1.f,0.f }, matId_Solid_Yellow);
AddPlane({ 0.f, 0.f, 125.f }, { 0.f, 0.f,-1.f }, matId_Solid_Magenta);
}
#pragma endregion
}

80
project/src/Scene.h Normal file
View File

@@ -0,0 +1,80 @@
#pragma once
#include <string>
#include <vector>
#include "Maths.h"
#include "DataTypes.h"
#include "Camera.h"
namespace dae
{
//Forward Declarations
class Timer;
class Material;
struct Plane;
struct Sphere;
struct Light;
//Scene Base Class
class Scene
{
public:
Scene();
virtual ~Scene();
Scene(const Scene&) = delete;
Scene(Scene&&) noexcept = delete;
Scene& operator=(const Scene&) = delete;
Scene& operator=(Scene&&) noexcept = delete;
virtual void Initialize() = 0;
virtual void Update(dae::Timer* pTimer)
{
m_Camera.Update(pTimer);
}
Camera& GetCamera() { return m_Camera; }
void GetClosestHit(const Ray& ray, HitRecord& closestHit) const;
bool DoesHit(const Ray& ray) const;
const std::vector<Plane>& GetPlaneGeometries() const { return m_PlaneGeometries; }
const std::vector<Sphere>& GetSphereGeometries() const { return m_SphereGeometries; }
const std::vector<Light>& GetLights() const { return m_Lights; }
const std::vector<Material*> GetMaterials() const { return m_Materials; }
protected:
std::string sceneName;
std::vector<Plane> m_PlaneGeometries{};
std::vector<Sphere> m_SphereGeometries{};
std::vector<TriangleMesh> m_TriangleMeshGeometries{};
std::vector<Light> m_Lights{};
std::vector<Material*> m_Materials{};
Camera m_Camera{};
Sphere* AddSphere(const Vector3& origin, float radius, unsigned char materialIndex = 0);
Plane* AddPlane(const Vector3& origin, const Vector3& normal, unsigned char materialIndex = 0);
TriangleMesh* AddTriangleMesh(TriangleCullMode cullMode, unsigned char materialIndex = 0);
Light* AddPointLight(const Vector3& origin, float intensity, const ColorRGB& color);
Light* AddDirectionalLight(const Vector3& direction, float intensity, const ColorRGB& color);
unsigned char AddMaterial(Material* pMaterial);
};
//+++++++++++++++++++++++++++++++++++++++++
//WEEK 1 Test Scene
class Scene_W1 final : public Scene
{
public:
Scene_W1() = default;
~Scene_W1() override = default;
Scene_W1(const Scene_W1&) = delete;
Scene_W1(Scene_W1&&) noexcept = delete;
Scene_W1& operator=(const Scene_W1&) = delete;
Scene_W1& operator=(Scene_W1&&) noexcept = delete;
void Initialize() override;
};
}

144
project/src/Timer.cpp Normal file
View File

@@ -0,0 +1,144 @@
#include "Timer.h"
#include <iostream>
#include <numeric>
#include <iostream>
#include <fstream>
#include <float.h>
#include "SDL.h"
using namespace dae;
Timer::Timer()
{
const uint64_t countsPerSecond = SDL_GetPerformanceFrequency();
m_SecondsPerCount = 1.0f / static_cast<float>(countsPerSecond);
}
void Timer::Reset()
{
const uint64_t currentTime = SDL_GetPerformanceCounter();
m_BaseTime = currentTime;
m_PreviousTime = currentTime;
m_StopTime = 0;
m_FPSTimer = 0.0f;
m_FPSCount = 0;
m_IsStopped = false;
}
void Timer::Start()
{
const uint64_t startTime = SDL_GetPerformanceCounter();
if (m_IsStopped)
{
m_PausedTime += (startTime - m_StopTime);
m_PreviousTime = startTime;
m_StopTime = 0;
m_IsStopped = false;
}
}
void Timer::StartBenchmark(int numFrames)
{
if (m_BenchmarkActive)
{
std::cout << "(Benchmark already running)";
return;
}
m_BenchmarkActive = true;
m_BenchmarkAvg = 0.f;
m_BenchmarkHigh = FLT_MIN;
m_BenchmarkLow = FLT_MAX;
m_BenchmarkFrames = numFrames;
m_BenchmarkCurrFrame = 0;
m_Benchmarks.clear();
m_Benchmarks.resize(m_BenchmarkFrames);
std::cout << "**BENCHMARK STARTED**\n";
}
void Timer::Update()
{
if (m_IsStopped)
{
m_FPS = 0;
m_ElapsedTime = 0.0f;
m_TotalTime = (float)(((m_StopTime - m_PausedTime) - m_BaseTime) * m_BaseTime);
return;
}
const uint64_t currentTime = SDL_GetPerformanceCounter();
m_CurrentTime = currentTime;
m_ElapsedTime = (float)((m_CurrentTime - m_PreviousTime) * m_SecondsPerCount);
m_PreviousTime = m_CurrentTime;
if (m_ElapsedTime < 0.0f)
m_ElapsedTime = 0.0f;
if (m_ForceElapsedUpperBound && m_ElapsedTime > m_ElapsedUpperBound)
{
m_ElapsedTime = m_ElapsedUpperBound;
}
m_TotalTime = (float)(((m_CurrentTime - m_PausedTime) - m_BaseTime) * m_SecondsPerCount);
//FPS LOGIC
m_FPSTimer += m_ElapsedTime;
++m_FPSCount;
if (m_FPSTimer >= 1.0f)
{
m_dFPS = m_FPSCount / m_FPSTimer;
m_FPS = m_FPSCount;
m_FPSCount = 0;
m_FPSTimer = 0.0f;
if (m_BenchmarkActive)
{
m_Benchmarks[m_BenchmarkCurrFrame] = m_dFPS;
m_BenchmarkLow = std::min(m_BenchmarkLow, m_dFPS);
m_BenchmarkHigh = std::max(m_BenchmarkHigh, m_dFPS);
++m_BenchmarkCurrFrame;
if (m_BenchmarkCurrFrame >= m_BenchmarkFrames)
{
m_BenchmarkActive = false;
m_BenchmarkAvg = std::accumulate(m_Benchmarks.begin(), m_Benchmarks.end(), 0.f) / float(m_BenchmarkFrames);
//print
std::cout << "**BENCHMARK FINISHED**\n";
std::cout << ">> HIGH = " << m_BenchmarkHigh << std::endl;
std::cout << ">> LOW = " << m_BenchmarkLow << std::endl;
std::cout << ">> AVG = " << m_BenchmarkAvg << std::endl;
//file save
std::ofstream fileStream("benchmark.txt");
fileStream << "FRAMES = " << m_BenchmarkCurrFrame << std::endl;
fileStream << "HIGH = " << m_BenchmarkHigh << std::endl;
fileStream << "LOW = " << m_BenchmarkLow << std::endl;
fileStream << "AVG = " << m_BenchmarkAvg << std::endl;
fileStream.close();
}
}
}
}
void Timer::Stop()
{
if (!m_IsStopped)
{
const uint64_t currentTime = SDL_GetPerformanceCounter();
m_StopTime = currentTime;
m_IsStopped = true;
}
}

61
project/src/Timer.h Normal file
View File

@@ -0,0 +1,61 @@
#pragma once
//Standard includes
#include <cstdint>
#include <vector>
namespace dae
{
class Timer
{
public:
Timer();
virtual ~Timer() = default;
Timer(const Timer&) = delete;
Timer(Timer&&) noexcept = delete;
Timer& operator=(const Timer&) = delete;
Timer& operator=(Timer&&) noexcept = delete;
void StartBenchmark(int numFrames = 10);
void Reset();
void Start();
void Update();
void Stop();
uint32_t GetFPS() const { return m_FPS; };
float GetdFPS() const { return m_dFPS; };
float GetElapsed() const { return m_ElapsedTime; };
float GetTotal() const { return m_TotalTime; };
bool IsRunning() const { return !m_IsStopped; };
private:
uint64_t m_BaseTime = 0;
uint64_t m_PausedTime = 0;
uint64_t m_StopTime = 0;
uint64_t m_PreviousTime = 0;
uint64_t m_CurrentTime = 0;
uint32_t m_FPS = 0;
float m_dFPS = 0.0f;
uint32_t m_FPSCount = 0;
float m_TotalTime = 0.0f;
float m_ElapsedTime = 0.0f;
float m_SecondsPerCount = 0.0f;
float m_ElapsedUpperBound = 0.03f;
float m_FPSTimer = 0.0f;
bool m_IsStopped = true;
bool m_ForceElapsedUpperBound = false;
bool m_BenchmarkActive = false;
float m_BenchmarkHigh{ 0.f };
float m_BenchmarkLow{ 0.f };
float m_BenchmarkAvg{ 0.f };
int m_BenchmarkFrames{ 0 };
int m_BenchmarkCurrFrame{ 0 };
std::vector<float> m_Benchmarks{};
};
}

163
project/src/Utils.h Normal file
View File

@@ -0,0 +1,163 @@
#pragma once
#include <fstream>
#include "Maths.h"
#include "DataTypes.h"
namespace dae
{
namespace GeometryUtils
{
#pragma region Sphere HitTest
//SPHERE HIT-TESTS
inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{
//todo W1
throw std::runtime_error("Not Implemented Yet");
return false;
}
inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray)
{
HitRecord temp{};
return HitTest_Sphere(sphere, ray, temp, true);
}
#pragma endregion
#pragma region Plane HitTest
//PLANE HIT-TESTS
inline bool HitTest_Plane(const Plane& plane, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{
//todo W1
throw std::runtime_error("Not Implemented Yet");
return false;
}
inline bool HitTest_Plane(const Plane& plane, const Ray& ray)
{
HitRecord temp{};
return HitTest_Plane(plane, ray, temp, true);
}
#pragma endregion
#pragma region Triangle HitTest
//TRIANGLE HIT-TESTS
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{
//todo W5
throw std::runtime_error("Not Implemented Yet");
return false;
}
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray)
{
HitRecord temp{};
return HitTest_Triangle(triangle, ray, temp, true);
}
#pragma endregion
#pragma region TriangeMesh HitTest
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
{
//todo W5
throw std::runtime_error("Not Implemented Yet");
return false;
}
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray)
{
HitRecord temp{};
return HitTest_TriangleMesh(mesh, ray, temp, true);
}
#pragma endregion
}
namespace LightUtils
{
//Direction from target to light
inline Vector3 GetDirectionToLight(const Light& light, const Vector3 origin)
{
//todo W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
inline ColorRGB GetRadiance(const Light& light, const Vector3& target)
{
//todo W3
throw std::runtime_error("Not Implemented Yet");
return {};
}
}
namespace Utils
{
//Just parses vertices and indices
#pragma warning(push)
#pragma warning(disable : 4505) //Warning unreferenced local function
static bool ParseOBJ(const std::string& filename, std::vector<Vector3>& positions, std::vector<Vector3>& normals, std::vector<int>& indices)
{
std::ifstream file(filename);
if (!file)
return false;
std::string sCommand;
// start a while iteration ending when the end of file is reached (ios::eof)
while (!file.eof())
{
//read the first word of the string, use the >> operator (istream::operator>>)
file >> sCommand;
//use conditional statements to process the different commands
if (sCommand == "#")
{
// Ignore Comment
}
else if (sCommand == "v")
{
//Vertex
float x, y, z;
file >> x >> y >> z;
positions.push_back({ x, y, z });
}
else if (sCommand == "f")
{
float i0, i1, i2;
file >> i0 >> i1 >> i2;
indices.push_back((int)i0 - 1);
indices.push_back((int)i1 - 1);
indices.push_back((int)i2 - 1);
}
//read till end of line and ignore all remaining chars
file.ignore(1000, '\n');
if (file.eof())
break;
}
//Precompute normals
for (uint64_t index = 0; index < indices.size(); index += 3)
{
uint32_t i0 = indices[index];
uint32_t i1 = indices[index + 1];
uint32_t i2 = indices[index + 2];
Vector3 edgeV0V1 = positions[i1] - positions[i0];
Vector3 edgeV0V2 = positions[i2] - positions[i0];
Vector3 normal = Vector3::Cross(edgeV0V1, edgeV0V2);
if (std::isnan(normal.x))
{
int k = 0;
}
normal.Normalize();
if (std::isnan(normal.x))
{
int k = 0;
}
normals.push_back(normal);
}
return true;
}
#pragma warning(pop)
}
}

170
project/src/Vector3.cpp Normal file
View File

@@ -0,0 +1,170 @@
#include <cassert>
#include <cmath>
#include "Vector3.h"
#include <stdexcept>
#include "MathHelpers.h"
#include "Vector4.h"
namespace dae {
const Vector3 Vector3::UnitX = Vector3{ 1, 0, 0 };
const Vector3 Vector3::UnitY = Vector3{ 0, 1, 0 };
const Vector3 Vector3::UnitZ = Vector3{ 0, 0, 1 };
const Vector3 Vector3::Zero = Vector3{ 0, 0, 0 };
Vector3::Vector3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}
Vector3::Vector3(const Vector4& v) : x(v.x), y(v.y), z(v.z) {}
Vector3::Vector3(const Vector3& from, const Vector3& to) : x(to.x - from.x), y(to.y - from.y), z(to.z - from.z) {}
float Vector3::Magnitude() const
{
return std::sqrt(x * x + y * y + z * z);
}
float Vector3::SqrMagnitude() const
{
return x * x + y * y + z * z;
}
float Vector3::Normalize()
{
const float m = Magnitude();
x /= m;
y /= m;
z /= m;
return m;
}
Vector3 Vector3::Normalized() const
{
const float m = Magnitude();
return { x / m, y / m, z / m };
}
float Vector3::Dot(const Vector3& v1, const Vector3& v2)
{
//todo W1
throw std::runtime_error("Not Implemented Yet");
return {};
}
Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2)
{
//todo W1
throw std::runtime_error("Not Implemented Yet");
return {};
}
Vector3 Vector3::Project(const Vector3& v1, const Vector3& v2)
{
return (v2 * (Dot(v1, v2) / Dot(v2, v2)));
}
Vector3 Vector3::Reject(const Vector3& v1, const Vector3& v2)
{
return (v1 - v2 * (Dot(v1, v2) / Dot(v2, v2)));
}
Vector3 Vector3::Reflect(const Vector3& v1, const Vector3& v2)
{
return v1 - (2.f * Vector3::Dot(v1, v2) * v2);
}
Vector4 Vector3::ToPoint4() const
{
return { x, y, z, 1 };
}
Vector4 Vector3::ToVector4() const
{
return { x, y, z, 0 };
}
#pragma region Operator Overloads
Vector3 Vector3::operator*(float scale) const
{
return { x * scale, y * scale, z * scale };
}
Vector3 Vector3::operator/(float scale) const
{
return { x / scale, y / scale, z / scale };
}
Vector3 Vector3::operator+(const Vector3& v) const
{
return { x + v.x, y + v.y, z + v.z };
}
Vector3 Vector3::operator-(const Vector3& v) const
{
return { x - v.x, y - v.y, z - v.z };
}
Vector3 Vector3::operator-() const
{
return { -x ,-y,-z };
}
Vector3& Vector3::operator*=(float scale)
{
x *= scale;
y *= scale;
z *= scale;
return *this;
}
Vector3& Vector3::operator/=(float scale)
{
x /= scale;
y /= scale;
z /= scale;
return *this;
}
Vector3& Vector3::operator-=(const Vector3& v)
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
Vector3& Vector3::operator+=(const Vector3& v)
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
float& Vector3::operator[](int index)
{
assert(index <= 2 && index >= 0);
if (index == 0) return x;
if (index == 1) return y;
return z;
}
float Vector3::operator[](int index) const
{
assert(index <= 2 && index >= 0);
if (index == 0) return x;
if (index == 1) return y;
return z;
}
bool Vector3::operator==(const Vector3& v) const
{
return AreEqual(x, v.x) && AreEqual(y, v.y) && AreEqual(z, v.z);
}
#pragma endregion
}

58
project/src/Vector3.h Normal file
View File

@@ -0,0 +1,58 @@
#pragma once
namespace dae
{
struct Vector4;
struct Vector3
{
float x{};
float y{};
float z{};
Vector3() = default;
Vector3(float _x, float _y, float _z);
Vector3(const Vector3& from, const Vector3& to);
Vector3(const Vector4& v);
float Magnitude() const;
float SqrMagnitude() const;
float Normalize();
Vector3 Normalized() const;
static float Dot(const Vector3& v1, const Vector3& v2);
static Vector3 Cross(const Vector3& v1, const Vector3& v2);
static Vector3 Project(const Vector3& v1, const Vector3& v2);
static Vector3 Reject(const Vector3& v1, const Vector3& v2);
static Vector3 Reflect(const Vector3& v1, const Vector3& v2);
static Vector3 Lico(float f1, const Vector3& v1, float f2, const Vector3& v2, float f3, const Vector3& v3);
Vector4 ToPoint4() const;
Vector4 ToVector4() const;
//Member Operators
Vector3 operator*(float scale) const;
Vector3 operator/(float scale) const;
Vector3 operator+(const Vector3& v) const;
Vector3 operator-(const Vector3& v) const;
Vector3 operator-() const;
//Vector3& operator-();
Vector3& operator+=(const Vector3& v);
Vector3& operator-=(const Vector3& v);
Vector3& operator/=(float scale);
Vector3& operator*=(float scale);
float& operator[](int index);
float operator[](int index) const;
bool operator==(const Vector3& v) const;
static const Vector3 UnitX;
static const Vector3 UnitY;
static const Vector3 UnitZ;
static const Vector3 Zero;
};
//Global Operators
inline Vector3 operator*(float scale, const Vector3& v)
{
return { v.x * scale, v.y * scale, v.z * scale };
}
}

100
project/src/Vector4.cpp Normal file
View File

@@ -0,0 +1,100 @@
#include <cassert>
#include <cmath>
#include "Vector3.h"
#include "Vector4.h"
#include <stdexcept>
#include "MathHelpers.h"
namespace dae
{
Vector4::Vector4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) {}
Vector4::Vector4(const Vector3& v, float _w) : x(v.x), y(v.y), z(v.z), w(_w) {}
float Vector4::Magnitude() const
{
return std::sqrt(x * x + y * y + z * z + w * w);
}
float Vector4::SqrMagnitude() const
{
return x * x + y * y + z * z + w * w;
}
float Vector4::Normalize()
{
const float m = Magnitude();
x /= m;
y /= m;
z /= m;
w /= m;
return m;
}
Vector4 Vector4::Normalized() const
{
const float m = Magnitude();
return { x / m, y / m, z / m, w / m };
}
float Vector4::Dot(const Vector4& v1, const Vector4& v2)
{
//todo W1
throw std::runtime_error("Not Implemented Yet");
return {};
}
#pragma region Operator Overloads
Vector4 Vector4::operator*(float scale) const
{
return { x * scale, y * scale, z * scale, w * scale };
}
Vector4 Vector4::operator+(const Vector4& v) const
{
return { x + v.x, y + v.y, z + v.z, w + v.w };
}
Vector4 Vector4::operator-(const Vector4& v) const
{
return { x - v.x, y - v.y, z - v.z, w - v.w };
}
Vector4& Vector4::operator+=(const Vector4& v)
{
x += v.x;
y += v.y;
z += v.z;
w += v.w;
return *this;
}
float& Vector4::operator[](int index)
{
assert(index <= 3 && index >= 0);
if (index == 0)return x;
if (index == 1)return y;
if (index == 2)return z;
return w;
}
float Vector4::operator[](int index) const
{
assert(index <= 3 && index >= 0);
if (index == 0)return x;
if (index == 1)return y;
if (index == 2)return z;
return w;
}
bool Vector4::operator==(const Vector4& v) const
{
return AreEqual(x, v.x, .000001f) && AreEqual(y, v.y, .000001f) && AreEqual(z, v.z, .000001f) && AreEqual(w, v.w, .000001f);
}
#pragma endregion
}

33
project/src/Vector4.h Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
namespace dae
{
struct Vector3;
struct Vector4
{
float x;
float y;
float z;
float w;
Vector4() = default;
Vector4(float _x, float _y, float _z, float _w);
Vector4(const Vector3& v, float _w);
float Magnitude() const;
float SqrMagnitude() const;
float Normalize();
Vector4 Normalized() const;
static float Dot(const Vector4& v1, const Vector4& v2);
// operator overloading
Vector4 operator*(float scale) const;
Vector4 operator+(const Vector4& v) const;
Vector4 operator-(const Vector4& v) const;
Vector4& operator+=(const Vector4& v);
float& operator[](int index);
float operator[](int index) const;
bool operator==(const Vector4& v) const;
};
}

114
project/src/main.cpp Normal file
View File

@@ -0,0 +1,114 @@
//External includes
#ifdef ENABLE_VLD
#include "vld.h"
#endif
#include "SDL.h"
#include "SDL_surface.h"
#undef main
//Standard includes
#include <iostream>
//Project includes
#include "Timer.h"
#include "Renderer.h"
#include "Scene.h"
using namespace dae;
void ShutDown(SDL_Window* pWindow)
{
SDL_DestroyWindow(pWindow);
SDL_Quit();
}
int main(int argc, char* args[])
{
//Unreferenced parameters
(void)argc;
(void)args;
//Create window + surfaces
SDL_Init(SDL_INIT_VIDEO);
const uint32_t width = 640;
const uint32_t height = 480;
SDL_Window* pWindow = SDL_CreateWindow(
"RayTracer - **Insert Name**",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
width, height, 0);
if (!pWindow)
return 1;
//Initialize "framework"
const auto pTimer = new Timer();
const auto pRenderer = new Renderer(pWindow);
const auto pScene = new Scene_W1();
pScene->Initialize();
//Start loop
pTimer->Start();
// Start Benchmark
// pTimer->StartBenchmark();
float printTimer = 0.f;
bool isLooping = true;
bool takeScreenshot = false;
while (isLooping)
{
//--------- Get input events ---------
SDL_Event e;
while (SDL_PollEvent(&e))
{
switch (e.type)
{
case SDL_QUIT:
isLooping = false;
break;
case SDL_KEYUP:
if (e.key.keysym.scancode == SDL_SCANCODE_X)
takeScreenshot = true;
break;
}
}
//--------- Update ---------
pScene->Update(pTimer);
//--------- Render ---------
pRenderer->Render(pScene);
//--------- Timer ---------
pTimer->Update();
printTimer += pTimer->GetElapsed();
if (printTimer >= 1.f)
{
printTimer = 0.f;
std::cout << "dFPS: " << pTimer->GetdFPS() << std::endl;
}
//Save screenshot after full render
if (takeScreenshot)
{
if (!pRenderer->SaveBufferToImage())
std::cout << "Screenshot saved!" << std::endl;
else
std::cout << "Something went wrong. Screenshot not saved!" << std::endl;
takeScreenshot = false;
}
}
pTimer->Stop();
//Shutdown "framework"
delete pScene;
delete pRenderer;
delete pTimer;
ShutDown(pWindow);
return 0;
}