diff --git a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj index 33b6481..5c6484c 100644 --- a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj +++ b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj @@ -77,13 +77,13 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Asset;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Core;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Math;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Rasterizer;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\RenderData;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Scene;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Shading;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\include;%(AdditionalIncludeDirectories) + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console true SDL2.lib;SDL2main.lib;%(AdditionalDependencies) - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x86;%(AdditionalLibraryDirectories) + $(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories) @@ -95,13 +95,13 @@ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Asset;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Core;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Math;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Rasterizer;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\RenderData;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Scene;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Shading;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\include;%(AdditionalIncludeDirectories) + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console true SDL2.lib;SDL2main.lib;%(AdditionalDependencies) - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x86;%(AdditionalLibraryDirectories) + $(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories) @@ -111,12 +111,12 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Asset;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Core;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Math;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Rasterizer;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\RenderData;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Scene;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Shading;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\include;%(AdditionalIncludeDirectories) + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console true - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x64;%(AdditionalLibraryDirectories) + $(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories) SDL2.lib;SDL2main.lib;%(AdditionalDependencies) @@ -129,13 +129,13 @@ NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Asset;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Core;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Math;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Rasterizer;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\RenderData;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Scene;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\Shading;D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\include;%(AdditionalIncludeDirectories) + $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories) Console true SDL2.lib;SDL2main.lib;%(AdditionalDependencies) - D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x64;%(AdditionalLibraryDirectories) + $(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories) @@ -149,6 +149,7 @@ + diff --git a/CPU-Software-Renderer/Core/FrameBuffer.cpp b/CPU-Software-Renderer/Core/FrameBuffer.cpp index 30072cf..d565b23 100644 --- a/CPU-Software-Renderer/Core/FrameBuffer.cpp +++ b/CPU-Software-Renderer/Core/FrameBuffer.cpp @@ -16,7 +16,6 @@ namespace Core { if (x < 0 || x >= width || y < 0 || y >= height) { - std::cerr << "Error: Attempting to set pixel at (" << x << ", " << y << ") which is out of bounds." << std::endl; return; } size_t index = static_cast(y) * width + x; diff --git a/CPU-Software-Renderer/Core/FrameBuffer.h b/CPU-Software-Renderer/Core/FrameBuffer.h index 41e42b1..5ef6ebb 100644 --- a/CPU-Software-Renderer/Core/FrameBuffer.h +++ b/CPU-Software-Renderer/Core/FrameBuffer.h @@ -14,6 +14,10 @@ namespace Core std::vector buffer; public: + int32_t get_width() const { return width; } + + int32_t get_height() const { return height; } + size_t total_pixels() const { return buffer.size(); } void* get_buffer() const { return (void*)buffer.data(); } diff --git a/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp b/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp index 07f2f07..294704f 100644 --- a/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp +++ b/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp @@ -3,21 +3,27 @@ #include #include "BoundingBox.h" #include -using namespace RenderData; +#include +#include namespace Rasterizer { - void TriangleRasterizer::DrawTriangle2D(const Triangle2D triangle, const Color color) + void TriangleRasterizer::DrawTriangle2D(const RenderData::Triangle2D triangle, const RenderData::Color color) { auto boundingBox = triangle.get_boundingBox(); - for (int x = boundingBox.min.x; x <= boundingBox.max.x; x++) + int32_t minX = std::max(0, boundingBox.min.x); + int32_t maxX = std::min(frameBuffer.get_width() - 1, boundingBox.max.x); + int32_t minY = std::max(0, boundingBox.min.y); + int32_t maxY = std::min(frameBuffer.get_height() - 1, boundingBox.max.y); + + for (int x = minX; x <= maxX; x++) { - for (int y = boundingBox.min.y; y <= boundingBox.max.y; y++) + for (int y = minY; y <= maxY; y++) { - if (triangle.ContainsPixel(Vector2(x, y))) + if (triangle.ContainsPixel(Math::Vector2(x, y))) { - frameBuffer.set_pixel(Vector2Int(x, y), color.to_rgba()); + frameBuffer.set_pixel(Math::Vector2Int(x, y), color.to_rgba()); } } } diff --git a/CPU-Software-Renderer/RenderData/BoundingBox.h b/CPU-Software-Renderer/RenderData/BoundingBox.h index deb4bb5..86bc0c2 100644 --- a/CPU-Software-Renderer/RenderData/BoundingBox.h +++ b/CPU-Software-Renderer/RenderData/BoundingBox.h @@ -5,10 +5,10 @@ namespace RenderData { struct BoundingBox2D { - Math::Vector2 min; - Math::Vector2 max; + Math::Vector2Int min; + Math::Vector2Int max; BoundingBox2D() : min(), max() {} - BoundingBox2D(const Math::Vector2 min, const Math::Vector2 max) : min(min), max(max) {} + BoundingBox2D(const Math::Vector2Int min, const Math::Vector2Int max) : min(min), max(max) {} }; } \ No newline at end of file diff --git a/CPU-Software-Renderer/RenderData/Triangle.h b/CPU-Software-Renderer/RenderData/Triangle.h index a470230..dcf359f 100644 --- a/CPU-Software-Renderer/RenderData/Triangle.h +++ b/CPU-Software-Renderer/RenderData/Triangle.h @@ -2,29 +2,38 @@ #include "Vector2.h" #include "BoundingBox.h" #include +#include +#include namespace RenderData { - using namespace Math; struct Triangle2D { - Vector2 v0; - Vector2 v1; - Vector2 v2; + Math::Vector2 v0; + Math::Vector2 v1; + Math::Vector2 v2; Triangle2D() : v0(), v1(), v2() {} - Triangle2D(const Vector2 a, const Vector2 b, const Vector2 c) : v0(a), v1(b), v2(c) {} + Triangle2D(const Math::Vector2 a, const Math::Vector2 b, const Math::Vector2 c) : v0(a), v1(b), v2(c) {} BoundingBox2D get_boundingBox() const { - Vector2 min, max; - min = Vector2(std::min({ v0.x, v1.x, v2.x }), min.y = std::min({ v0.y, v1.y, v2.y })); - max = Vector2(std::max({ v0.x, v1.x, v2.x }), max.y = std::max({ v0.y, v1.y, v2.y })); + using namespace Math; + + int32_t minX = static_cast(std::floor(std::min({ v0.x, v1.x, v2.x }))); + int32_t maxX = static_cast(std::ceil(std::max({ v0.x, v1.x, v2.x }))); + int32_t minY = static_cast(std::floor(std::min({ v0.y, v1.y, v2.y }))); + int32_t maxY = static_cast(std::ceil(std::max({ v0.y, v1.y, v2.y }))); + + Vector2Int min(minX, minY); + Vector2Int max(maxX, maxY); return BoundingBox2D(min, max); } - bool ContainsPixel(const Vector2 point) const + bool ContainsPixel(const Math::Vector2 point) const { + using namespace Math; + auto cross = [](const Vector2& p1, const Vector2& p2, const Vector2& p3) -> float { const float x1 = p2.x - p1.x; diff --git a/CPU-Software-Renderer/main.cpp b/CPU-Software-Renderer/main.cpp index a20b2d2..92635fb 100644 --- a/CPU-Software-Renderer/main.cpp +++ b/CPU-Software-Renderer/main.cpp @@ -8,15 +8,24 @@ #include "Color.h" #include "FrameBuffer.h" #include "Rasterizer.h" +#include "SDL_events.h" +#include "SDL_keycode.h" const uint32_t SDL_INIT_FLAGS = SDL_INIT_VIDEO; const int32_t width = 800; const int32_t height = 600; SDL_Window* window = nullptr; SDL_Renderer* renderer = nullptr; +SDL_Texture* texture = nullptr; static void ClearSDLResources() { + if (texture != nullptr) + { + SDL_DestroyTexture(texture); + texture = nullptr; + } + if (renderer != nullptr) { SDL_DestroyRenderer(renderer); @@ -82,6 +91,21 @@ static bool EnsureRenderer() return true; } +static bool EnsureTexture() +{ + if (texture != nullptr) return true; + + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height); + + if (texture == nullptr) + { + std::cerr << "Texture could not be created! SDL_Error: " << SDL_GetError() << std::endl; + ClearSDLResources(); + return false; + } + return true; +} + int main(int argc, char* argv[]) { @@ -91,7 +115,7 @@ int main(int argc, char* argv[]) if (!EnsureRenderer()) return -1; - SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height); + if (!EnsureTexture()) return -1; Core::FrameBuffer frameBuffer(width, height); Rasterizer::Rasterizer rasterizer(frameBuffer); @@ -106,10 +130,24 @@ int main(int argc, char* argv[]) rasterizer.DrawLine(v1, v2, color1); rasterizer.DrawLine(v2, v0, color2); - while (true) + bool isRuning = true; + while (isRuning) { - SDL_UpdateTexture(texture, nullptr, frameBuffer.get_buffer(), width * sizeof(uint32_t)); + SDL_Event event; + while (SDL_PollEvent(&event)) + { + if (event.type == SDL_QUIT) + { + isRuning = false; + } + if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_SPACE) + { + isRuning = false; + } + } + + SDL_UpdateTexture(texture, nullptr, frameBuffer.get_buffer(), width * sizeof(uint32_t)); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderPresent(renderer);