From 858c0b4d5925d66101eca3908e61f5853020667c Mon Sep 17 00:00:00 2001
From: SepComet <2428390463@qq.com>
Date: Thu, 19 Mar 2026 14:16:29 +0800
Subject: [PATCH] =?UTF-8?q?viewport=20=E8=A7=86=E5=8F=A3=E5=8F=98=E6=8D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
AGENTS.md | 30 ++
.../CPU-Software-Renderer.vcxproj | 371 +++++++++---------
.../CPU-Software-Renderer.vcxproj.filters | 294 +++++++-------
CPU-Software-Renderer/Core/FrameBuffer.cpp | 31 +-
CPU-Software-Renderer/Math/MathUtil.h | 2 +-
CPU-Software-Renderer/Scene/Camera.cpp | 13 +
CPU-Software-Renderer/Scene/Camera.h | 2 +
CPU-Software-Renderer/main.cpp | 13 +-
9 files changed, 402 insertions(+), 355 deletions(-)
create mode 100644 AGENTS.md
diff --git a/.gitignore b/.gitignore
index 93475d9..600ece8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,3 +44,4 @@ compile_commands.json
Thumbs.db
SDL2-2.32.10-win32-x64.zip
SDL2-devel-2.32.10-VC.zip
+/.dotnet-home
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..19e6302
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,30 @@
+# Repository Guidelines
+
+## Project Structure & Module Organization
+The repository is a single Visual Studio C++ project under `CPU-Software-Renderer/`. `main.cpp` is the current executable entry point and demo loop. Core renderer pieces live in `Core/` (`FrameBuffer`, `DepthBuffer`, `Renderer`), math types in `Math/`, rasterization logic in `Rasterizer/`, scene data in `Scene/`, asset loading in `Asset/`, and shader code in `Shading/`. SDL2 is vendored in `CPU-Software-Renderer/libs/SDL2/`. Planning notes live in `CPU-Software-Renderer/TODO.md`. Build outputs appear in `Debug/`, `Release/`, and `x64/`; do not commit those artifacts.
+
+## Build, Test, and Development Commands
+Use Visual Studio 2022 or MSBuild, not `dotnet build`, because the project depends on Visual C++ targets.
+
+```powershell
+MSBuild.exe CPU-Software-Renderer\CPU-Software-Renderer.vcxproj /p:Configuration=Debug /p:Platform=x64
+```
+
+Builds the debug x64 executable at `CPU-Software-Renderer/x64/Debug/CPU-Software-Renderer.exe`.
+
+```powershell
+MSBuild.exe CPU-Software-Renderer\CPU-Software-Renderer.vcxproj /p:Configuration=Release /p:Platform=x64
+```
+
+Builds the optimized release binary. In Visual Studio, open `CPU-Software-Renderer.slnx` or the `.vcxproj`, then run the selected `Debug|x64` or `Release|x64` target.
+
+## Coding Style & Naming Conventions
+Follow the existing C++20/MSVC style: tabs for indentation, braces on the next line for functions and control blocks, and include headers with quoted local paths such as `"FrameBuffer.h"`. Types and namespaces use `PascalCase` (`FrameBuffer`, `Math::Vector3`), methods use `snake_case` (`set_pixel`, `set_position`), and local variables use descriptive lowercase names. Keep modules narrow: math stays in `Math/`, render-domain structs in `RenderData/`, and behavior in `Core/` or `Rasterizer/`.
+
+## Testing Guidelines
+There is no automated test project yet. Validate changes by building `Debug|x64`, running the executable, and checking the rendered output or interaction path you changed. When adding nontrivial math or rasterization behavior, prefer small, isolated helper functions so a future test target can cover them easily.
+
+## Commit & Pull Request Guidelines
+Recent history uses short, imperative commit subjects, sometimes in English and sometimes in Chinese, for example `add TODO.md` and `完善 SDL 主循环并收紧三角形光栅化边界处理`. Keep the subject concise and focused on one change. Pull requests should describe the rendering behavior changed, list the build configuration used for verification, and include a screenshot or short note when the visual output changes.
+
+Use UTF-8 encoding when reading and writing.
\ 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 e92ba6e..88400ea 100644
--- a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj
+++ b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj
@@ -1,194 +1,187 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
- Debug
- x64
-
-
- Release
- x64
-
-
-
- 18.0
- Win32Proj
- {937b923d-dd0c-41ae-81eb-af978170b0ca}
- CPUSoftwareRenderer
- 10.0
-
-
-
- Application
- true
- v145
- Unicode
-
-
- Application
- false
- v145
- true
- Unicode
-
-
- Application
- true
- v145
- Unicode
-
-
- Application
- false
- v145
- true
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Level3
- true
- WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- stdcpp20
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 18.0
+ Win32Proj
+ {937b923d-dd0c-41ae-81eb-af978170b0ca}
+ CPUSoftwareRenderer
+ 10.0
+
+
+
+ Application
+ true
+ v145
+ Unicode
+
+
+ Application
+ false
+ v145
+ true
+ Unicode
+
+
+ Application
+ true
+ v145
+ Unicode
+
+
+ Application
+ false
+ v145
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp20
- $(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)
- $(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- true
- true
- true
- WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- stdcpp20
+ $(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)
+ $(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp20
- $(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)
- $(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)
-
-
-
-
- Level3
- true
- _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- stdcpp20
+ $(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)
+ $(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp20
- $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)
-
-
- Console
- true
- $(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)
- SDL2.lib;SDL2main.lib;%(AdditionalDependencies)
-
-
-
-
- Level3
- true
- true
- true
- NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- true
- stdcpp20
+ $(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)
+ /utf-8 %(AdditionalOptions)
+
+
+ Console
+ true
+ $(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)
+ SDL2.lib;SDL2main.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ stdcpp20
- $(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)
- $(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ $(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)
+ $(ProjectDir)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 ad8a31f..ea3a808 100644
--- a/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj.filters
+++ b/CPU-Software-Renderer/CPU-Software-Renderer.vcxproj.filters
@@ -1,146 +1,150 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
-
-
- {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
-
-
-
-
- 资源文件
-
-
-
-
- 头文件\Core
-
-
- 头文件\Core
-
-
- 头文件\Core
-
-
- 头文件\Math
-
-
- 头文件\Math
-
-
- 头文件\Math
-
-
- 头文件\Math
-
-
- 头文件\Math
-
-
- 头文件\Scene
-
-
- 头文件\Scene
-
-
- 头文件\Scene
-
-
- 头文件\Scene
-
-
- 头文件\Scene
-
-
- 头文件\Shading
-
-
- 头文件\Shading
-
-
- 头文件\Rasterizer
-
-
- 头文件\Rasterizer
-
-
- 头文件\Asset
-
-
- 头文件\RenderData
-
-
- 头文件\RenderData
-
-
- 头文件\RenderData
-
-
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {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
+
+
+ 源文件
+
+
+
+
+ 资源文件
+
+
+
+
+
+ 头文件\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/Core/FrameBuffer.cpp b/CPU-Software-Renderer/Core/FrameBuffer.cpp
index d565b23..9792785 100644
--- a/CPU-Software-Renderer/Core/FrameBuffer.cpp
+++ b/CPU-Software-Renderer/Core/FrameBuffer.cpp
@@ -1,24 +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);
- }
-
-
+#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)
{
return;
}
+ // Row-major layout with y = 0 on the first row, matching a top-left screen origin.
size_t index = static_cast(y) * width + x;
buffer.at(index) = color;
}
-}
\ No newline at end of file
+}
diff --git a/CPU-Software-Renderer/Math/MathUtil.h b/CPU-Software-Renderer/Math/MathUtil.h
index 98d7afb..c4e9100 100644
--- a/CPU-Software-Renderer/Math/MathUtil.h
+++ b/CPU-Software-Renderer/Math/MathUtil.h
@@ -5,7 +5,7 @@
namespace Math
{
- static class MathUtil
+ class MathUtil
{
public:
static Matrix4x4 get_translate_matrix(const float x, const float y, const float z) { return get_translate_matrix(Vector3(x, y, z)); }
diff --git a/CPU-Software-Renderer/Scene/Camera.cpp b/CPU-Software-Renderer/Scene/Camera.cpp
index 3e2cda1..d373441 100644
--- a/CPU-Software-Renderer/Scene/Camera.cpp
+++ b/CPU-Software-Renderer/Scene/Camera.cpp
@@ -3,6 +3,7 @@
#include "Camera.h"
#include
#include "MathUtil.h"
+#include
namespace Scene
{
@@ -56,4 +57,16 @@ namespace Scene
0, 0, -1, 0
);
}
+
+ Math::Matrix4x4 Camera::get_viewport_matrix(float width, float height) const
+ {
+ using namespace Math;
+
+ return Matrix4x4(
+ (width - 1) / 2, 0, 0, (width - 1) / 2,
+ 0, -(height - 1) / 2, 0, (height - 1) / 2,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1
+ );
+ }
}
\ No newline at end of file
diff --git a/CPU-Software-Renderer/Scene/Camera.h b/CPU-Software-Renderer/Scene/Camera.h
index 9dc5ea5..4939f45 100644
--- a/CPU-Software-Renderer/Scene/Camera.h
+++ b/CPU-Software-Renderer/Scene/Camera.h
@@ -41,5 +41,7 @@ namespace Scene
Math::Matrix4x4 get_orthographic_projection_matrix(float width, float height) const;
Math::Matrix4x4 get_perspective_projection_matrix(float aspectRatio) const;
+
+ Math::Matrix4x4 get_viewport_matrix(float width, float height) const;
};
}
diff --git a/CPU-Software-Renderer/main.cpp b/CPU-Software-Renderer/main.cpp
index 40b32c4..ef66813 100644
--- a/CPU-Software-Renderer/main.cpp
+++ b/CPU-Software-Renderer/main.cpp
@@ -17,6 +17,8 @@
#include "Camera.h"
#include "SDL_events.h"
#include "SDL_keycode.h"
+#include "SDL_timer.h"
+#include
const uint32_t SDL_INIT_FLAGS = SDL_INIT_VIDEO;
const int32_t width = 800;
@@ -128,8 +130,7 @@ struct CubeFace
static ProjectedVertex ProjectToScreen(
const Math::Vector3& vertex,
const Math::Matrix4x4& mvp,
- const int32_t screenWidth,
- const int32_t screenHeight)
+ const Math::Matrix4x4& viewport)
{
using namespace Math;
@@ -149,8 +150,9 @@ static ProjectedVertex ProjectToScreen(
return {};
}
- const float screenX = (ndcX * 0.5f + 0.5f) * static_cast(screenWidth - 1);
- const float screenY = (1.0f - (ndcY * 0.5f + 0.5f)) * static_cast(screenHeight - 1);
+ const Vector4 screen = viewport * Vector4(ndcX, ndcY, ndcZ, 1.0f);
+ const float screenX = screen.x;
+ const float screenY = screen.y;
return { Vector2(screenX, screenY).to_vector2Int(), true };
}
@@ -247,6 +249,7 @@ int main(int argc, char* argv[])
const Math::Matrix4x4 view = camera.get_view_matrix();
const Math::Matrix4x4 modelView = view * model;
const Math::Matrix4x4 projection = camera.get_perspective_projection_matrix(aspectRatio);
+ const Math::Matrix4x4 viewport = camera.get_viewport_matrix(static_cast(width), static_cast(height));
const Math::Matrix4x4 mvp = projection * modelView;
std::array viewSpaceVertices;
@@ -254,7 +257,7 @@ int main(int argc, char* argv[])
for (size_t i = 0; i < cubeVertices.size(); ++i)
{
viewSpaceVertices[i] = (modelView * Math::Vector4::Point(cubeVertices[i])).to_vector3();
- projectedVertices[i] = ProjectToScreen(cubeVertices[i], mvp, width, height);
+ projectedVertices[i] = ProjectToScreen(cubeVertices[i], mvp, viewport);
}
std::array visibleEdges = {};