This commit is contained in:
2024-11-11 01:41:07 +01:00
parent 2f55e5b8d6
commit 8f8605b76f
8 changed files with 317 additions and 112 deletions

View File

@@ -1,9 +1,11 @@
//External includes
#include <iostream>
#include "SDL_surface.h"
//Project includes
#include "Renderer.h"
#include "Maths.h"
#include "HitTest.h"
using namespace dae;
@@ -24,6 +26,8 @@ Renderer::Renderer(SDL_Window *pWindow) : m_pWindow(pWindow) {
//Initialize Camera
m_Camera.Initialize(60.f, {.0f, .0f, -10.f});
m_aspectRatio = static_cast<float>(m_Width) / static_cast<float>(m_Height);
m_pTexture = Texture::LoadFromFile("./Resources/uv_grid_2.png");
}
Renderer::~Renderer() {
@@ -50,91 +54,154 @@ void Renderer::Render() {
constexpr int numVerticies = 3;
std::vector<Vertex> verticiesScreenSpace{};
VertexTransformationFunction(m_verticiesWorld, verticiesScreenSpace);
const int numTriangles{static_cast<int>(m_verticiesWorld.size()) / numVerticies};
// VertexTransformationFunction(m_verticiesWorld, verticiesScreenSpace);
for (int triangleIndex{}; triangleIndex < numTriangles; ++triangleIndex) {
for (const Mesh &currentMesh: m_meshesWorldStrip) {
VertexTransformationFunction(currentMesh.vertices, verticiesScreenSpace);
const Vector3 &vertexPos0{verticiesScreenSpace[triangleIndex * numVerticies].position};
const Vector3 &vertexPos1{verticiesScreenSpace[triangleIndex * numVerticies + 1].position};
const Vector3 &vertexPos2{verticiesScreenSpace[triangleIndex * numVerticies + 2].position};
int numTriangles{};
const float minX{std::min(vertexPos0.x, std::min(vertexPos1.x, vertexPos2.x))};
const float minY{std::min(vertexPos0.y, std::min(vertexPos1.y, vertexPos2.y))};
switch (currentMesh.primitiveTopology) {
case PrimitiveTopology::TriangleList:
numTriangles = static_cast<int>(currentMesh.indices.size()) / numVerticies;
break;
case PrimitiveTopology::TriangleStrip:
numTriangles = static_cast<int>(currentMesh.indices.size()) - 2;
break;
}
const float maxX{std::max(vertexPos0.x, std::max(vertexPos1.x, vertexPos2.x))};
const float maxY{std::max(vertexPos0.y, std::max(vertexPos1.y, vertexPos2.y))};
const int indexOffset{triangleIndex * numVerticies};
for (int triangleIndex{}; triangleIndex < numTriangles; ++triangleIndex) {
const Vector3 side1{
verticiesScreenSpace[indexOffset + 1].position - verticiesScreenSpace[indexOffset].position};
const Vector3 side2{
verticiesScreenSpace[indexOffset + 2].position - verticiesScreenSpace[indexOffset].position};
Vertex vertex0, vertex1, vertex2;
const float area{0.5f * Vector3::Cross(side1, side2).z};
switch (currentMesh.primitiveTopology) {
case PrimitiveTopology::TriangleList:
vertex0 = verticiesScreenSpace[currentMesh.indices[triangleIndex * numVerticies + 0]];
vertex1 = verticiesScreenSpace[currentMesh.indices[triangleIndex * numVerticies + 1]];
vertex2 = verticiesScreenSpace[currentMesh.indices[triangleIndex * numVerticies + 2]];
break;
case PrimitiveTopology::TriangleStrip:
vertex0 = verticiesScreenSpace[currentMesh.indices[triangleIndex + 0]];
vertex1 = verticiesScreenSpace[currentMesh.indices[triangleIndex + 1]];
vertex2 = verticiesScreenSpace[currentMesh.indices[triangleIndex + 2]];
const int startX = std::max(0, static_cast<int>(minX));
const int endX = std::min(m_Width - 1, static_cast<int>(maxX));
const int startY = std::max(0, static_cast<int>(minY));
const int endY = std::min(m_Height - 1, static_cast<int>(maxY));
for (int px{startX}; px < endX; ++px) {
for (int py{startY}; py < endY; ++py) {
Vector3 P{px + 0.5f, py + 0.5f, 1};
bool inTriangle{true};
float currDepth{0.0f};
ColorRGB pointColor{};
for (int vertexIndex{0}; vertexIndex < numVerticies; ++vertexIndex) {
const Vertex &nextVert{verticiesScreenSpace[(vertexIndex + 1) % numVerticies + indexOffset]};
const Vector3 &currentVecPos{verticiesScreenSpace[vertexIndex + indexOffset].position};
const Vector3 eVec{nextVert.position - currentVecPos};
const Vector3 pVec{P - currentVecPos};
const float crossResult{Vector3::Cross(eVec, pVec).z};
if (crossResult < 0) {
inTriangle = false;
break;
if (triangleIndex % 2 == 1) {
std::swap(vertex1, vertex2);
}
currDepth +=
verticiesScreenSpace[((vertexIndex + 2) % numVerticies + indexOffset)].position.z *
((crossResult * 0.5f) / area);
pointColor += verticiesScreenSpace[((vertexIndex + 2) % numVerticies + indexOffset)].color *
((crossResult * 0.5f) / area);
}
if (vertex0.position == vertex1.position ||
vertex0.position == vertex2.position ||
vertex1.position == vertex2.position) {
continue;
}
break;
}
if (!inTriangle) {
continue;
}
const float minX{std::min(vertex0.position.x, std::min(vertex1.position.x, vertex2.position.x))};
const float minY{std::min(vertex0.position.y, std::min(vertex1.position.y, vertex2.position.y))};
const int depthBufferIndex{px + (py * m_Width)};
const float maxX{std::max(vertex0.position.x, std::max(vertex1.position.x, vertex2.position.x))};
const float maxY{std::max(vertex0.position.y, std::max(vertex1.position.y, vertex2.position.y))};
if (m_pDepthBufferPixels[depthBufferIndex] >= currDepth) {
m_pDepthBufferPixels[depthBufferIndex] = currDepth;
finalColor = pointColor;
finalColor.MaxToOne();
const Vector3 side1{vertex1.position - vertex0.position};
const Vector3 side2{vertex2.position - vertex0.position};
const float totalArea{Vector3::Cross(side1, side2).z};
const int startX = std::max(0, static_cast<int>(minX)) - 1;
const int endX = std::min(m_Width - 1, static_cast<int>(maxX)) + 1;
const int startY = std::max(0, static_cast<int>(minY)) - 1;
const int endY = std::min(m_Height - 1, static_cast<int>(maxY)) + 1;
for (int px{startX}; px < endX; ++px) {
for (int py{startY}; py < endY; ++py) {
if (px < 0 || px >= m_Width || py < 0 || py >= m_Height) {
//TEMP fix for out of bounds
//This is to remove triangles having an incorrect edge on their bounding box
continue;
}
Vector3 P{static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f};
const Vector3 cross0{Vector3::Cross(vertex2.position - vertex1.position, P - vertex1.position)};
if (cross0.z < 0) {
continue;
}
const Vector3 cross1{Vector3::Cross(vertex0.position - vertex2.position, P - vertex2.position)};
if (cross1.z < 0) {
continue;
}
const Vector3 cross2{Vector3::Cross(vertex1.position - vertex0.position, P - vertex0.position)};
if (cross2.z < 0) {
continue;
}
const int depthBufferIndex{px + (py * m_Width)};
float totalWeight{cross0.z + cross1.z + cross2.z};
Vector3 weights{
cross0.z / totalWeight,
cross1.z / totalWeight,
cross2.z / totalWeight,
};
const float currentDepth =
1 / (weights.x / vertex0.position.z +
weights.y / vertex1.position.z +
weights.z / vertex2.position.z);
const Vector2 UvCoords =
vertex0.uv * currentDepth * weights.x / vertex0.position.z +
vertex1.uv * currentDepth * weights.y / vertex1.position.z +
vertex2.uv * currentDepth * weights.z / vertex2.position.z;
if (m_pDepthBufferPixels[depthBufferIndex] >= currentDepth) {
m_pDepthBufferPixels[depthBufferIndex] = currentDepth;
//Update Color in Buffer
finalColor = m_pTexture->Sample(UvCoords);
finalColor.MaxToOne();
m_pBackBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
static_cast<uint8_t>(finalColor.r * 255),
static_cast<uint8_t>(finalColor.g * 255),
static_cast<uint8_t>(finalColor.b * 255));
}
m_pBackBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
static_cast<uint8_t>(finalColor.r * 255),
static_cast<uint8_t>(finalColor.g * 255),
static_cast<uint8_t>(finalColor.b * 255));
}
}
}
}
//RENDER LOGIC
int x, y{0};
//For loop over all the pixels
for (int px{}; px < 100; ++px) {
for (int py{}; py < 100; ++py) {
//Get the pixel position
x = px;
y = py;
ColorRGB test = m_pTexture->Sample(Vector2{static_cast<float>(px) / 100, static_cast<float>(py) / 100});
m_pBackBufferPixels[x + (y * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
static_cast<uint8_t>(test.r * 255),
static_cast<uint8_t>(test.g * 255),
static_cast<uint8_t>(test.b * 255));
}
}
//RENDER LOGIC
SDL_UnlockSurface(m_pBackBuffer);
SDL_BlitSurface(m_pBackBuffer, nullptr, m_pFrontBuffer, nullptr);
SDL_BlitSurface(m_pBackBuffer,
nullptr, m_pFrontBuffer, nullptr);
SDL_UpdateWindowSurface(m_pWindow);
}
@@ -148,7 +215,7 @@ void Renderer::VertexTransformationFunction(const std::vector<Vertex> &vertices_
vertPos.x = (vertPos.x + 1) / 2 * static_cast<float>(m_Width);
vertPos.y = (1 - vertPos.y) / 2 * static_cast<float>(m_Height);
vertices_out.push_back(Vertex{vertPos, vert.color});
vertices_out.push_back(Vertex{vertPos, vert.color, vert.uv});
}
}