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 = {};