Batman (week 6)
This commit is contained in:
157
project/src/Renderer.cpp
Normal file
157
project/src/Renderer.cpp
Normal file
@@ -0,0 +1,157 @@
|
||||
//External includes
|
||||
#include "SDL_surface.h"
|
||||
|
||||
//Project includes
|
||||
#include "Renderer.h"
|
||||
#include "Maths.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
Renderer::Renderer(SDL_Window *pWindow) : m_pWindow(pWindow) {
|
||||
//Initialize
|
||||
SDL_GetWindowSize(pWindow, &m_Width, &m_Height);
|
||||
|
||||
//Create Buffers
|
||||
m_pFrontBuffer = SDL_GetWindowSurface(pWindow);
|
||||
m_pBackBuffer = SDL_CreateRGBSurface(0, m_Width, m_Height, 32, 0, 0, 0, 0);
|
||||
m_pBackBufferPixels = (uint32_t *) m_pBackBuffer->pixels;
|
||||
|
||||
m_pDepthBufferPixels = new float[m_Width * m_Height];
|
||||
|
||||
//Initialize Camera
|
||||
m_Camera.Initialize(60.f, {.0f, .0f, -10.f});
|
||||
|
||||
//Initialize Camera
|
||||
m_Camera.Initialize(60.f, {.0f, .0f, -10.f});
|
||||
m_aspectRatio = static_cast<float>(m_Width) / static_cast<float>(m_Height);
|
||||
}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
delete[] m_pDepthBufferPixels;
|
||||
}
|
||||
|
||||
void Renderer::Update(Timer *pTimer) {
|
||||
m_Camera.Update(pTimer);
|
||||
}
|
||||
|
||||
void Renderer::Render() {
|
||||
//@START
|
||||
//Lock BackBuffer
|
||||
//Random color
|
||||
SDL_FillRect(m_pBackBuffer, nullptr, m_ClearColor);
|
||||
SDL_LockSurface(m_pBackBuffer);
|
||||
std::fill_n(m_pDepthBufferPixels, m_Width * m_Height, std::numeric_limits<float>::max());
|
||||
|
||||
//Clear
|
||||
SDL_FillRect(m_pBackBuffer, nullptr, m_ClearColor);
|
||||
|
||||
|
||||
ColorRGB finalColor{};
|
||||
constexpr int numVerticies = 3;
|
||||
|
||||
std::vector<Vertex> verticiesScreenSpace{};
|
||||
VertexTransformationFunction(m_verticiesWorld, verticiesScreenSpace);
|
||||
const int numTriangles{static_cast<int>(m_verticiesWorld.size()) / numVerticies};
|
||||
|
||||
for (int triangleIndex{}; triangleIndex < numTriangles; ++triangleIndex) {
|
||||
|
||||
const Vector3 &vertexPos0{verticiesScreenSpace[triangleIndex * numVerticies].position};
|
||||
const Vector3 &vertexPos1{verticiesScreenSpace[triangleIndex * numVerticies + 1].position};
|
||||
const Vector3 &vertexPos2{verticiesScreenSpace[triangleIndex * numVerticies + 2].position};
|
||||
|
||||
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))};
|
||||
|
||||
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};
|
||||
|
||||
const Vector3 side1{
|
||||
verticiesScreenSpace[indexOffset + 1].position - verticiesScreenSpace[indexOffset].position};
|
||||
const Vector3 side2{
|
||||
verticiesScreenSpace[indexOffset + 2].position - verticiesScreenSpace[indexOffset].position};
|
||||
|
||||
const float area{0.5f * Vector3::Cross(side1, side2).z};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
currDepth +=
|
||||
verticiesScreenSpace[((vertexIndex + 2) % numVerticies + indexOffset)].position.z *
|
||||
((crossResult * 0.5f) / area);
|
||||
pointColor += verticiesScreenSpace[((vertexIndex + 2) % numVerticies + indexOffset)].color *
|
||||
((crossResult * 0.5f) / area);
|
||||
}
|
||||
|
||||
if (!inTriangle) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int depthBufferIndex{px + (py * m_Width)};
|
||||
|
||||
if (m_pDepthBufferPixels[depthBufferIndex] >= currDepth) {
|
||||
m_pDepthBufferPixels[depthBufferIndex] = currDepth;
|
||||
|
||||
finalColor = pointColor;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//RENDER LOGIC
|
||||
|
||||
SDL_UnlockSurface(m_pBackBuffer);
|
||||
SDL_BlitSurface(m_pBackBuffer, nullptr, m_pFrontBuffer, nullptr);
|
||||
SDL_UpdateWindowSurface(m_pWindow);
|
||||
}
|
||||
|
||||
void Renderer::VertexTransformationFunction(const std::vector<Vertex> &vertices_in,
|
||||
std::vector<Vertex> &vertices_out) const {
|
||||
for (const Vertex &vert: vertices_in) {
|
||||
Vector3 vertPos{m_Camera.invViewMatrix.TransformPoint(vert.position)};
|
||||
|
||||
vertPos.x = (vertPos.x / vertPos.z) / (m_aspectRatio * m_Camera.fov);
|
||||
vertPos.y = (vertPos.y / vertPos.z) / m_Camera.fov;
|
||||
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
bool Renderer::SaveBufferToImage() const {
|
||||
return SDL_SaveBMP(m_pBackBuffer, "Rasterizer_ColorBuffer.bmp");
|
||||
}
|
||||
Reference in New Issue
Block a user