viewport 视口变换
This commit is contained in:
parent
73c1d3a21d
commit
858c0b4d59
|
|
@ -44,3 +44,4 @@ compile_commands.json
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
SDL2-2.32.10-win32-x64.zip
|
SDL2-2.32.10-win32-x64.zip
|
||||||
SDL2-devel-2.32.10-VC.zip
|
SDL2-devel-2.32.10-VC.zip
|
||||||
|
/.dotnet-home
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -58,24 +58,16 @@
|
||||||
<ImportGroup Label="Shared">
|
<ImportGroup Label="Shared">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
|
|
||||||
Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
|
|
||||||
Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
|
|
||||||
Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props"
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')"
|
|
||||||
Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
|
@ -123,6 +115,7 @@
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
<AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>
|
||||||
$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
$(ProjectDir)Asset;$(ProjectDir)Core;$(ProjectDir)Math;$(ProjectDir)Rasterizer;$(ProjectDir)RenderData;$(ProjectDir)Scene;$(ProjectDir)Shading;$(ProjectDir)libs\SDL2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
|
|
||||||
|
|
@ -72,11 +72,15 @@
|
||||||
<ClCompile Include="Rasterizer\TriangleRasterizer.cpp">
|
<ClCompile Include="Rasterizer\TriangleRasterizer.cpp">
|
||||||
<Filter>源文件\Rasterizer</Filter>
|
<Filter>源文件\Rasterizer</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Scene\Camera.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="TODO.md">
|
<None Include="TODO.md">
|
||||||
<Filter>资源文件</Filter>
|
<Filter>资源文件</Filter>
|
||||||
</None>
|
</None>
|
||||||
|
<None Include="..\README.md" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Core\DepthBuffer.h">
|
<ClInclude Include="Core\DepthBuffer.h">
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ namespace Core
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Row-major layout with y = 0 on the first row, matching a top-left screen origin.
|
||||||
size_t index = static_cast<size_t>(y) * width + x;
|
size_t index = static_cast<size_t>(y) * width + x;
|
||||||
buffer.at(index) = color;
|
buffer.at(index) = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
namespace Math
|
namespace Math
|
||||||
{
|
{
|
||||||
static class MathUtil
|
class MathUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Matrix4x4 get_translate_matrix(const float x, const float y, const float z) { return get_translate_matrix(Vector3(x, y, z)); }
|
static Matrix4x4 get_translate_matrix(const float x, const float y, const float z) { return get_translate_matrix(Vector3(x, y, z)); }
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include <Vector3.h>
|
#include <Vector3.h>
|
||||||
#include "MathUtil.h"
|
#include "MathUtil.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace Scene
|
namespace Scene
|
||||||
{
|
{
|
||||||
|
|
@ -56,4 +57,16 @@ namespace Scene
|
||||||
0, 0, -1, 0
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -41,5 +41,7 @@ namespace Scene
|
||||||
Math::Matrix4x4 get_orthographic_projection_matrix(float width, float height) const;
|
Math::Matrix4x4 get_orthographic_projection_matrix(float width, float height) const;
|
||||||
|
|
||||||
Math::Matrix4x4 get_perspective_projection_matrix(float aspectRatio) const;
|
Math::Matrix4x4 get_perspective_projection_matrix(float aspectRatio) const;
|
||||||
|
|
||||||
|
Math::Matrix4x4 get_viewport_matrix(float width, float height) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "SDL_events.h"
|
#include "SDL_events.h"
|
||||||
#include "SDL_keycode.h"
|
#include "SDL_keycode.h"
|
||||||
|
#include "SDL_timer.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
const uint32_t SDL_INIT_FLAGS = SDL_INIT_VIDEO;
|
const uint32_t SDL_INIT_FLAGS = SDL_INIT_VIDEO;
|
||||||
const int32_t width = 800;
|
const int32_t width = 800;
|
||||||
|
|
@ -128,8 +130,7 @@ struct CubeFace
|
||||||
static ProjectedVertex ProjectToScreen(
|
static ProjectedVertex ProjectToScreen(
|
||||||
const Math::Vector3& vertex,
|
const Math::Vector3& vertex,
|
||||||
const Math::Matrix4x4& mvp,
|
const Math::Matrix4x4& mvp,
|
||||||
const int32_t screenWidth,
|
const Math::Matrix4x4& viewport)
|
||||||
const int32_t screenHeight)
|
|
||||||
{
|
{
|
||||||
using namespace Math;
|
using namespace Math;
|
||||||
|
|
||||||
|
|
@ -149,8 +150,9 @@ static ProjectedVertex ProjectToScreen(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const float screenX = (ndcX * 0.5f + 0.5f) * static_cast<float>(screenWidth - 1);
|
const Vector4 screen = viewport * Vector4(ndcX, ndcY, ndcZ, 1.0f);
|
||||||
const float screenY = (1.0f - (ndcY * 0.5f + 0.5f)) * static_cast<float>(screenHeight - 1);
|
const float screenX = screen.x;
|
||||||
|
const float screenY = screen.y;
|
||||||
|
|
||||||
return { Vector2(screenX, screenY).to_vector2Int(), true };
|
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 view = camera.get_view_matrix();
|
||||||
const Math::Matrix4x4 modelView = view * model;
|
const Math::Matrix4x4 modelView = view * model;
|
||||||
const Math::Matrix4x4 projection = camera.get_perspective_projection_matrix(aspectRatio);
|
const Math::Matrix4x4 projection = camera.get_perspective_projection_matrix(aspectRatio);
|
||||||
|
const Math::Matrix4x4 viewport = camera.get_viewport_matrix(static_cast<float>(width), static_cast<float>(height));
|
||||||
const Math::Matrix4x4 mvp = projection * modelView;
|
const Math::Matrix4x4 mvp = projection * modelView;
|
||||||
|
|
||||||
std::array<Math::Vector3, 8> viewSpaceVertices;
|
std::array<Math::Vector3, 8> viewSpaceVertices;
|
||||||
|
|
@ -254,7 +257,7 @@ int main(int argc, char* argv[])
|
||||||
for (size_t i = 0; i < cubeVertices.size(); ++i)
|
for (size_t i = 0; i < cubeVertices.size(); ++i)
|
||||||
{
|
{
|
||||||
viewSpaceVertices[i] = (modelView * Math::Vector4::Point(cubeVertices[i])).to_vector3();
|
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<bool, 12> visibleEdges = {};
|
std::array<bool, 12> visibleEdges = {};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue