This commit is contained in:
2024-12-11 17:30:25 +01:00
parent 98f3fc50cd
commit bbf119b3d4
4 changed files with 136 additions and 155 deletions

View File

@@ -152,16 +152,6 @@ namespace dae {
} }
Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf) { Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf) {
// const float yScale = 1.f / tanf(fovy / 2.f);
// const float xScale = yScale / aspect;
//
// return {
// {xScale, 0, 0, 0},
// {0, yScale, 0, 0},
// {0, 0, zf / (zf - zn), 1},
// {0, 0, -zn * zf / (zf - zn), 0}
// };
return Matrix( return Matrix(
{ 1.f / (aspect * fovy), 0, 0, 0 }, { 1.f / (aspect * fovy), 0, 0, 0 },
{ 0, 1.f / fovy, 0, 0 }, { 0, 1.f / fovy, 0, 0 },

View File

@@ -64,7 +64,7 @@ void Renderer::Render() {
ColorRGB finalColor{}; ColorRGB finalColor{};
constexpr int numVerticies = 3; constexpr int numVerticies = 3;
std::vector<Vertex> verticiesScreenSpace{}; verticiesScreenSpace.clear();
for (const Mesh &currentMesh: m_worldMeshes) { for (const Mesh &currentMesh: m_worldMeshes) {
@@ -184,6 +184,24 @@ void Renderer::Render() {
} }
} }
float min{std::numeric_limits<float>::max()};
float max{std::numeric_limits<float>::min()};
for (int i{}; i < m_Width * m_Height; ++i) {
if (m_pDepthBufferPixels[i] == std::numeric_limits<float>::max()) {
continue;
}
min = std::min(min, m_pDepthBufferPixels[i]);
max = std::max(max, m_pDepthBufferPixels[i]);
}
for (int i{}; i < m_Width * m_Height; ++i) {
if (m_pDepthBufferPixels[i] == std::numeric_limits<float>::max()) {
continue;
}
m_pDepthBufferPixels[i] = (m_pDepthBufferPixels[i] - min) / (max - min);
}
//RENDER LOGIC //RENDER LOGIC
@@ -240,7 +258,7 @@ bool Renderer::SaveBufferToImage() const {
return SDL_SaveBMP(m_pBackBuffer, "Rasterizer_ColorBuffer.bmp"); return SDL_SaveBMP(m_pBackBuffer, "Rasterizer_ColorBuffer.bmp");
} }
ColorRGB Renderer::shadePixel(const Sample &sample) { ColorRGB Renderer::shadePixel(const Sample& sample) {
Vector3 lightDirection = { .577f, -.577f, .577f}; Vector3 lightDirection = { .577f, -.577f, .577f};
Vector3 normal = sample.normal.Normalized(); Vector3 normal = sample.normal.Normalized();
constexpr float lightIntensity{ 7.f }; constexpr float lightIntensity{ 7.f };

View File

@@ -121,6 +121,7 @@ namespace dae {
std::vector<Mesh> m_worldMeshes{}; std::vector<Mesh> m_worldMeshes{};
std::vector<Vertex> verticiesScreenSpace{};
float* m_pDepthBufferPixels{}; float* m_pDepthBufferPixels{};

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include <cassert> #include <cassert>
#include <fstream> #include <fstream>
#include "Maths.h" #include "Maths.h"
@@ -6,171 +7,142 @@
//#define DISABLE_OBJ //#define DISABLE_OBJ
namespace dae namespace dae {
{ 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<Vertex>& vertices, std::vector<uint32_t>& indices, bool flipAxisAndWinding = true)
{
#ifdef DISABLE_OBJ
//TODO: Enable the code below after uncommenting all the vertex attributes of DataTypes::Vertex static bool ParseOBJ(const std::string &filename, std::vector<Vertex> &vertices, std::vector<uint32_t> &indices,
// >> Comment/Remove '#define DISABLE_OBJ' bool flipAxisAndWinding = true) {
assert(false && "OBJ PARSER not enabled! Check the comments in Utils::ParseOBJ"); std::ifstream file(filename);
if (!file)
return false;
#else std::vector<Vector3> positions{};
std::vector<Vector3> normals{};
std::vector<Vector2> UVs{};
std::ifstream file(filename); vertices.clear();
if (!file) indices.clear();
return false;
std::vector<Vector3> positions{}; std::string sCommand;
std::vector<Vector3> normals{}; // start a while iteration ending when the end of file is reached (ios::eof)
std::vector<Vector2> UVs{}; 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;
vertices.clear(); positions.emplace_back(x, y, z);
indices.clear(); } else if (sCommand == "vt") {
// Vertex TexCoord
float u, v;
file >> u >> v;
UVs.emplace_back(u, 1 - v);
} else if (sCommand == "vn") {
// Vertex Normal
float x, y, z;
file >> x >> y >> z;
std::string sCommand; normals.emplace_back(x, y, z);
// start a while iteration ending when the end of file is reached (ios::eof) } else if (sCommand == "f") {
while (!file.eof()) //if a face is read:
{ //construct the 3 vertices, add them to the vertex array
//read the first word of the string, use the >> operator (istream::operator>>) //add three indices to the index array
file >> sCommand; //add the material index as attibute to the attribute array
//use conditional statements to process the different commands //
if (sCommand == "#") // Faces or triangles
{ Vertex vertex{};
// Ignore Comment size_t iPosition, iTexCoord, iNormal;
}
else if (sCommand == "v")
{
//Vertex
float x, y, z;
file >> x >> y >> z;
positions.emplace_back(x, y, z); uint32_t tempIndices[3];
} for (size_t iFace = 0; iFace < 3; iFace++) {
else if (sCommand == "vt") // OBJ format uses 1-based arrays
{ file >> iPosition;
// Vertex TexCoord vertex.position = positions[iPosition - 1].ToVector4();
float u, v;
file >> u >> v;
UVs.emplace_back(u, 1 - v);
}
else if (sCommand == "vn")
{
// Vertex Normal
float x, y, z;
file >> x >> y >> z;
normals.emplace_back(x, y, z); if ('/' == file.peek())//is next in buffer == '/' ?
} {
else if (sCommand == "f") file.ignore();//read and ignore one element ('/')
{
//if a face is read:
//construct the 3 vertices, add them to the vertex array
//add three indices to the index array
//add the material index as attibute to the attribute array
//
// Faces or triangles
Vertex vertex{};
size_t iPosition, iTexCoord, iNormal;
uint32_t tempIndices[3]; if ('/' != file.peek()) {
for (size_t iFace = 0; iFace < 3; iFace++) // Optional texture coordinate
{ file >> iTexCoord;
// OBJ format uses 1-based arrays vertex.uv = UVs[iTexCoord - 1];
file >> iPosition; }
vertex.position = positions[iPosition - 1].ToVector4();
if ('/' == file.peek())//is next in buffer == '/' ? if ('/' == file.peek()) {
{ file.ignore();
file.ignore();//read and ignore one element ('/')
if ('/' != file.peek()) // Optional vertex normal
{ file >> iNormal;
// Optional texture coordinate vertex.normal = normals[iNormal - 1];
file >> iTexCoord; }
vertex.uv = UVs[iTexCoord - 1]; }
}
if ('/' == file.peek()) vertices.push_back(vertex);
{ tempIndices[iFace] = uint32_t(vertices.size()) - 1;
file.ignore(); //indices.push_back(uint32_t(vertices.size()) - 1);
}
// Optional vertex normal indices.push_back(tempIndices[0]);
file >> iNormal; if (flipAxisAndWinding) {
vertex.normal = normals[iNormal - 1]; indices.push_back(tempIndices[2]);
} indices.push_back(tempIndices[1]);
} } else {
indices.push_back(tempIndices[1]);
indices.push_back(tempIndices[2]);
}
}
//read till end of line and ignore all remaining chars
file.ignore(1000, '\n');
}
vertices.push_back(vertex); //Cheap Tangent Calculations
tempIndices[iFace] = uint32_t(vertices.size()) - 1; for (uint32_t i = 0; i < indices.size(); i += 3) {
//indices.push_back(uint32_t(vertices.size()) - 1); uint32_t index0 = indices[i];
} uint32_t index1 = indices[size_t(i) + 1];
uint32_t index2 = indices[size_t(i) + 2];
indices.push_back(tempIndices[0]); const Vector3 &p0 = vertices[index0].position;
if (flipAxisAndWinding) const Vector3 &p1 = vertices[index1].position;
{ const Vector3 &p2 = vertices[index2].position;
indices.push_back(tempIndices[2]); const Vector2 &uv0 = vertices[index0].uv;
indices.push_back(tempIndices[1]); const Vector2 &uv1 = vertices[index1].uv;
} const Vector2 &uv2 = vertices[index2].uv;
else
{
indices.push_back(tempIndices[1]);
indices.push_back(tempIndices[2]);
}
}
//read till end of line and ignore all remaining chars
file.ignore(1000, '\n');
}
//Cheap Tangent Calculations const Vector3 edge0 = p1 - p0;
for (uint32_t i = 0; i < indices.size(); i += 3) const Vector3 edge1 = p2 - p0;
{ const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x);
uint32_t index0 = indices[i]; const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y);
uint32_t index1 = indices[size_t(i) + 1]; float r = 1.f / Vector2::Cross(diffX, diffY);
uint32_t index2 = indices[size_t(i) + 2];
const Vector3& p0 = vertices[index0].position; Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r;
const Vector3& p1 = vertices[index1].position; vertices[index0].tangent += tangent;
const Vector3& p2 = vertices[index2].position; vertices[index1].tangent += tangent;
const Vector2& uv0 = vertices[index0].uv; vertices[index2].tangent += tangent;
const Vector2& uv1 = vertices[index1].uv; }
const Vector2& uv2 = vertices[index2].uv;
const Vector3 edge0 = p1 - p0; //Fix the tangents per vertex now because we accumulated
const Vector3 edge1 = p2 - p0; for (auto &v: vertices) {
const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x); v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized();
const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y);
float r = 1.f / Vector2::Cross(diffX, diffY);
Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r; if (flipAxisAndWinding) {
vertices[index0].tangent += tangent; v.position.z *= -1.f;
vertices[index1].tangent += tangent; v.normal.z *= -1.f;
vertices[index2].tangent += tangent; v.tangent.z *= -1.f;
} }
//Fix the tangents per vertex now because we accumulated }
for (auto& v : vertices)
{
v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized();
if(flipAxisAndWinding) return true;
{ }
v.position.z *= -1.f;
v.normal.z *= -1.f;
v.tangent.z *= -1.f;
}
}
return true;
#endif
}
#pragma warning(pop) #pragma warning(pop)
} }
} }