From 7bd5d7c13d530ea1e99893eefacc526624e61ba0 Mon Sep 17 00:00:00 2001
From: SepComet <202308010230@stu.csust.edu.cn>
Date: Sun, 15 Mar 2026 16:20:36 +0800
Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E9=A1=B9=E7=9B=AE=EF=BC=8C?=
=?UTF-8?q?=E4=B8=BA=E5=90=8E=E7=BB=AD=E5=BC=80=E5=8F=91=E9=93=BA=E8=B7=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
CPU-Software-Renderer.slnx | 4 +-
CPU-Software-Renderer/Asset/ObjLoader.cpp | 0
CPU-Software-Renderer/Asset/ObjLoader.h | 7 +
.../CPU-Software-Renderer.vcxproj | 46 +++-
.../CPU-Software-Renderer.vcxproj.filters | 122 ++++++++-
CPU-Software-Renderer/Color.cpp | 22 --
CPU-Software-Renderer/Color.h | 34 ---
CPU-Software-Renderer/Core/DepthBuffer.cpp | 0
CPU-Software-Renderer/Core/DepthBuffer.h | 7 +
CPU-Software-Renderer/Core/FrameBuffer.cpp | 25 ++
CPU-Software-Renderer/Core/FrameBuffer.h | 42 +++
CPU-Software-Renderer/Core/Renderer.cpp | 0
CPU-Software-Renderer/Core/Renderer.h | 7 +
CPU-Software-Renderer/Math/MathUtil.h | 7 +
CPU-Software-Renderer/Math/Matrix4x4.h | 7 +
CPU-Software-Renderer/Math/Vector2.h | 50 ++++
CPU-Software-Renderer/Math/Vector3.h | 20 ++
CPU-Software-Renderer/Math/Vector4.h | 7 +
CPU-Software-Renderer/Rasterization.cpp | 129 ---------
CPU-Software-Renderer/Rasterization.h | 34 ---
.../Rasterizer/Rasterizer.cpp | 102 ++++++++
CPU-Software-Renderer/Rasterizer/Rasterizer.h | 21 ++
.../Rasterizer/TriangleRasterizer.cpp | 25 ++
.../Rasterizer/TriangleRasterizer.h | 19 ++
.../RenderData/BoundingBox.h | 14 +
CPU-Software-Renderer/RenderData/Color.h | 34 +++
CPU-Software-Renderer/RenderData/Triangle.h | 47 ++++
CPU-Software-Renderer/Scene/Camera.h | 7 +
CPU-Software-Renderer/Scene/Mesh.h | 7 +
CPU-Software-Renderer/Scene/Model.h | 7 +
CPU-Software-Renderer/Scene/Transform.h | 7 +
CPU-Software-Renderer/Scene/Vertex.h | 7 +
.../Shading/BlinnPhongShader.cpp | 0
.../Shading/BlinnPhongShader.h | 7 +
CPU-Software-Renderer/Shading/ShaderTypes.h | 9 +
CPU-Software-Renderer/StructType.h | 142 ----------
CPU-Software-Renderer/main.cpp | 35 +--
README.md | 247 +++++++++---------
38 files changed, 791 insertions(+), 516 deletions(-)
create mode 100644 CPU-Software-Renderer/Asset/ObjLoader.cpp
create mode 100644 CPU-Software-Renderer/Asset/ObjLoader.h
delete mode 100644 CPU-Software-Renderer/Color.cpp
delete mode 100644 CPU-Software-Renderer/Color.h
create mode 100644 CPU-Software-Renderer/Core/DepthBuffer.cpp
create mode 100644 CPU-Software-Renderer/Core/DepthBuffer.h
create mode 100644 CPU-Software-Renderer/Core/FrameBuffer.cpp
create mode 100644 CPU-Software-Renderer/Core/FrameBuffer.h
create mode 100644 CPU-Software-Renderer/Core/Renderer.cpp
create mode 100644 CPU-Software-Renderer/Core/Renderer.h
create mode 100644 CPU-Software-Renderer/Math/MathUtil.h
create mode 100644 CPU-Software-Renderer/Math/Matrix4x4.h
create mode 100644 CPU-Software-Renderer/Math/Vector2.h
create mode 100644 CPU-Software-Renderer/Math/Vector3.h
create mode 100644 CPU-Software-Renderer/Math/Vector4.h
delete mode 100644 CPU-Software-Renderer/Rasterization.cpp
delete mode 100644 CPU-Software-Renderer/Rasterization.h
create mode 100644 CPU-Software-Renderer/Rasterizer/Rasterizer.cpp
create mode 100644 CPU-Software-Renderer/Rasterizer/Rasterizer.h
create mode 100644 CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp
create mode 100644 CPU-Software-Renderer/Rasterizer/TriangleRasterizer.h
create mode 100644 CPU-Software-Renderer/RenderData/BoundingBox.h
create mode 100644 CPU-Software-Renderer/RenderData/Color.h
create mode 100644 CPU-Software-Renderer/RenderData/Triangle.h
create mode 100644 CPU-Software-Renderer/Scene/Camera.h
create mode 100644 CPU-Software-Renderer/Scene/Mesh.h
create mode 100644 CPU-Software-Renderer/Scene/Model.h
create mode 100644 CPU-Software-Renderer/Scene/Transform.h
create mode 100644 CPU-Software-Renderer/Scene/Vertex.h
create mode 100644 CPU-Software-Renderer/Shading/BlinnPhongShader.cpp
create mode 100644 CPU-Software-Renderer/Shading/BlinnPhongShader.h
create mode 100644 CPU-Software-Renderer/Shading/ShaderTypes.h
delete mode 100644 CPU-Software-Renderer/StructType.h
diff --git a/CPU-Software-Renderer.slnx b/CPU-Software-Renderer.slnx
index 5180c2c..3cdcc9b 100644
--- a/CPU-Software-Renderer.slnx
+++ b/CPU-Software-Renderer.slnx
@@ -3,5 +3,7 @@
-
+
+
+
diff --git a/CPU-Software-Renderer/Asset/ObjLoader.cpp b/CPU-Software-Renderer/Asset/ObjLoader.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/CPU-Software-Renderer/Asset/ObjLoader.h b/CPU-Software-Renderer/Asset/ObjLoader.h
new file mode 100644
index 0000000..d94dcec
--- /dev/null
+++ b/CPU-Software-Renderer/Asset/ObjLoader.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Asset
+{
+ class ObjLoader
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj
index 4d2f6bc..33b6481 100644
--- a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj
+++ b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj
@@ -77,10 +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)
Console
true
+ SDL2.lib;SDL2main.lib;%(AdditionalDependencies)
+ D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)
@@ -92,10 +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)
Console
true
+ SDL2.lib;SDL2main.lib;%(AdditionalDependencies)
+ D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)
@@ -105,7 +111,7 @@
_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
stdcpp20
- D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\include;%(AdditionalIncludeDirectories)
+ 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)
Console
@@ -123,26 +129,52 @@
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)
Console
true
+ SDL2.lib;SDL2main.lib;%(AdditionalDependencies)
+ D:\source\CPU-Software-Renderer\CPU-Software-Renderer\libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)
-
+
+
+
+
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
diff --git a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj.filters b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj.filters
index 42fc765..ad8a31f 100644
--- a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj.filters
+++ b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj.filters
@@ -13,16 +13,64 @@
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+ {e546c002-17ba-4911-9a70-a1cf7ce337fd}
+
+
+ {b92096d9-3d39-4064-b9a2-efa279ad0775}
+
+
+ {7b6f5c6b-60bb-46f2-925b-65346e4d8c4b}
+
+
+ {1aa3c6ac-a580-480c-a2fe-2d57c98693ff}
+
+
+ {a7d67eb7-b4bc-4b5a-86f2-e80bcd1518d5}
+
+
+ {55224e49-7917-4fee-9a61-f1c14ebf8d5e}
+
+
+ {6eda961b-ec6a-4670-b093-be46b27fdeb7}
+
+
+ {4345cc0e-3d61-4dd9-b37f-4b42c30aa8d3}
+
+
+ {4b52509e-dde8-45e0-aeb3-d18131b94265}
+
+
+ {1644176d-c2fe-404b-9f42-45eb0bc85222}
+
+
+ {c77ae566-281a-4d76-80bd-41496deb0aeb}
+
源文件
-
- 源文件
+
+ 源文件\Core
-
- 源文件
+
+ 源文件\Core
+
+
+ 源文件\Core
+
+
+ 源文件\Asset
+
+
+ 源文件\Shading
+
+
+ 源文件\Rasterizer
+
+
+ 源文件\Rasterizer
@@ -31,14 +79,68 @@
-
- 头文件
+
+ 头文件\Core
-
- 头文件
+
+ 头文件\Core
-
- 头文件
+
+ 头文件\Core
+
+
+ 头文件\Math
+
+
+ 头文件\Math
+
+
+ 头文件\Math
+
+
+ 头文件\Math
+
+
+ 头文件\Math
+
+
+ 头文件\Scene
+
+
+ 头文件\Scene
+
+
+ 头文件\Scene
+
+
+ 头文件\Scene
+
+
+ 头文件\Scene
+
+
+ 头文件\Shading
+
+
+ 头文件\Shading
+
+
+ 头文件\Rasterizer
+
+
+ 头文件\Rasterizer
+
+
+ 头文件\Asset
+
+
+ 头文件\RenderData
+
+
+ 头文件\RenderData
+
+
+ 头文件\RenderData
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Color.cpp b/CPU-Software-Renderer/Color.cpp
deleted file mode 100644
index 873f23a..0000000
--- a/CPU-Software-Renderer/Color.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "Color.h"
-
-Color::Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
-{
- this->r = r;
- this->g = g;
- this->b = b;
- this->a = a;
-}
-
-Color::Color(uint8_t r, uint8_t g, uint8_t b)
-{
- Color(r, g, b, 255);
-}
-
-Color::Color(Color& other)
-{
- this->r = other.r;
- this->g = other.g;
- this->b = other.b;
- this->a = other.a;
-}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Color.h b/CPU-Software-Renderer/Color.h
deleted file mode 100644
index 2634d4e..0000000
--- a/CPU-Software-Renderer/Color.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-#include
-
-class Color
-{
- uint8_t r;
- uint8_t g;
- uint8_t b;
- uint8_t a;
-
-public:
- Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
- Color(uint8_t r, uint8_t g, uint8_t b);
- Color(Color& other);
-
- uint8_t GetR() const { return r; }
- void SetR(const uint8_t r) { this->r = r; }
-
- uint8_t GetG() const { return g; }
- void SetG(const uint8_t g) { this->g = g; }
-
- uint8_t GetB() const { return b; }
- void SetB(const uint8_t b) { this->b = b; }
-
- uint8_t GetA() const { return a; }
- void SetA(const uint8_t a) { this->a = a; }
-
- operator uint32_t() const
- {
- return (r << 24) | (g << 16) | (b << 8) | a;
- }
-
-};
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Core/DepthBuffer.cpp b/CPU-Software-Renderer/Core/DepthBuffer.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/CPU-Software-Renderer/Core/DepthBuffer.h b/CPU-Software-Renderer/Core/DepthBuffer.h
new file mode 100644
index 0000000..4e113e6
--- /dev/null
+++ b/CPU-Software-Renderer/Core/DepthBuffer.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Core
+{
+ class DepthBuffer
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Core/FrameBuffer.cpp b/CPU-Software-Renderer/Core/FrameBuffer.cpp
new file mode 100644
index 0000000..30072cf
--- /dev/null
+++ b/CPU-Software-Renderer/Core/FrameBuffer.cpp
@@ -0,0 +1,25 @@
+#include "FrameBuffer.h"
+#include
+#include
+#include
+using namespace Math;
+
+namespace Core
+{
+ void FrameBuffer::clear(const uint32_t color)
+ {
+ std::fill(buffer.begin(), buffer.end(), color);
+ }
+
+
+ void FrameBuffer::set_pixel(const int32_t x, const int32_t y, const uint32_t color)
+ {
+ 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;
+ buffer.at(index) = color;
+ }
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Core/FrameBuffer.h b/CPU-Software-Renderer/Core/FrameBuffer.h
new file mode 100644
index 0000000..41e42b1
--- /dev/null
+++ b/CPU-Software-Renderer/Core/FrameBuffer.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "Color.h"
+#include "Vector2.h"
+#include
+#include
+
+namespace Core
+{
+ class FrameBuffer
+ {
+ private:
+ int32_t width;
+ int32_t height;
+ std::vector buffer;
+
+ public:
+ size_t total_pixels() const { return buffer.size(); }
+
+ void* get_buffer() const { return (void*)buffer.data(); }
+
+ FrameBuffer(int32_t width, int32_t height) :width(width), height(height), buffer(std::vector(width * height, 0)) {}
+
+ void clear(const RenderData::Color& color)
+ {
+ clear(color.to_rgba());
+ }
+
+ void clear(const uint32_t color);
+
+ void set_pixel(const int32_t x, const int32_t y, const RenderData::Color& color)
+ {
+ set_pixel(Math::Vector2Int(x, y), color.to_rgba());
+ }
+
+ void set_pixel(const Math::Vector2Int position, const uint32_t color)
+ {
+ set_pixel(position.x, position.y, color);
+ }
+
+ void set_pixel(const int32_t x, const int32_t y, const uint32_t color);
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Core/Renderer.cpp b/CPU-Software-Renderer/Core/Renderer.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/CPU-Software-Renderer/Core/Renderer.h b/CPU-Software-Renderer/Core/Renderer.h
new file mode 100644
index 0000000..b3b04c9
--- /dev/null
+++ b/CPU-Software-Renderer/Core/Renderer.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Core
+{
+ class Renderer
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Math/MathUtil.h b/CPU-Software-Renderer/Math/MathUtil.h
new file mode 100644
index 0000000..fefaf5a
--- /dev/null
+++ b/CPU-Software-Renderer/Math/MathUtil.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Math
+{
+ class MathUtil
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Math/Matrix4x4.h b/CPU-Software-Renderer/Math/Matrix4x4.h
new file mode 100644
index 0000000..555a649
--- /dev/null
+++ b/CPU-Software-Renderer/Math/Matrix4x4.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Math
+{
+ class Matrix4x4
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Math/Vector2.h b/CPU-Software-Renderer/Math/Vector2.h
new file mode 100644
index 0000000..d3176ac
--- /dev/null
+++ b/CPU-Software-Renderer/Math/Vector2.h
@@ -0,0 +1,50 @@
+#pragma once
+#include
+#include
+#include
+
+namespace Math
+{
+ struct Vector2Int
+ {
+ int32_t x = 0;
+ int32_t y = 0;
+
+ Vector2Int() : x(0), y(0) {}
+ Vector2Int(int32_t x, int32_t y) : x(x), y(y) {}
+
+ ///
+ /// 交换当前 Vector2Int 对象与另一个 Vector2Int 对象的 x 和 y 的值
+ ///
+ /// 要交换的对象
+ static void swap(Vector2Int& vec1, Vector2Int& vec2)
+ {
+ std::swap(vec1.x, vec2.x);
+ std::swap(vec1.y, vec2.y);
+ }
+ };
+
+ struct Vector2
+ {
+ float x = 0.0f;
+ float y = 0.0f;
+
+ Vector2() : x(0), y(0) {}
+ Vector2(float x, float y) : x(x), y(y) {}
+
+ ///
+ /// 交换当前 Vector2 对象与另一个 Vector2 对象的 x 和 y 的值
+ ///
+ /// 要交换的对象
+ static void swap(Vector2& vec1, Vector2& vec2)
+ {
+ std::swap(vec1.x, vec2.x);
+ std::swap(vec1.y, vec2.y);
+ }
+
+ Vector2Int to_vector2Int() const
+ {
+ return Vector2Int(static_cast(std::lround(x)), static_cast(std::lround(y)));
+ }
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Math/Vector3.h b/CPU-Software-Renderer/Math/Vector3.h
new file mode 100644
index 0000000..acff28b
--- /dev/null
+++ b/CPU-Software-Renderer/Math/Vector3.h
@@ -0,0 +1,20 @@
+#pragma once
+#include
+
+namespace Math
+{
+ struct Vector3
+ {
+ float x = 0.0f;
+ float y = 0.0f;
+ float z = 0.0f;
+
+ Vector3() : x(0), y(0), z(0) {}
+ Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
+
+ float magnitude() const
+ {
+ return std::sqrt(x * x + y * y + z * z);
+ }
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Math/Vector4.h b/CPU-Software-Renderer/Math/Vector4.h
new file mode 100644
index 0000000..1d8d84e
--- /dev/null
+++ b/CPU-Software-Renderer/Math/Vector4.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Math
+{
+ class Vector4
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Rasterization.cpp b/CPU-Software-Renderer/Rasterization.cpp
deleted file mode 100644
index 3952a54..0000000
--- a/CPU-Software-Renderer/Rasterization.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#include "Rasterization.h"
-#include "StructType.h"
-#include
-#include
-#include
-#include
-using namespace CustomStructs;
-
-void Rasterization::DrawLineHorizontal(Vector2Int v0, Vector2Int v1, Color color)
-{
- if (v0.x > v1.x) Vector2Int::swap(v0, v1);
-
- int32_t dx = v1.x - v0.x;
- int32_t dy = v1.y - v0.y;
-
- int32_t dir = dy < 0 ? -1 : 1;
- dy *= dir;
-
- if (dx == 0) return;
-
- int32_t y = v0.y;
- int32_t p = 2 * dy - dx;
- for (int32_t x = v0.x; x <= v1.x; x++)
- {
- SetPixel(Vector2Int(x, y), color);
- // 当 p >= 0 时,取上方像素点
- if (p >= 0)
- {
- y += dir;
- p -= 2 * dx;
- }
- // 当 p < 0 时,取下方像素点
- p += 2 * dy;
- }
-}
-
-void Rasterization::DrawLineVertical(Vector2Int v0, Vector2Int v1, Color color)
-{
- if (v0.y > v1.y) Vector2Int::swap(v0, v1);
-
- int32_t dx = v1.x - v0.x;
- int32_t dy = v1.y - v0.y;
-
- int32_t dir = dx < 0 ? -1 : 1;
- dx *= dir;
-
- if (dy == 0) return;
-
- int32_t x = v0.x;
- int32_t p = 2 * dx - dy;
- for (int32_t y = v0.y; y <= v1.y; y++)
- {
- SetPixel(Vector2Int(x, y), color);
- // 当 p >= 0 时,取上方像素点
- if (p >= 0)
- {
- x += dir;
- p -= 2 * dy;
- }
- // 当 p < 0 时,取下方像素点
- p += 2 * dx;
- }
-}
-
-///
-/// 在给定的起始点和结束点之间绘制一条线段,并使用指定的颜色填充
-///
-/// 直线顶点 1
-/// 直线顶点 2
-/// 绘制的颜色
-///
-/// bresenham 画线算法
-///
-void Rasterization::DrawLine(Vector2Int v0, Vector2Int v1, Color color)
-{
- int32_t x0 = v0.x, y0 = v0.y;
- int32_t x1 = v1.x, y1 = v1.y;
-
- if (std::abs(x1 - x0) > std::abs(y1 - y0))
- {
- DrawLineHorizontal(v0, v1, color);
- }
- else
- {
- DrawLineVertical(v0, v1, color);
- }
-}
-
-void Rasterization::Clear(const Color color)
-{
- uint32_t colorValue = static_cast(color);
- std::fill(frameBuffer.begin(), frameBuffer.end(), colorValue);
-}
-
-void Rasterization::SetPixel(const Vector2Int pos, const Color color)
-{
- uint32_t colorValue = static_cast(color);
- if (pos.x < 0 || pos.y < 0 || pos.x >= width || pos.y >= height) return;
- const size_t pixelIndex = static_cast(pos.y) * static_cast(width) + static_cast(pos.x);
- frameBuffer[pixelIndex] = colorValue;
-}
-
-void Rasterization::DrawWireTriangle(const Vector2Int v0, const Vector2Int v1, const Vector2Int v2, Color color)
-{
- DrawLine(v0, v1, color);
- DrawLine(v0, v2, color);
- DrawLine(v1, v2, color);
-}
-
-void Rasterization::DrawFillTriangle(const Vector2Int v0, const Vector2Int v1, const Vector2Int v2, Color color)
-{
- Vector2Int aa, bb;
- aa.x = std::min({ v0.x, v1.x, v2.x });
- aa.y = std::min({ v0.y, v1.y, v2.y });
- bb.x = std::max({ v0.x, v1.x, v2.x });
- bb.y = std::max({ v0.y, v1.y, v2.y });
- Triangle triangle(v0, v1, v2);
-
- for (int x = aa.x; x <= bb.x; x++)
- {
- for (int y = aa.y; y <= bb.y; y++)
- {
- if (triangle.IsInTriangle(Vector2Int(x, y)))
- {
- SetPixel(Vector2Int(x, y), color);
- }
- }
- }
-}
diff --git a/CPU-Software-Renderer/Rasterization.h b/CPU-Software-Renderer/Rasterization.h
deleted file mode 100644
index 147e0bf..0000000
--- a/CPU-Software-Renderer/Rasterization.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-#include "StructType.h"
-#include
-#include
-using namespace CustomStructs;
-
-class Rasterization
-{
-private:
- int32_t width;
- int32_t height;
-
-public:
- std::vector frameBuffer;
-
-private:
- void DrawLineHorizontal(Vector2Int v0, Vector2Int v1, Color color);
-
- void DrawLineVertical(Vector2Int v0, Vector2Int v1, Color color);
-
-public:
- Rasterization(const int32_t width, const int32_t height)
- : width(width), height(height), frameBuffer(std::vector(static_cast(width)* static_cast(height))) {}
-
- void Clear(const Color color);
-
- void SetPixel(const Vector2Int pos, const Color color);
-
- void DrawLine(const Vector2Int v0, const Vector2Int v1, Color color);
-
- void DrawWireTriangle(const Vector2Int v0, const Vector2Int v1, const Vector2Int v2, Color color);
-
- void DrawFillTriangle(const Vector2Int v0, const Vector2Int v1, const Vector2Int v2, Color color);
-};
diff --git a/CPU-Software-Renderer/Rasterizer/Rasterizer.cpp b/CPU-Software-Renderer/Rasterizer/Rasterizer.cpp
new file mode 100644
index 0000000..9e7a943
--- /dev/null
+++ b/CPU-Software-Renderer/Rasterizer/Rasterizer.cpp
@@ -0,0 +1,102 @@
+#include "Rasterizer.h"
+#include
+#include "Color.h"
+#include
+#include
+
+namespace Rasterizer
+{
+ using namespace Math;
+ using namespace RenderData;
+
+ void Rasterizer::DrawLineHorizontal(const Vector2Int v0, const Vector2Int v1, const Color color)
+ {
+ Vector2Int start = v0, end = v1;
+ if (v0.x > v1.x)
+ {
+ start = v1;
+ end = v0;
+ }
+
+ int32_t dx = end.x - start.x;
+ int32_t dy = end.y - start.y;
+
+ int32_t dir = dy < 0 ? -1 : 1;
+ dy *= dir;
+
+ if (dx == 0) return;
+
+ int32_t y = start.y;
+ int32_t p = 2 * dy - dx;
+ for (int32_t x = start.x; x <= end.x; x++)
+ {
+ frameBuffer.set_pixel(x, y, color.to_rgba());
+ // 当 p >= 0 时,取上方像素点
+ if (p >= 0)
+ {
+ y += dir;
+ p -= 2 * dx;
+ }
+ // 当 p < 0 时,取下方像素点
+ p += 2 * dy;
+ }
+ }
+
+ void Rasterizer::DrawLineVertical(const Vector2Int v0, const Vector2Int v1, const Color color)
+ {
+ Vector2Int start = v0, end = v1;
+ if (v0.y > v1.y)
+ {
+ start = v1;
+ end = v0;
+ }
+
+ int32_t dx = end.x - start.x;
+ int32_t dy = end.y - start.y;
+
+ int32_t dir = dx < 0 ? -1 : 1;
+ dx *= dir;
+
+ if (dy == 0) return;
+
+ int32_t x = start.x;
+ int32_t p = 2 * dx - dy;
+ for (int32_t y = start.y; y <= end.y; y++)
+ {
+ frameBuffer.set_pixel(x, y, color.to_rgba());
+ // 当 p >= 0 时,取上方像素点
+ if (p >= 0)
+ {
+ x += dir;
+ p -= 2 * dy;
+ }
+ // 当 p < 0 时,取下方像素点
+ p += 2 * dx;
+ }
+ }
+
+ ///
+ /// 在给定的起始点和结束点之间绘制一条线段,并使用指定的颜色填充
+ ///
+ /// 直线顶点 1
+ /// 直线顶点 2
+ /// 绘制的颜色
+ ///
+ /// bresenham 画线算法
+ ///
+ void Rasterizer::DrawLine(const Vector2Int v0, const Vector2Int v1, const Color color)
+ {
+ int32_t x0 = v0.x, y0 = v0.y;
+ int32_t x1 = v1.x, y1 = v1.y;
+
+ if (std::abs(x1 - x0) > std::abs(y1 - y0))
+ {
+ DrawLineHorizontal(v0, v1, color);
+ }
+ else
+ {
+ DrawLineVertical(v0, v1, color);
+ }
+ }
+}
+
diff --git a/CPU-Software-Renderer/Rasterizer/Rasterizer.h b/CPU-Software-Renderer/Rasterizer/Rasterizer.h
new file mode 100644
index 0000000..58c291d
--- /dev/null
+++ b/CPU-Software-Renderer/Rasterizer/Rasterizer.h
@@ -0,0 +1,21 @@
+#pragma once
+#include "Color.h"
+#include "FrameBuffer.h"
+#include
+
+namespace Rasterizer
+{
+ class Rasterizer
+ {
+ private:
+ Core::FrameBuffer& frameBuffer;
+
+ void DrawLineHorizontal(const Math::Vector2Int v0, const Math::Vector2Int v1, const RenderData::Color color);
+ void DrawLineVertical(const Math::Vector2Int v0, const Math::Vector2Int v1, const RenderData::Color color);
+
+ public:
+ explicit Rasterizer(Core::FrameBuffer& frameBuffer) :frameBuffer(frameBuffer) {};
+
+ void DrawLine(const Math::Vector2Int v0, const Math::Vector2Int v1, const RenderData::Color color);
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp b/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp
new file mode 100644
index 0000000..07f2f07
--- /dev/null
+++ b/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.cpp
@@ -0,0 +1,25 @@
+#include "TriangleRasterizer.h"
+#include
+#include
+#include "BoundingBox.h"
+#include
+using namespace RenderData;
+
+namespace Rasterizer
+{
+ void TriangleRasterizer::DrawTriangle2D(const Triangle2D triangle, const Color color)
+ {
+ auto boundingBox = triangle.get_boundingBox();
+
+ for (int x = boundingBox.min.x; x <= boundingBox.max.x; x++)
+ {
+ for (int y = boundingBox.min.y; y <= boundingBox.max.y; y++)
+ {
+ if (triangle.ContainsPixel(Vector2(x, y)))
+ {
+ frameBuffer.set_pixel(Vector2Int(x, y), color.to_rgba());
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.h b/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.h
new file mode 100644
index 0000000..bd51c20
--- /dev/null
+++ b/CPU-Software-Renderer/Rasterizer/TriangleRasterizer.h
@@ -0,0 +1,19 @@
+#pragma once
+#include "Triangle.h"
+#include "Color.h"
+#include "FrameBuffer.h"
+
+namespace Rasterizer
+{
+ class TriangleRasterizer
+ {
+ private:
+ Core::FrameBuffer& frameBuffer;
+
+
+ public:
+ explicit TriangleRasterizer(Core::FrameBuffer& frameBuffer) :frameBuffer(frameBuffer) {};
+
+ void DrawTriangle2D(const RenderData::Triangle2D triangle, const RenderData::Color color);
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/RenderData/BoundingBox.h b/CPU-Software-Renderer/RenderData/BoundingBox.h
new file mode 100644
index 0000000..deb4bb5
--- /dev/null
+++ b/CPU-Software-Renderer/RenderData/BoundingBox.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Vector2.h"
+
+namespace RenderData
+{
+ struct BoundingBox2D
+ {
+ Math::Vector2 min;
+ Math::Vector2 max;
+
+ BoundingBox2D() : min(), max() {}
+ BoundingBox2D(const Math::Vector2 min, const Math::Vector2 max) : min(min), max(max) {}
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/RenderData/Color.h b/CPU-Software-Renderer/RenderData/Color.h
new file mode 100644
index 0000000..1aa5ba6
--- /dev/null
+++ b/CPU-Software-Renderer/RenderData/Color.h
@@ -0,0 +1,34 @@
+#pragma once
+#include
+
+namespace RenderData
+{
+ struct Color
+ {
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+ uint8_t a;
+ Color() : r(0), g(0), b(0), a(0) {}
+ Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
+ {
+ this->r = ClampToByte(r);
+ this->g = ClampToByte(g);
+ this->b = ClampToByte(b);
+ this->a = ClampToByte(a);
+ }
+
+ uint32_t to_rgba() const
+ {
+ uint32_t value = (static_cast(r) << 24) | (static_cast(g) << 16) | (static_cast(b) << 8) | (static_cast(a));
+ return value;
+ }
+
+ static uint8_t ClampToByte(const int32_t value)
+ {
+ if (value < 0) return 0;
+ if (value > 255) return 255;
+ return static_cast(value);
+ }
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/RenderData/Triangle.h b/CPU-Software-Renderer/RenderData/Triangle.h
new file mode 100644
index 0000000..a470230
--- /dev/null
+++ b/CPU-Software-Renderer/RenderData/Triangle.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "Vector2.h"
+#include "BoundingBox.h"
+#include
+
+namespace RenderData
+{
+ using namespace Math;
+ struct Triangle2D
+ {
+ Vector2 v0;
+ Vector2 v1;
+ Vector2 v2;
+ Triangle2D() : v0(), v1(), v2() {}
+ Triangle2D(const Vector2 a, const Vector2 b, const 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 }));
+
+ return BoundingBox2D(min, max);
+ }
+
+ bool ContainsPixel(const Vector2 point) const
+ {
+ auto cross = [](const Vector2& p1, const Vector2& p2, const Vector2& p3) -> float
+ {
+ const float x1 = p2.x - p1.x;
+ const float y1 = p2.y - p1.y;
+ const float x2 = p3.x - p1.x;
+ const float y2 = p3.y - p1.y;
+ return x1 * y2 - y1 * x2;
+ };
+
+ const float c0 = cross(v0, v1, point);
+ const float c1 = cross(v1, v2, point);
+ const float c2 = cross(v2, v0, point);
+
+ const bool hasNeg = (c0 < 0) || (c1 < 0) || (c2 < 0);
+ const bool hasPos = (c0 > 0) || (c1 > 0) || (c2 > 0);
+
+ return !(hasNeg && hasPos);
+ }
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Scene/Camera.h b/CPU-Software-Renderer/Scene/Camera.h
new file mode 100644
index 0000000..2e3c3c6
--- /dev/null
+++ b/CPU-Software-Renderer/Scene/Camera.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Scene
+{
+ class Camera
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Scene/Mesh.h b/CPU-Software-Renderer/Scene/Mesh.h
new file mode 100644
index 0000000..7ee047c
--- /dev/null
+++ b/CPU-Software-Renderer/Scene/Mesh.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Scene
+{
+ class Mesh
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Scene/Model.h b/CPU-Software-Renderer/Scene/Model.h
new file mode 100644
index 0000000..838472a
--- /dev/null
+++ b/CPU-Software-Renderer/Scene/Model.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Scene
+{
+ class Model
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Scene/Transform.h b/CPU-Software-Renderer/Scene/Transform.h
new file mode 100644
index 0000000..d6d4abe
--- /dev/null
+++ b/CPU-Software-Renderer/Scene/Transform.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Scene
+{
+ class Transform
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Scene/Vertex.h b/CPU-Software-Renderer/Scene/Vertex.h
new file mode 100644
index 0000000..40c5f0b
--- /dev/null
+++ b/CPU-Software-Renderer/Scene/Vertex.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Scene
+{
+ class Vertex
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Shading/BlinnPhongShader.cpp b/CPU-Software-Renderer/Shading/BlinnPhongShader.cpp
new file mode 100644
index 0000000..e69de29
diff --git a/CPU-Software-Renderer/Shading/BlinnPhongShader.h b/CPU-Software-Renderer/Shading/BlinnPhongShader.h
new file mode 100644
index 0000000..399eaff
--- /dev/null
+++ b/CPU-Software-Renderer/Shading/BlinnPhongShader.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Shading
+{
+ class BlinnPhongShader
+ {};
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Shading/ShaderTypes.h b/CPU-Software-Renderer/Shading/ShaderTypes.h
new file mode 100644
index 0000000..d5b03d2
--- /dev/null
+++ b/CPU-Software-Renderer/Shading/ShaderTypes.h
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace Shading
+{
+ enum class ShaderType
+ {
+ BlinnPhong,
+ };
+}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/StructType.h b/CPU-Software-Renderer/StructType.h
deleted file mode 100644
index 71d4d27..0000000
--- a/CPU-Software-Renderer/StructType.h
+++ /dev/null
@@ -1,142 +0,0 @@
-#pragma once
-#include
-#include
-
-namespace CustomStructs
-{
- struct Vector2Int
- {
- int32_t x;
- int32_t y;
- Vector2Int() : x(0), y(0) {}
- Vector2Int(int32_t x, int32_t y) : x(x), y(y) {}
-
- ///
- /// 交换 x 和 y 的值
- ///
- void swap()
- {
- std::swap(x, y);
- }
-
- ///
- /// 交换当前 Vector2Int 对象与另一个 Vector2Int 对象的 x 和 y 的值
- ///
- /// 要交换的对象
- static void swap(Vector2Int& vec1, Vector2Int& vec2)
- {
- std::swap(vec1.x, vec2.x);
- std::swap(vec1.y, vec2.y);
- }
- };
-
- struct Vector2
- {
- float x;
- float y;
- Vector2() : x(0), y(0) {}
- Vector2(float x, float y) : x(x), y(y) {}
- Vector2(const Vector2Int& v) : x(static_cast(v.x)), y(static_cast(v.y)) {}
-
- ///
- /// 交换 x 和 y 的值
- ///
- void swap()
- {
- std::swap(x, y);
- }
-
- ///
- /// 交换当前 Vector2 对象与另一个 Vector2 对象的 x 和 y 的值
- ///
- /// 要交换的对象
- static void swap(Vector2& vec1, Vector2& vec2)
- {
- std::swap(vec1.x, vec2.x);
- std::swap(vec1.y, vec2.y);
- }
- };
-
- struct Vector3Int
- {
- int32_t x;
- int32_t y;
- int32_t z;
- Vector3Int() : x(0), y(0), z(0) {}
- Vector3Int(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z) {}
- };
-
- struct Vector3
- {
- float x;
- float y;
- float z;
- Vector3() : x(0), y(0), z(0) {}
- Vector3(float x, float y, float z) : x(x), y(y), z(z) {}
- Vector3(const Vector3Int& v) : x(static_cast(v.x)), y(static_cast(v.y)), z(static_cast(v.z)) {}
- };
-
- struct Triangle
- {
- Vector2Int a;
- Vector2Int b;
- Vector2Int c;
- Triangle() : a(), b(), c() {}
- Triangle(const Vector2Int a, const Vector2Int b, const Vector2Int c) : a(a), b(b), c(c) {}
-
- bool IsInTriangle(const Vector2Int point) const
- {
- auto cross = [](const Vector2Int& p1, const Vector2Int& p2, const Vector2Int& p3) -> int64_t
- {
- const int64_t x1 = static_cast(p2.x) - p1.x;
- const int64_t y1 = static_cast(p2.y) - p1.y;
- const int64_t x2 = static_cast(p3.x) - p1.x;
- const int64_t y2 = static_cast(p3.y) - p1.y;
- return x1 * y2 - y1 * x2;
- };
-
- const int64_t c0 = cross(a, b, point);
- const int64_t c1 = cross(b, c, point);
- const int64_t c2 = cross(c, a, point);
-
- const bool hasNeg = (c0 < 0) || (c1 < 0) || (c2 < 0);
- const bool hasPos = (c0 > 0) || (c1 > 0) || (c2 > 0);
-
- return !(hasNeg && hasPos);
- }
- };
-
- struct Color
- {
- uint8_t r;
- uint8_t g;
- uint8_t b;
- uint8_t a;
- Color() : r(0), g(0), b(0), a(0) {}
- Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
- {
- this->r = ClampToByte(static_cast(r));
- this->g = ClampToByte(static_cast(g));
- this->b = ClampToByte(static_cast(b));
- this->a = ClampToByte(static_cast(a));
- }
-
- operator uint32_t() const
- {
- return
- (
- (static_cast(r) << 24) |
- (static_cast(g) << 16) |
- (static_cast(b) << 8) |
- (static_cast(a))
- );
- }
-
- static uint8_t ClampToByte(const int32_t value)
- {
- if (value < 0) return 0;
- if (value > 255) return 255;
- return static_cast(value);
- }
- };
-}
diff --git a/CPU-Software-Renderer/main.cpp b/CPU-Software-Renderer/main.cpp
index e5ad45d..a20b2d2 100644
--- a/CPU-Software-Renderer/main.cpp
+++ b/CPU-Software-Renderer/main.cpp
@@ -1,17 +1,17 @@
-#include
-#include
+#include
#include
-#include "Rasterization.h"
-#include "StructType.h"
#include "SDL_video.h"
#include "SDL_render.h"
#include
#include "SDL_error.h"
-#include
+#include "Vector2.h"
+#include "Color.h"
+#include "FrameBuffer.h"
+#include "Rasterizer.h"
const uint32_t SDL_INIT_FLAGS = SDL_INIT_VIDEO;
-const int width = 800;
-const int height = 600;
+const int32_t width = 800;
+const int32_t height = 600;
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
@@ -90,20 +90,25 @@ int main(int argc, char* argv[])
if (!EnsureSDLWindow()) return -1;
if (!EnsureRenderer()) return -1;
-
+
SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, width, height);
- Rasterization* rasterization = new Rasterization(width, height);
+ Core::FrameBuffer frameBuffer(width, height);
+ Rasterizer::Rasterizer rasterizer(frameBuffer);
- CustomStructs::Vector2Int v0(100, 100);
- CustomStructs::Vector2Int v1(300, 100);
- CustomStructs::Vector2Int v2(300, 400);
- CustomStructs::Color color1(255, 0, 0, 255);
- rasterization->DrawFillTriangle(v0, v1, v2, color1);
+ Math::Vector2Int v0(100, 100);
+ Math::Vector2Int v1(300, 100);
+ Math::Vector2Int v2(300, 400);
+ RenderData::Color color0(255, 0, 0, 255);
+ RenderData::Color color1(0, 255, 0, 255);
+ RenderData::Color color2(0, 0, 255, 255);
+ rasterizer.DrawLine(v0, v1, color0);
+ rasterizer.DrawLine(v1, v2, color1);
+ rasterizer.DrawLine(v2, v0, color2);
while (true)
{
- SDL_UpdateTexture(texture, nullptr, rasterization->frameBuffer.data(), width * sizeof(uint32_t));
+ SDL_UpdateTexture(texture, nullptr, frameBuffer.get_buffer(), width * sizeof(uint32_t));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
diff --git a/README.md b/README.md
index 332c609..0ca0ee4 100644
--- a/README.md
+++ b/README.md
@@ -1,158 +1,161 @@
# CPU Software Renderer
-一个基于 C++ 和 SDL2 的小型 CPU 渲染器练习项目。当前版本聚焦在最基础的 2D 光栅化能力上,通过 CPU 维护帧缓冲区,再将像素数据上传到 SDL 纹理并显示到窗口中。
+一个基于 C++20 和 SDL2 的 CPU 软光栅化练习项目。
-项目目标不是调用现成图形 API 去画三角形,而是从像素写入、直线绘制、三角形光栅化开始,逐步补齐一个软件渲染器所需的核心 pipeline。
-
-## 项目定位
-
-- 使用 CPU 完成像素级绘制和光栅化
-- 使用 SDL2 负责窗口创建、纹理更新和屏幕展示
-- 以最小可运行工程为基础,逐步扩展到 3D 渲染流程
+这个仓库当前还处在早期阶段,重点不是调用现成图形 API 画三角形,而是自己维护帧缓冲、自己做基础光栅化,并逐步搭起一个小型 software renderer 的骨架。
## 当前状态
-当前代码已经具备这些基础能力:
+目前已经完成或具备雏形的部分:
-- 基于 `frameBuffer` 的软件像素输出
-- `SetPixel` 像素写入
-- Bresenham 直线绘制
-- 三角形线框绘制
-- 三角形包围盒扫描填充
-- SDL2 窗口创建、纹理更新与显示
+- 使用 SDL2 创建窗口、纹理和显示循环
+- 在 CPU 侧维护 `FrameBuffer`
+- 像素写入接口 `set_pixel`
+- 基础直线光栅化模块 `Rasterizer`
+- 2D 三角形、包围盒、颜色等基础数据结构
+- 独立的 `TriangleRasterizer` 模块,用于后续填充三角形
-当前 `main.cpp` 中已经可以直接绘制一个填充三角形,用来验证基础光栅化逻辑。
+当前 `main.cpp` 主要用于验证基础链路,程序启动后会在窗口中绘制三条彩色线段组成的三角形轮廓。
-## 技术选型
+还没有完成的核心能力:
-- 语言标准:C++20
-- 工程类型:Visual Studio C++ 项目(`.vcxproj`)
-- 渲染方式:CPU Software Rasterization
-- 窗口与展示层:SDL2
-- 开发环境:Windows + MSVC
+- 完整接入实心三角形渲染流程
+- MVP 变换
+- 深度测试
+- 重心坐标插值
+- 光照
+- OBJ 加载
+- 可交互相机
-选择 SDL2 的原因很直接:它只负责跨平台窗口和像素展示,足够轻量,不会替代掉软件渲染器本身的核心逻辑。
-
-## 依赖
-
-项目当前依赖很少:
-
-- SDL2
-
-仓库内已经包含 SDL2 相关文件:
-
-- 头文件目录:`libs/SDL2/include`
-- x64 库目录:`libs/SDL2/lib/x64`
-- 运行时动态库:`libs/SDL2/SDL2.dll`
-
-## 构建环境
-
-当前工程配置以 Windows 本地开发为主,推荐环境:
-
-- Visual Studio 2022
-- MSVC 工具链
-- Windows 10/11 SDK
-
-项目文件中启用了:
-
-- `stdcpp20`
-- `PlatformToolset=v145`
-
-## 构建方式
-
-1. 使用 Visual Studio 打开 `CPU-Software-Renderer.vcxproj`
-2. 选择 `Debug | x64`
-3. 直接构建并运行
-
-说明:
-
-- 当前工程的 SDL2 include/lib 路径写在 `.vcxproj` 里
-- 现有配置里 `Debug | x64` 已配置 SDL2 头文件和链接目录
-- 如果你移动了仓库位置,可能需要同步调整工程中的绝对路径
-
-## 当前工程结构
+## 当前结构
```text
CPU-Software-Renderer/
-├─ main.cpp # 程序入口,SDL 初始化与显示循环
-├─ Rasterization.h/.cpp # 帧缓冲、画线、三角形绘制
-├─ StructType.h # 向量、三角形、颜色等基础结构
-├─ Color.h/.cpp # 颜色相关封装
-├─ libs/SDL2/ # SDL2 头文件、库和运行时文件
-└─ TODO.md # 后续功能路线图
+├─ CPU-Software-Renderer/
+│ ├─ main.cpp
+│ ├─ Core/
+│ │ ├─ FrameBuffer.h/.cpp
+│ │ ├─ DepthBuffer.h/.cpp
+│ │ └─ Renderer.h/.cpp
+│ ├─ Math/
+│ │ ├─ Vector2.h
+│ │ ├─ Vector3.h
+│ │ ├─ Vector4.h
+│ │ ├─ Matrix4x4.h
+│ │ └─ MathUtil.h
+│ ├─ RenderData/
+│ │ ├─ Color.h
+│ │ ├─ BoundingBox.h
+│ │ └─ Triangle.h
+│ ├─ Rasterizer/
+│ │ ├─ Rasterizer.h/.cpp
+│ │ └─ TriangleRasterizer.h/.cpp
+│ ├─ Scene/
+│ │ ├─ Vertex.h
+│ │ ├─ Mesh.h
+│ │ ├─ Transform.h
+│ │ ├─ Model.h
+│ │ └─ Camera.h
+│ ├─ Asset/
+│ │ └─ ObjLoader.h/.cpp
+│ ├─ Shading/
+│ │ ├─ ShaderTypes.h
+│ │ └─ BlinnPhongShader.h/.cpp
+│ ├─ libs/SDL2/
+│ └─ TODO.md
+└─ README.md
```
-## 已实现模块
+## 模块说明
-### 1. Frame Buffer
+### Core
-渲染结果先写入 CPU 侧的 `std::vector` 帧缓冲区,再通过 `SDL_UpdateTexture` 更新到纹理。
+- `FrameBuffer`:管理 CPU 侧颜色缓冲
+- `DepthBuffer`:为后续深度测试预留
+- `Renderer`:为后续统一调度渲染流程预留
-### 2. Rasterizer
+### Math
-当前已经实现:
+- 放通用数学类型
+- 当前以 `Vector2`、`Vector2Int`、`Vector3` 为主
+- `Vector4` 和 `Matrix4x4` 目前还是占位
-- `DrawLine`
-- `DrawWireTriangle`
-- `DrawFillTriangle`
+### RenderData
-其中直线绘制使用 Bresenham 思路,填充三角形使用包围盒扫描配合点在三角形内测试。
+- 放渲染领域数据,而不是底层数学类型
+- 当前包含 `Color`、`BoundingBox2D`、`Triangle2D`
-### 3. 基础数学类型
+### Rasterizer
-当前工程已经定义了:
+- `Rasterizer`:负责基础线段光栅化
+- `TriangleRasterizer`:负责三角形填充相关逻辑
-- `Vector2Int`
-- `Vector2`
-- `Vector3Int`
-- `Vector3`
-- `Triangle`
-- `Color`
+### Scene / Asset / Shading
-这些结构会作为后续扩展 MVP 变换、深度测试、法线和属性插值的基础。
+这些目录已经预留出来了,方便后面扩展到 3D 渲染流程,但当前多数还是占位类。
+
+## 构建环境
+
+- Windows
+- Visual Studio 2022
+- MSVC
+- C++20
+- SDL2
+
+工程文件是 Visual Studio 的 `.vcxproj`。
+
+## 依赖
+
+仓库内已经包含 SDL2:
+
+- 头文件:`CPU-Software-Renderer/libs/SDL2/include`
+- Win32 库:`CPU-Software-Renderer/libs/SDL2/lib/x86`
+- x64 库:`CPU-Software-Renderer/libs/SDL2/lib/x64`
+
+## 构建与运行
+
+1. 用 Visual Studio 打开 `CPU-Software-Renderer/CPU-Software-Renderer.vcxproj`
+2. 选择 `Debug` 或 `Release`
+3. 选择 `Win32` 或 `x64`
+4. 构建并运行
+
+说明:
+
+- 工程里已经分别配置了 Win32 和 x64 的 SDL2 include/lib 路径
+- 运行时需要让程序找到与平台匹配的 `SDL2.dll`
+- 如果你移动了仓库位置,可能需要同步检查 `.vcxproj` 里的绝对路径
+
+## 设计取向
+
+当前代码结构遵循一个比较简单的原则:
+
+- 纯数据类型放在 `Math` 和 `RenderData`
+- 做事的模块放在 `Core`、`Rasterizer`、`Asset`、`Shading`
+- 先把 2D 基础链路理顺,再逐步加 3D pipeline
+
+这意味着现阶段更强调“结构和边界先理清”,而不是一次性把所有功能堆进去。
## 后续计划
-1. 完成稳定的三角形光栅化基础
-2. 加入 MVP 变换,实现 3D 顶点到屏幕空间的投影
-3. 加入 Z-buffer,解决遮挡关系
-4. 实现重心坐标属性插值
-5. 实现 Blinn-Phong 光照
-6. 支持 OBJ 模型加载
-7. 实现相机控制
+按 `TODO.md` 的路线,后续会逐步补齐:
-如果后续继续扩展,比较值得加入的方向还有:
+1. 稳定的三角形填充
+2. MVP 变换
+3. Z-buffer
+4. 属性插值
+5. Blinn-Phong 光照
+6. OBJ 模型加载
+7. 相机控制
+
+如果后续继续扩展,还可以考虑:
- Texture Mapping
-- MSAA 抗锯齿
+- MSAA
- 更完整的数学库
-- Shader 结构拆分
-
-## 这个项目最终会变成什么
-
-按当前路线推进后,这个项目会逐步具备一个小型软件渲染器的基本结构:
-
-```text
-Renderer
-├─ Rasterizer
-├─ Shader
-├─ Camera
-├─ Math
-├─ OBJLoader
-└─ ZBuffer
-```
-
-最终目标是实现一个不依赖 GPU 光栅化管线、但具备基本 3D 渲染能力的 CPU Renderer。
-
-## 适合用来做什么
-
-这个项目比较适合:
-
-- 学习软件渲染器的基本实现方式
-- 理解三角形光栅化、像素写入和屏幕空间坐标
-- 作为后续学习图形学、渲染 pipeline、光照和模型加载的实验场
-- 用于整理个人图形学项目经历
+- 更清晰的 shader 输入输出结构
## 说明
-当前项目仍在早期阶段,很多功能还处于逐步实现中。README 中的“后续计划”部分表示目标路线,不代表这些能力已经全部完成。
+这个项目现在更接近“正在搭骨架的 renderer”,不是一个已经完成的 3D 渲染器。
+
+README 中提到的很多模块和目录,目的是反映当前的架构方向;其中一部分已经有初步实现,另一部分还只是为后续阶段预留。