Compare commits
1 Commits
18845abe1c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| a83ecb32bb |
8
.gitignore
vendored
8
.gitignore
vendored
@@ -18,6 +18,9 @@ bld/
|
|||||||
# Visual Studio
|
# Visual Studio
|
||||||
.vs/
|
.vs/
|
||||||
|
|
||||||
|
# Clion
|
||||||
|
.idea
|
||||||
|
|
||||||
# Do not ignore libs
|
# Do not ignore libs
|
||||||
!project/libs/**
|
!project/libs/**
|
||||||
|
|
||||||
@@ -28,3 +31,8 @@ bld/
|
|||||||
*.iws
|
*.iws
|
||||||
*.iws.*
|
*.iws.*
|
||||||
cmake-build-debug/**
|
cmake-build-debug/**
|
||||||
|
|
||||||
|
cmake-build-default/**
|
||||||
|
cmake-build-minsizerel/**
|
||||||
|
cmake-build-relwithdebinfo/**
|
||||||
|
cmake-build-release/**
|
||||||
@@ -85,9 +85,17 @@ namespace dae
|
|||||||
Matrix translationTransform{};
|
Matrix translationTransform{};
|
||||||
Matrix scaleTransform{};
|
Matrix scaleTransform{};
|
||||||
|
|
||||||
|
Vector3 minAABB{};
|
||||||
|
Vector3 maxAABB{};
|
||||||
|
|
||||||
|
Vector3 transformedMinAABB{};
|
||||||
|
Vector3 transformedMaxAABB{};
|
||||||
|
|
||||||
std::vector<Vector3> transformedPositions{};
|
std::vector<Vector3> transformedPositions{};
|
||||||
std::vector<Vector3> transformedNormals{};
|
std::vector<Vector3> transformedNormals{};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Translate(const Vector3& translation)
|
void Translate(const Vector3& translation)
|
||||||
{
|
{
|
||||||
translationTransform = Matrix::CreateTranslation(translation);
|
translationTransform = Matrix::CreateTranslation(translation);
|
||||||
@@ -124,21 +132,107 @@ namespace dae
|
|||||||
|
|
||||||
void CalculateNormals()
|
void CalculateNormals()
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Not Implemented Yet");
|
constexpr int triSides{ 3 };
|
||||||
|
const size_t nTris{ indices.size() / triSides };
|
||||||
|
normals.resize(nTris);
|
||||||
|
|
||||||
|
for(size_t triIndex{}; triIndex < nTris; ++triIndex)
|
||||||
|
{
|
||||||
|
const Vector3& v0{ positions[indices[triIndex * triSides + 0]] };
|
||||||
|
const Vector3& v1{ positions[indices[triIndex * triSides + 1]] };
|
||||||
|
const Vector3& v2{ positions[indices[triIndex * triSides + 2]] };
|
||||||
|
|
||||||
|
const Vector3 v0v1{ v1 - v0 };
|
||||||
|
const Vector3 v0v2{ v2 - v0 };
|
||||||
|
|
||||||
|
const Vector3 normal{ Vector3::Cross(v0v1, v0v2).Normalized() };
|
||||||
|
|
||||||
|
normals[triIndex] = normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateTransforms()
|
void UpdateTransforms()
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Not Implemented Yet");
|
const size_t vertexCount = positions.size();
|
||||||
//Calculate Final Transform
|
const size_t normalCount = normals.size();
|
||||||
//const auto finalTransform = ...
|
const Matrix finalTransform{ scaleTransform * rotationTransform * translationTransform };
|
||||||
|
transformedPositions.resize(vertexCount);
|
||||||
|
transformedNormals.resize(normalCount);
|
||||||
|
|
||||||
//Transform Positions (positions > transformedPositions)
|
|
||||||
//...
|
|
||||||
|
|
||||||
//Transform Normals (normals > transformedNormals)
|
for (size_t i = 0; i < vertexCount; ++i)
|
||||||
//...
|
{
|
||||||
|
transformedPositions[i] = finalTransform.TransformPoint(positions[i]);
|
||||||
}
|
}
|
||||||
|
for(size_t i = 0; i < normalCount; ++i){
|
||||||
|
transformedNormals[i] = finalTransform.TransformVector(normals[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateTransformedAABB(finalTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateAABB(){
|
||||||
|
if(positions.size() > 0){
|
||||||
|
minAABB = positions[0];
|
||||||
|
maxAABB = positions[0];
|
||||||
|
for (auto& p : positions)
|
||||||
|
{
|
||||||
|
minAABB = Vector3::Min(minAABB, p);
|
||||||
|
maxAABB = Vector3::Max(maxAABB, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateTransformedAABB(const Matrix& finalTransform) {
|
||||||
|
// AABB update: be careful -> transform the 8 vertices of the aabb
|
||||||
|
// and calculate new min and max.
|
||||||
|
Vector3 tMinAABB = finalTransform.TransformPoint(minAABB);
|
||||||
|
Vector3 tMaxAABB = tMinAABB;
|
||||||
|
|
||||||
|
// (xmax, ymin, zmin)
|
||||||
|
Vector3 tAABB = finalTransform.TransformPoint(maxAABB.x, minAABB.y, minAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmax, ymin, zmax)
|
||||||
|
tAABB = finalTransform.TransformPoint(maxAABB.x, minAABB.y, maxAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmin, ymax, zmax)
|
||||||
|
tAABB = finalTransform.TransformPoint(minAABB.x, maxAABB.y, maxAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmin, ymin, zmax)
|
||||||
|
tAABB = finalTransform.TransformPoint(minAABB.x, minAABB.y, maxAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmax, ymax, zmin)
|
||||||
|
tAABB = finalTransform.TransformPoint(maxAABB.x, maxAABB.y, minAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmin, ymax, zmin)
|
||||||
|
tAABB = finalTransform.TransformPoint(minAABB.x, maxAABB.y, minAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmax, ymax, zmax)
|
||||||
|
tAABB = finalTransform.TransformPoint(maxAABB.x, maxAABB.y, maxAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
// (xmin, ymin, zmax)
|
||||||
|
tAABB = finalTransform.TransformPoint(minAABB.x, minAABB.y, maxAABB.z);
|
||||||
|
tMinAABB = Vector3::Min(tAABB, tMinAABB);
|
||||||
|
tMaxAABB = Vector3::Max(tAABB, tMaxAABB);
|
||||||
|
|
||||||
|
transformedMinAABB = tMinAABB;
|
||||||
|
transformedMaxAABB = tMaxAABB;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
#pragma region LIGHT
|
#pragma region LIGHT
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_surface.h"
|
#include "SDL_surface.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <execution>
|
||||||
|
|
||||||
//Project includes
|
//Project includes
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
@@ -21,10 +23,10 @@ Renderer::Renderer(SDL_Window *pWindow) :
|
|||||||
m_pBufferPixels = static_cast<uint32_t *>(m_pBuffer->pixels);
|
m_pBufferPixels = static_cast<uint32_t *>(m_pBuffer->pixels);
|
||||||
|
|
||||||
m_xvalues.reserve(m_Width);
|
m_xvalues.reserve(m_Width);
|
||||||
for (uint16_t x{}; x < m_Width; ++x) {
|
for(uint16_t x{}; x < m_Width; ++x)
|
||||||
|
{
|
||||||
m_xvalues.push_back(x);
|
m_xvalues.push_back(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Render(Scene *pScene) const {
|
void Renderer::Render(Scene *pScene) const {
|
||||||
@@ -36,168 +38,17 @@ void Renderer::Render(Scene *pScene) const {
|
|||||||
|
|
||||||
float apsectRatio = static_cast<float>(m_Width) / m_Height;
|
float apsectRatio = static_cast<float>(m_Width) / m_Height;
|
||||||
float fov = tan((camera.fovAngle * (PI / 180.f)) / 2);
|
float fov = tan((camera.fovAngle * (PI / 180.f)) / 2);
|
||||||
for (int px{}; px < m_Width; px += 1) {
|
|
||||||
for (int py{}; py < m_Height; py += 1) {
|
|
||||||
|
|
||||||
int actualPx = px;
|
uint32_t amountOfPixels = m_Width * m_Height;
|
||||||
// if (py % 2 != 0) {
|
std::vector<uint32_t> pixelIndices{};
|
||||||
// actualPx = px + 1;
|
pixelIndices.reserve(amountOfPixels);
|
||||||
// }
|
for (uint32_t i{}; i < amountOfPixels; ++i) {
|
||||||
|
pixelIndices.push_back(i);
|
||||||
float NDCx = ((2 * ((actualPx + 0.5) / m_Width) - 1) * apsectRatio) * fov;
|
|
||||||
float NDCy = (1 - 2 * ((py + 0.5) / m_Height)) * fov;
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 rayDir = Vector3{NDCx, NDCy, 1};
|
|
||||||
rayDir = CameraToWorld.TransformVector((rayDir));
|
|
||||||
rayDir.Normalize();
|
|
||||||
|
|
||||||
Ray ray{camera.origin, rayDir};
|
|
||||||
|
|
||||||
|
|
||||||
//set the color based on the ray direction
|
|
||||||
ColorRGB finalColor{0.f, 0.f, 0.f};
|
|
||||||
|
|
||||||
HitRecord closestHit{};
|
|
||||||
pScene->GetClosestHit(ray, closestHit);
|
|
||||||
|
|
||||||
|
|
||||||
if (closestHit.didHit) {
|
|
||||||
for (const Light &light: lights) {
|
|
||||||
Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)};
|
|
||||||
float rayMaxValue = lightDirection.Normalize();
|
|
||||||
Ray lightRay = Ray{closestHit.origin + closestHit.normal * 0.01f, lightDirection, 0.0001f,
|
|
||||||
rayMaxValue};
|
|
||||||
bool doesLightHit = pScene->DoesHit(lightRay);
|
|
||||||
|
|
||||||
|
|
||||||
if (m_CurrentLightingMode == LightingMode::Radiance) {
|
|
||||||
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
|
||||||
auto radiance = LightUtils::GetRadiance(light, closestHit.origin);
|
|
||||||
finalColor += radiance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::for_each(std::execution::par, pixelIndices.begin(), pixelIndices.end(), [&](uint32_t& pixelIndex) {
|
||||||
} else if (m_CurrentLightingMode == LightingMode::ObservedArea) {
|
this->RenderPixel(pScene, pixelIndex, fov, apsectRatio, CameraToWorld, camera.origin);
|
||||||
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
});
|
||||||
// float observedArea = std::clamp(
|
|
||||||
// LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f);
|
|
||||||
// finalColor.r += observedArea;
|
|
||||||
// finalColor.g += observedArea;
|
|
||||||
// finalColor.b += observedArea;
|
|
||||||
}
|
|
||||||
} else if (m_CurrentLightingMode == LightingMode::Combined) {
|
|
||||||
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
|
||||||
auto radiance = LightUtils::GetRadiance(light, closestHit.origin);
|
|
||||||
float observedArea = std::clamp(
|
|
||||||
LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f);
|
|
||||||
|
|
||||||
finalColor += radiance * observedArea *
|
|
||||||
materials[closestHit.materialIndex]->Shade(closestHit, lightDirection,
|
|
||||||
rayDir);
|
|
||||||
}
|
|
||||||
} else if (m_CurrentLightingMode == LightingMode::BRDF) {
|
|
||||||
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
|
||||||
auto radiance = LightUtils::GetRadiance(light, closestHit.origin);
|
|
||||||
float observedArea = std::clamp(
|
|
||||||
LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f);
|
|
||||||
|
|
||||||
finalColor += materials[closestHit.materialIndex]->Shade(closestHit, lightDirection, ray.direction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// if (m_CurrentLightingMode == LightingMode::ObservedArea) {
|
|
||||||
// if (closestHit.didHit) {
|
|
||||||
// for (const Light &light: lights) {
|
|
||||||
// Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)};
|
|
||||||
// const float lightDistance = lightDirection.Normalize();
|
|
||||||
//
|
|
||||||
// float law = std::clamp(LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f);
|
|
||||||
//// finalColor += materials[closestHit.materialIndex]->Shade() * law;
|
|
||||||
// finalColor += ColorRGB{law, law, law};
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (m_ShadowsEnabled) {
|
|
||||||
//
|
|
||||||
// if (closestHit.didHit) {
|
|
||||||
//// finalColor = materials[closestHit.materialIndex]->Shade();
|
|
||||||
// if (m_ShadowsEnabled) {
|
|
||||||
// for (const Light &light: lights) {
|
|
||||||
// Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)};
|
|
||||||
// const float lightDistance = lightDirection.Normalize();
|
|
||||||
//
|
|
||||||
// const Ray lightRay{
|
|
||||||
// closestHit.origin + closestHit.normal * 0.01f,
|
|
||||||
// lightDirection, 0.0001f, lightDistance
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// if (pScene->DoesHit(lightRay)) {
|
|
||||||
// finalColor *= 0.5;
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
finalColor.MaxToOne();
|
|
||||||
|
|
||||||
m_pBufferPixels[actualPx + (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));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// go over the pixels and avg the pixels i skipped
|
|
||||||
// for (int px2{1}; px2 < m_Width; px2 += 2) {
|
|
||||||
// for (int py{1}; py < m_Height; py += 1) {
|
|
||||||
// if (px2 == m_Width - 1 || py == m_Height - 1) continue;
|
|
||||||
// if (px2 == 0 || py == 0) continue;
|
|
||||||
//
|
|
||||||
// int px = px2;
|
|
||||||
// if (py % 2 != 0) {
|
|
||||||
// px = px2 + 1;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// uint8_t r = 0;
|
|
||||||
// uint8_t g = 0;
|
|
||||||
// uint8_t b = 0;
|
|
||||||
// SDL_GetRGB(m_pBufferPixels[px + (py * m_Width)], m_pBuffer->format, &r, &g, &b);
|
|
||||||
// ColorRGB currentColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f};
|
|
||||||
//
|
|
||||||
// SDL_GetRGB(m_pBufferPixels[(px - 1) + (py * m_Width)], m_pBuffer->format, &r, &g, &b);
|
|
||||||
// ColorRGB leftColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f};
|
|
||||||
//
|
|
||||||
// SDL_GetRGB(m_pBufferPixels[(px + 1) + (py * m_Width)], m_pBuffer->format, &r, &g, &b);
|
|
||||||
// ColorRGB rightColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f};
|
|
||||||
//
|
|
||||||
// SDL_GetRGB(m_pBufferPixels[px + ((py - 1) * m_Width)], m_pBuffer->format, &r, &g, &b);
|
|
||||||
// ColorRGB upColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f};
|
|
||||||
//
|
|
||||||
// SDL_GetRGB(m_pBufferPixels[px + ((py + 1) * m_Width)], m_pBuffer->format, &r, &g, &b);
|
|
||||||
// ColorRGB downColor = ColorRGB{r / 255.f, g / 255.f, b / 255.f};
|
|
||||||
//
|
|
||||||
// float avgR = (leftColor.r + rightColor.r + upColor.r + downColor.r) / 4;
|
|
||||||
// float avgG = (leftColor.g + rightColor.g + upColor.g + downColor.g) / 4;
|
|
||||||
// float avgB = (leftColor.b + rightColor.b + upColor.b + downColor.b) / 4;
|
|
||||||
// ColorRGB avgColor = ColorRGB{avgR, avgG, avgB};
|
|
||||||
//
|
|
||||||
// m_pBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBuffer->format,
|
|
||||||
// static_cast<uint8_t>(avgColor.r * 255),
|
|
||||||
// static_cast<uint8_t>(avgColor.g * 255),
|
|
||||||
// static_cast<uint8_t>(avgColor.b * 255));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//@END
|
//@END
|
||||||
//Update SDL Surface
|
//Update SDL Surface
|
||||||
@@ -266,3 +117,85 @@ void Renderer::CycleLightingMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::RenderPixel(Scene *pScene, uint32_t pixelIndex, float fov, float aspectRatio, const Matrix cameraToWorld,
|
||||||
|
const Vector3 &cameraPosition) const {
|
||||||
|
|
||||||
|
auto materials = pScene->GetMaterials();
|
||||||
|
auto lights = pScene->GetLights();
|
||||||
|
|
||||||
|
const uint32_t px{ pixelIndex % m_Width}, py{ pixelIndex / m_Width };
|
||||||
|
|
||||||
|
float NDCx{px + 0.5f }, NDCy{py + 0.5f };
|
||||||
|
float cx{(2.f * NDCx / m_Width - 1.f) * aspectRatio * fov };
|
||||||
|
float cy{(1.f - 2.f * NDCy / m_Height) * fov };
|
||||||
|
|
||||||
|
Vector3 rayDir{ cx, cy, 1.f };
|
||||||
|
rayDir = cameraToWorld.TransformVector((rayDir));
|
||||||
|
rayDir.Normalize();
|
||||||
|
|
||||||
|
Ray ray{cameraPosition, rayDir};
|
||||||
|
|
||||||
|
|
||||||
|
//set the color based on the ray direction
|
||||||
|
ColorRGB finalColor{0.f, 0.f, 0.f};
|
||||||
|
|
||||||
|
HitRecord closestHit{};
|
||||||
|
pScene->GetClosestHit(ray, closestHit);
|
||||||
|
|
||||||
|
|
||||||
|
if (closestHit.didHit) {
|
||||||
|
for (const Light &light: lights) {
|
||||||
|
Vector3 lightDirection{LightUtils::GetDirectionToLight(light, closestHit.origin)};
|
||||||
|
float rayMaxValue = lightDirection.Normalize();
|
||||||
|
Ray lightRay = Ray{closestHit.origin + closestHit.normal * 0.01f, lightDirection, 0.0001f,
|
||||||
|
rayMaxValue};
|
||||||
|
bool doesLightHit = pScene->DoesHit(lightRay);
|
||||||
|
|
||||||
|
|
||||||
|
if (m_CurrentLightingMode == LightingMode::Radiance) {
|
||||||
|
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
||||||
|
auto radiance = LightUtils::GetRadiance(light, closestHit.origin);
|
||||||
|
finalColor += radiance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else if (m_CurrentLightingMode == LightingMode::ObservedArea) {
|
||||||
|
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
||||||
|
float observedArea = std::clamp(
|
||||||
|
LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f);
|
||||||
|
finalColor.r += observedArea;
|
||||||
|
finalColor.g += observedArea;
|
||||||
|
finalColor.b += observedArea;
|
||||||
|
}
|
||||||
|
} else if (m_CurrentLightingMode == LightingMode::Combined) {
|
||||||
|
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
||||||
|
auto radiance = LightUtils::GetRadiance(light, closestHit.origin);
|
||||||
|
float observedArea = std::clamp(
|
||||||
|
LightUtils::LambertCosineLaw(closestHit.normal, lightDirection), 0.0f, 1.0f);
|
||||||
|
|
||||||
|
finalColor += radiance * observedArea *
|
||||||
|
materials[closestHit.materialIndex]->Shade(closestHit, lightDirection,
|
||||||
|
rayDir);
|
||||||
|
}
|
||||||
|
} else if (m_CurrentLightingMode == LightingMode::BRDF) {
|
||||||
|
if (!m_ShadowsEnabled or (m_ShadowsEnabled and !doesLightHit)) {
|
||||||
|
|
||||||
|
finalColor += materials[closestHit.materialIndex]->Shade(closestHit, lightDirection,
|
||||||
|
ray.direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finalColor.MaxToOne();
|
||||||
|
|
||||||
|
m_pBufferPixels[pixelIndex] = 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));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ namespace dae
|
|||||||
Renderer& operator=(Renderer&&) noexcept = delete;
|
Renderer& operator=(Renderer&&) noexcept = delete;
|
||||||
|
|
||||||
void Render(Scene* pScene) const;
|
void Render(Scene* pScene) const;
|
||||||
|
|
||||||
|
void RenderPixel(Scene* pScene, uint32_t pixelIndex, float fov, float aspectRatio, const Matrix cameraToWorld, const Vector3& cameraPosition) const;
|
||||||
|
|
||||||
bool SaveBufferToImage() const;
|
bool SaveBufferToImage() const;
|
||||||
|
|
||||||
void CycleLightingMode();
|
void CycleLightingMode();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace dae {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dae::Scene::GetClosestHit(const Ray &ray, HitRecord &closestHit) const {
|
void dae::Scene::GetClosestHit(const Ray &ray, HitRecord &closestHit) const {
|
||||||
closestHit.t = FLT_MAX;
|
closestHit.t = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
for (const Plane &plane: m_PlaneGeometries) {
|
for (const Plane &plane: m_PlaneGeometries) {
|
||||||
HitRecord hitRecord{};
|
HitRecord hitRecord{};
|
||||||
@@ -43,6 +43,21 @@ namespace dae {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(const TriangleMesh& mesh : m_TriangleMeshGeometries)
|
||||||
|
{
|
||||||
|
HitRecord hit{};
|
||||||
|
GeometryUtils::HitTest_TriangleMesh(mesh, ray, hit);
|
||||||
|
if(hit.t < closestHit.t)
|
||||||
|
closestHit = hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for(const Triangle& mesh : m_Triangles)
|
||||||
|
// {
|
||||||
|
// HitRecord hit{};
|
||||||
|
// GeometryUtils::HitTest_Triangle(mesh, ray, hit);
|
||||||
|
// if(hit.t < closestHit.t)
|
||||||
|
// closestHit = hit;
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,6 +76,18 @@ namespace dae {
|
|||||||
if(GeometryUtils::HitTest_Plane(plane, ray, hit, true))
|
if(GeometryUtils::HitTest_Plane(plane, ray, hit, true))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
for(const TriangleMesh& mesh : m_TriangleMeshGeometries)
|
||||||
|
{
|
||||||
|
if(GeometryUtils::HitTest_TriangleMesh(mesh, ray, hit, true))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for(const Triangle& mesh : m_Triangles)
|
||||||
|
// {
|
||||||
|
// if(GeometryUtils::HitTest_Triangle(mesh, ray, hit, true))
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -214,4 +241,49 @@ namespace dae {
|
|||||||
AddPointLight(Vector3{ -2.5f, 5.f, -5.f }, 70.f, ColorRGB{ 1.f, .8f, .45f }); //Front Light Left
|
AddPointLight(Vector3{ -2.5f, 5.f, -5.f }, 70.f, ColorRGB{ 1.f, .8f, .45f }); //Front Light Left
|
||||||
AddPointLight(Vector3{ 2.5f, 2.5f, -5.f }, 50.f, ColorRGB{ .34f, .47f, .68f });
|
AddPointLight(Vector3{ 2.5f, 2.5f, -5.f }, 50.f, ColorRGB{ .34f, .47f, .68f });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scene_W4_TestScene::Initialize() {
|
||||||
|
m_Camera.origin = { 0.f, 1.f, -5.f };
|
||||||
|
m_Camera.SetFOV(45.f);
|
||||||
|
|
||||||
|
// Materials
|
||||||
|
const auto matLambert_GrayBlue = AddMaterial(new Material_Lambert({ 0.49f, 0.57f, 0.57f }, 1.f));
|
||||||
|
const auto matLambert_White = AddMaterial(new Material_Lambert(colors::White, 1.f));
|
||||||
|
|
||||||
|
// Planes
|
||||||
|
AddPlane(Vector3{ 0.f, 0.f, 10.f }, Vector3{ 0.f, 0.f, -1.f }, matLambert_GrayBlue); // BACK
|
||||||
|
AddPlane(Vector3{ 0.f, 0.f, 0.f }, Vector3{ 0.f, 1.f, 0.f }, matLambert_GrayBlue); // BOTTOM
|
||||||
|
AddPlane(Vector3{ 0.f, 10.f, 0.f }, Vector3{ 0.f, -1.f, 0.f }, matLambert_GrayBlue); // TOP
|
||||||
|
AddPlane(Vector3{ 5.f, 0.f, 0.f }, Vector3{ -1.f, 0.f, 0.f }, matLambert_GrayBlue); // RIGHT
|
||||||
|
AddPlane(Vector3{ -5.f, 0.f, 0.f }, Vector3{ 1.f, 0.f, 0.f }, matLambert_GrayBlue); // LEFT
|
||||||
|
|
||||||
|
// // Triangle (Temp)
|
||||||
|
auto triangle = Triangle{ { -.75f, .5f, 0.f }, { -.75f, 2.f, 0.f }, { .75f, .5f, 0.f } };
|
||||||
|
triangle.cullMode = TriangleCullMode::NoCulling;
|
||||||
|
triangle.materialIndex = matLambert_White;
|
||||||
|
|
||||||
|
m_Triangles.emplace_back(triangle);
|
||||||
|
|
||||||
|
//
|
||||||
|
pMesh = AddTriangleMesh(TriangleCullMode::NoCulling, matLambert_White);
|
||||||
|
Utils::ParseOBJ("Resources/lowpoly_bunny.obj", pMesh->positions, pMesh->normals, pMesh->indices);
|
||||||
|
// pMesh->Scale({2.f, 2.f, 2.f});
|
||||||
|
// pMesh->Scale({2.f, 2.f, 2.f});
|
||||||
|
pMesh->RotateY(PI_DIV_2);
|
||||||
|
|
||||||
|
pMesh->UpdateAABB();
|
||||||
|
pMesh->UpdateTransforms();
|
||||||
|
|
||||||
|
// Light
|
||||||
|
AddPointLight(Vector3{ 0.f, 5.f, 5.f }, 50.f, ColorRGB{ 1.f, .61f, .45f }); // Backlight
|
||||||
|
AddPointLight(Vector3{ -2.5f, 5.f, -5.f }, 70.f, ColorRGB{ 1.f, .8f, .45f }); // Front Light Left
|
||||||
|
AddPointLight(Vector3{ 2.5f, 5.f, -5.f }, 50.f, ColorRGB{ .34f, .47f, .68f }); // Front Light Right
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene_W4_TestScene::Update(Timer *timer) {
|
||||||
|
Scene::Update(timer);
|
||||||
|
|
||||||
|
// pMesh->RotateY(PI_DIV_2 * timer->GetTotal());
|
||||||
|
// pMesh->UpdateTransforms();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ namespace dae
|
|||||||
std::vector<Light> m_Lights{};
|
std::vector<Light> m_Lights{};
|
||||||
std::vector<Material*> m_Materials{};
|
std::vector<Material*> m_Materials{};
|
||||||
|
|
||||||
|
std::vector<Triangle> m_Triangles{};
|
||||||
|
|
||||||
Camera m_Camera{};
|
Camera m_Camera{};
|
||||||
|
|
||||||
Sphere* AddSphere(const Vector3& origin, float radius, unsigned char materialIndex = 0);
|
Sphere* AddSphere(const Vector3& origin, float radius, unsigned char materialIndex = 0);
|
||||||
@@ -94,7 +96,6 @@ namespace dae
|
|||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Scene_W3 final : public Scene
|
class Scene_W3 final : public Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -108,4 +109,24 @@ namespace dae
|
|||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Scene_W4_TestScene final : public Scene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Scene_W4_TestScene() = default;
|
||||||
|
~Scene_W4_TestScene() override = default;
|
||||||
|
|
||||||
|
Scene_W4_TestScene(const Scene_W4_TestScene&) = delete;
|
||||||
|
Scene_W4_TestScene(Scene_W4_TestScene&&) noexcept = delete;
|
||||||
|
Scene_W4_TestScene& operator=(const Scene_W4_TestScene&) = delete;
|
||||||
|
Scene_W4_TestScene& operator=(Scene_W4_TestScene&&) noexcept = delete;
|
||||||
|
|
||||||
|
void Initialize() override;
|
||||||
|
void Update(Timer* timer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
TriangleMesh* pMesh{ nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <memory>
|
||||||
#include "Maths.h"
|
#include "Maths.h"
|
||||||
#include "DataTypes.h"
|
#include "DataTypes.h"
|
||||||
|
|
||||||
namespace dae
|
namespace dae {
|
||||||
{
|
namespace GeometryUtils {
|
||||||
namespace GeometryUtils
|
|
||||||
{
|
|
||||||
#pragma region Sphere HitTest
|
#pragma region Sphere HitTest
|
||||||
|
|
||||||
//SPHERE HIT-TESTS
|
//SPHERE HIT-TESTS
|
||||||
inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
inline bool
|
||||||
{
|
HitTest_Sphere(const Sphere &sphere, const Ray &ray, HitRecord &hitRecord, bool ignoreHitRecord = false) {
|
||||||
const float radius2 = sphere.radius * sphere.radius;
|
const float radius2 = sphere.radius * sphere.radius;
|
||||||
const Vector3 CameraToOrigin = sphere.origin - ray.origin;
|
const Vector3 CameraToOrigin = sphere.origin - ray.origin;
|
||||||
const float tInSphere = Vector3::Dot(CameraToOrigin, ray.direction);
|
const float tInSphere = Vector3::Dot(CameraToOrigin, ray.direction);
|
||||||
|
|
||||||
if(tInSphere < 0) return false; //Looking away from sphere
|
if (tInSphere < 0) return false; //Looking away from sphere
|
||||||
|
|
||||||
float originToInsideDist2 = CameraToOrigin.SqrMagnitude() - tInSphere * tInSphere;
|
float originToInsideDist2 = CameraToOrigin.SqrMagnitude() - tInSphere * tInSphere;
|
||||||
if(originToInsideDist2 > radius2)
|
if (originToInsideDist2 > radius2)
|
||||||
return false; // 'inside' point is outside of sphere
|
return false; // 'inside' point is outside of sphere
|
||||||
|
|
||||||
float tDiff = std::sqrt(radius2 - originToInsideDist2);
|
float tDiff = std::sqrt(radius2 - originToInsideDist2);
|
||||||
@@ -27,7 +28,7 @@ namespace dae
|
|||||||
const bool hit = t > ray.min && t < ray.max;
|
const bool hit = t > ray.min && t < ray.max;
|
||||||
|
|
||||||
|
|
||||||
if (!ignoreHitRecord && hit){
|
if (!ignoreHitRecord && hit) {
|
||||||
hitRecord.t = t;
|
hitRecord.t = t;
|
||||||
hitRecord.origin = ray.origin + ray.direction * t;
|
hitRecord.origin = ray.origin + ray.direction * t;
|
||||||
hitRecord.normal = (hitRecord.origin - sphere.origin).Normalized();
|
hitRecord.normal = (hitRecord.origin - sphere.origin).Normalized();
|
||||||
@@ -40,25 +41,26 @@ namespace dae
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool HitTest_Sphere(const Sphere& sphere, const Ray& ray)
|
inline bool HitTest_Sphere(const Sphere &sphere, const Ray &ray) {
|
||||||
{
|
|
||||||
HitRecord temp{};
|
HitRecord temp{};
|
||||||
return HitTest_Sphere(sphere, ray, temp, true);
|
return HitTest_Sphere(sphere, ray, temp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
#pragma region Plane HitTest
|
#pragma region Plane HitTest
|
||||||
|
|
||||||
//PLANE HIT-TESTS
|
//PLANE HIT-TESTS
|
||||||
inline bool HitTest_Plane(const Plane& plane, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
inline bool
|
||||||
{
|
HitTest_Plane(const Plane &plane, const Ray &ray, HitRecord &hitRecord, bool ignoreHitRecord = false) {
|
||||||
float dot = Vector3::Dot(plane.normal, ray.direction);
|
float dot = Vector3::Dot(plane.normal, ray.direction);
|
||||||
if(dot < 0) {
|
if (dot < 0) {
|
||||||
// float t = Vector3::Dot(plane.origin - ray.origin, plane.normal) / dot;
|
// float t = Vector3::Dot(plane.origin - ray.origin, plane.normal) / dot;
|
||||||
float t = Vector3::Dot(plane.origin - ray.origin, plane.normal);
|
float t = Vector3::Dot(plane.origin - ray.origin, plane.normal);
|
||||||
t /= dot;
|
t /= dot;
|
||||||
|
|
||||||
const bool hit = t > ray.min && t < ray.max;
|
const bool hit = t > ray.min && t < ray.max;
|
||||||
|
|
||||||
if(hit && !ignoreHitRecord){
|
if (hit && !ignoreHitRecord) {
|
||||||
hitRecord.t = t;
|
hitRecord.t = t;
|
||||||
hitRecord.origin = ray.origin + ray.direction * t;
|
hitRecord.origin = ray.origin + ray.direction * t;
|
||||||
hitRecord.normal = plane.normal;
|
hitRecord.normal = plane.normal;
|
||||||
@@ -72,55 +74,174 @@ namespace dae
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool HitTest_Plane(const Plane& plane, const Ray& ray)
|
inline bool HitTest_Plane(const Plane &plane, const Ray &ray) {
|
||||||
{
|
|
||||||
HitRecord temp{};
|
HitRecord temp{};
|
||||||
return HitTest_Plane(plane, ray, temp, true);
|
return HitTest_Plane(plane, ray, temp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
#pragma region Triangle HitTest
|
#pragma region Triangle HitTest
|
||||||
|
|
||||||
//TRIANGLE HIT-TESTS
|
//TRIANGLE HIT-TESTS
|
||||||
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
inline bool
|
||||||
{
|
HitTest_Triangle(const Triangle &triangle, const Ray &ray, HitRecord &hitRecord, bool ignoreHitRecord = false) {
|
||||||
//todo W5
|
const Vector3 &n = triangle.normal;
|
||||||
throw std::runtime_error("Not Implemented Yet");
|
const float dot = Vector3::Dot(n, ray.direction);
|
||||||
|
|
||||||
|
switch (triangle.cullMode) {
|
||||||
|
case TriangleCullMode::BackFaceCulling: {
|
||||||
|
if (ignoreHitRecord) {
|
||||||
|
if (dot >= FLT_EPSILON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dot <= FLT_EPSILON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TriangleCullMode::FrontFaceCulling: {
|
||||||
|
if (ignoreHitRecord) {
|
||||||
|
if (dot <= FLT_EPSILON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dot >= FLT_EPSILON) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TriangleCullMode::NoCulling: {
|
||||||
|
if (dot == 0.f)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Vector3 L = triangle.v0 - ray.origin;
|
||||||
|
const float t = Vector3::Dot(L, n) / dot;
|
||||||
|
|
||||||
|
if (
|
||||||
|
t < ray.min || t > ray
|
||||||
|
.max)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const Vector3 hitPoint = ray.origin + ray.direction * t;
|
||||||
|
const Vector3 *verts[3] = {&triangle.v0, &triangle.v1, &triangle.v2};
|
||||||
|
|
||||||
|
for (
|
||||||
|
int index{};
|
||||||
|
index < 3; ++index) {
|
||||||
|
const Vector3 e = *verts[(index + 1) % 3] - *verts[index];
|
||||||
|
const Vector3 p = hitPoint - *verts[index];
|
||||||
|
|
||||||
|
const Vector3 c = Vector3::Cross(e, p);
|
||||||
|
if (
|
||||||
|
Vector3::Dot(Vector3::Cross(e, p), n
|
||||||
|
) < 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool HitTest_Triangle(const Triangle& triangle, const Ray& ray)
|
if (!ignoreHitRecord) {
|
||||||
{
|
hitRecord.
|
||||||
|
t = t;
|
||||||
|
hitRecord.
|
||||||
|
origin = hitPoint;
|
||||||
|
hitRecord.
|
||||||
|
normal = triangle.normal;
|
||||||
|
hitRecord.
|
||||||
|
materialIndex = triangle.materialIndex;
|
||||||
|
hitRecord.
|
||||||
|
didHit = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HitTest_Triangle(const Triangle &triangle, const Ray &ray) {
|
||||||
HitRecord temp{};
|
HitRecord temp{};
|
||||||
return HitTest_Triangle(triangle, ray, temp, true);
|
return HitTest_Triangle(triangle, ray, temp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
#pragma region TriangeMesh HitTest
|
#pragma region TriangeMesh HitTest
|
||||||
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray, HitRecord& hitRecord, bool ignoreHitRecord = false)
|
|
||||||
{
|
inline bool SlabTest_TriangleMesh(const TriangleMesh &mesh, const Ray &ray) {
|
||||||
//todo W5
|
float tx1 = (mesh.transformedMinAABB.x - ray.origin.x) / ray.direction.x;
|
||||||
throw std::runtime_error("Not Implemented Yet");
|
float tx2 = (mesh.transformedMaxAABB.x - ray.origin.x) / ray.direction.x;
|
||||||
return false;
|
//
|
||||||
|
float tmin = std::min(tx1, tx2);
|
||||||
|
float tmax = std::max(tx1, tx2);
|
||||||
|
//
|
||||||
|
float ty1 = (mesh.transformedMinAABB.y - ray.origin.y) / ray.direction.y;
|
||||||
|
float ty2 = (mesh.transformedMaxAABB.y - ray.origin.y) / ray.direction.y;
|
||||||
|
//
|
||||||
|
tmin = std::max(tmin, std::min(ty1, ty2));
|
||||||
|
tmax = std::min(tmax, std::max(ty1, ty2));
|
||||||
|
|
||||||
|
float tz1 = (mesh.transformedMinAABB.z - ray.origin.z) / ray.direction.z;
|
||||||
|
float tz2 = (mesh.transformedMaxAABB.z - ray.origin.z) / ray.direction.z;
|
||||||
|
|
||||||
|
tmin = std::max(tmin, std::min(tz1, tz2));
|
||||||
|
tmax = std::min(tmax, std::max(tz1, tz2));
|
||||||
|
//
|
||||||
|
return tmax > 0 && tmax >= tmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool HitTest_TriangleMesh(const TriangleMesh& mesh, const Ray& ray)
|
inline bool HitTest_TriangleMesh(const TriangleMesh &mesh, const Ray &ray, HitRecord &hitRecord,
|
||||||
{
|
bool ignoreHitRecord = false) {
|
||||||
|
if (!SlabTest_TriangleMesh(mesh, ray))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
constexpr int triSides{3};
|
||||||
|
const size_t nTris{mesh.indices.size() / triSides};
|
||||||
|
bool hit{false};
|
||||||
|
|
||||||
|
for (int i{}; i < nTris; ++i) {
|
||||||
|
const Vector3 &v0{mesh.transformedPositions[mesh.indices[i * triSides + 0]]};
|
||||||
|
const Vector3 &v1{mesh.transformedPositions[mesh.indices[i * triSides + 1]]};
|
||||||
|
const Vector3 &v2{mesh.transformedPositions[mesh.indices[i * triSides + 2]]};
|
||||||
|
|
||||||
|
const Vector3 norm{mesh.transformedNormals[i]};
|
||||||
|
|
||||||
|
Triangle tri{
|
||||||
|
v0, v1, v2, norm
|
||||||
|
};
|
||||||
|
|
||||||
|
tri.cullMode = mesh.cullMode;
|
||||||
|
tri.materialIndex = mesh.materialIndex;
|
||||||
|
|
||||||
|
HitRecord curHit;
|
||||||
|
if (HitTest_Triangle(tri, ray, curHit, ignoreHitRecord)) {
|
||||||
|
hit = true;
|
||||||
|
|
||||||
|
if (curHit.t < hitRecord.t) {
|
||||||
|
hitRecord = curHit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool HitTest_TriangleMesh(const TriangleMesh &mesh, const Ray &ray) {
|
||||||
HitRecord temp{};
|
HitRecord temp{};
|
||||||
return HitTest_TriangleMesh(mesh, ray, temp, true);
|
return HitTest_TriangleMesh(mesh, ray, temp, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace LightUtils
|
namespace LightUtils {
|
||||||
{
|
|
||||||
//Direction from target to light
|
//Direction from target to light
|
||||||
inline Vector3 GetDirectionToLight(const Light& light, const Vector3 origin)
|
inline Vector3 GetDirectionToLight(const Light &light, const Vector3 origin) {
|
||||||
{
|
return {light.origin - origin};
|
||||||
return { light.origin - origin };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ColorRGB GetRadiance(const Light& light, const Vector3& target)
|
inline ColorRGB GetRadiance(const Light &light, const Vector3 &target) {
|
||||||
{
|
switch (light.type) {
|
||||||
switch(light.type)
|
|
||||||
{
|
|
||||||
case LightType::Point:
|
case LightType::Point:
|
||||||
return light.color * light.intensity / (light.origin - target).SqrMagnitude();
|
return light.color * light.intensity / (light.origin - target).SqrMagnitude();
|
||||||
case LightType::Directional:
|
case LightType::Directional:
|
||||||
@@ -128,49 +249,43 @@ namespace dae
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float LambertCosineLaw(const Vector3& normal, const Vector3& lightDirection)
|
inline float LambertCosineLaw(const Vector3 &normal, const Vector3 &lightDirection) {
|
||||||
{
|
|
||||||
return Vector3::Dot(normal, lightDirection);
|
return Vector3::Dot(normal, lightDirection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Utils
|
namespace Utils {
|
||||||
{
|
|
||||||
//Just parses vertices and indices
|
//Just parses vertices and indices
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4505) //Warning unreferenced local function
|
#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)
|
|
||||||
{
|
static bool
|
||||||
|
ParseOBJ(const std::string &filename, std::vector<Vector3> &positions, std::vector<Vector3> &normals,
|
||||||
|
std::vector<int> &indices) {
|
||||||
std::ifstream file(filename);
|
std::ifstream file(filename);
|
||||||
if (!file)
|
if (!file)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string sCommand;
|
std::string sCommand;
|
||||||
// start a while iteration ending when the end of file is reached (ios::eof)
|
// start a while iteration ending when the end of file is reached (ios::eof)
|
||||||
while (!file.eof())
|
while (!file.eof()) {
|
||||||
{
|
|
||||||
//read the first word of the string, use the >> operator (istream::operator>>)
|
//read the first word of the string, use the >> operator (istream::operator>>)
|
||||||
file >> sCommand;
|
file >> sCommand;
|
||||||
//use conditional statements to process the different commands
|
//use conditional statements to process the different commands
|
||||||
if (sCommand == "#")
|
if (sCommand == "#") {
|
||||||
{
|
|
||||||
// Ignore Comment
|
// Ignore Comment
|
||||||
}
|
} else if (sCommand == "v") {
|
||||||
else if (sCommand == "v")
|
|
||||||
{
|
|
||||||
//Vertex
|
//Vertex
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
file >> x >> y >> z;
|
file >> x >> y >> z;
|
||||||
positions.push_back({ x, y, z });
|
positions.push_back({x, y, z});
|
||||||
}
|
} else if (sCommand == "f") {
|
||||||
else if (sCommand == "f")
|
|
||||||
{
|
|
||||||
float i0, i1, i2;
|
float i0, i1, i2;
|
||||||
file >> i0 >> i1 >> i2;
|
file >> i0 >> i1 >> i2;
|
||||||
|
|
||||||
indices.push_back((int)i0 - 1);
|
indices.push_back((int) i0 - 1);
|
||||||
indices.push_back((int)i1 - 1);
|
indices.push_back((int) i1 - 1);
|
||||||
indices.push_back((int)i2 - 1);
|
indices.push_back((int) i2 - 1);
|
||||||
}
|
}
|
||||||
//read till end of line and ignore all remaining chars
|
//read till end of line and ignore all remaining chars
|
||||||
file.ignore(1000, '\n');
|
file.ignore(1000, '\n');
|
||||||
@@ -180,8 +295,7 @@ namespace dae
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Precompute normals
|
//Precompute normals
|
||||||
for (uint64_t index = 0; index < indices.size(); index += 3)
|
for (uint64_t index = 0; index < indices.size(); index += 3) {
|
||||||
{
|
|
||||||
uint32_t i0 = indices[index];
|
uint32_t i0 = indices[index];
|
||||||
uint32_t i1 = indices[index + 1];
|
uint32_t i1 = indices[index + 1];
|
||||||
uint32_t i2 = indices[index + 2];
|
uint32_t i2 = indices[index + 2];
|
||||||
@@ -190,14 +304,12 @@ namespace dae
|
|||||||
Vector3 edgeV0V2 = positions[i2] - positions[i0];
|
Vector3 edgeV0V2 = positions[i2] - positions[i0];
|
||||||
Vector3 normal = Vector3::Cross(edgeV0V1, edgeV0V2);
|
Vector3 normal = Vector3::Cross(edgeV0V1, edgeV0V2);
|
||||||
|
|
||||||
if (std::isnan(normal.x))
|
if (std::isnan(normal.x)) {
|
||||||
{
|
|
||||||
int k = 0;
|
int k = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
normal.Normalize();
|
normal.Normalize();
|
||||||
if (std::isnan(normal.x))
|
if (std::isnan(normal.x)) {
|
||||||
{
|
|
||||||
int k = 0;
|
int k = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,6 +318,7 @@ namespace dae
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,5 +162,14 @@ namespace dae {
|
|||||||
{
|
{
|
||||||
return AreEqual(x, v.x) && AreEqual(y, v.y) && AreEqual(z, v.z);
|
return AreEqual(x, v.x) && AreEqual(y, v.y) && AreEqual(z, v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3 Vector3::Max(const Vector3 &v1, const Vector3 &v2) {
|
||||||
|
return { std::max(v1.x, v2.x), std::max(v1.y, v2.y), std::max(v1.z, v2.z) };
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 Vector3::Min(const Vector3 &v1, const Vector3 &v2) {
|
||||||
|
return { std::min(v1.x, v2.x), std::min(v1.y, v2.y), std::min(v1.z, v2.z) };
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,9 @@ namespace dae
|
|||||||
static Vector3 Reflect(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);
|
static Vector3 Lico(float f1, const Vector3& v1, float f2, const Vector3& v2, float f3, const Vector3& v3);
|
||||||
|
|
||||||
|
static Vector3 Max(const Vector3& v1, const Vector3& v2);
|
||||||
|
static Vector3 Min(const Vector3& v1, const Vector3& v2);
|
||||||
|
|
||||||
Vector4 ToPoint4() const;
|
Vector4 ToPoint4() const;
|
||||||
Vector4 ToVector4() const;
|
Vector4 ToVector4() const;
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ int main(int argc, char* args[])
|
|||||||
const auto pTimer = new Timer();
|
const auto pTimer = new Timer();
|
||||||
const auto pRenderer = new Renderer(pWindow);
|
const auto pRenderer = new Renderer(pWindow);
|
||||||
|
|
||||||
const auto pScene = new Scene_W3();
|
const auto pScene = new Scene_W4_TestScene();
|
||||||
pScene->Initialize();
|
pScene->Initialize();
|
||||||
|
|
||||||
//Start loop
|
//Start loop
|
||||||
|
|||||||
Reference in New Issue
Block a user