Add Uvs
This commit is contained in:
@@ -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 ¤tMesh: 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 ¤tVecPos{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});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user