viewport 视口变换

This commit is contained in:
SepComet 2026-03-19 14:16:29 +08:00
parent 73c1d3a21d
commit 858c0b4d59
9 changed files with 402 additions and 355 deletions

1
.gitignore vendored
View File

@ -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

30
AGENTS.md Normal file
View File

@ -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.

View File

@ -1,194 +1,187 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32"> <ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>Win32</Platform> <Platform>Win32</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64"> <ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
<ProjectConfiguration Include="Release|x64"> <ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration> <Configuration>Release</Configuration>
<Platform>x64</Platform> <Platform>x64</Platform>
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<VCProjectVersion>18.0</VCProjectVersion> <VCProjectVersion>18.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<ProjectGuid>{937b923d-dd0c-41ae-81eb-af978170b0ca}</ProjectGuid> <ProjectGuid>{937b923d-dd0c-41ae-81eb-af978170b0ca}</ProjectGuid>
<RootNamespace>CPUSoftwareRenderer</RootNamespace> <RootNamespace>CPUSoftwareRenderer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset> <PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset> <PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset> <PlatformToolset>v145</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v145</PlatformToolset> <PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
</ImportGroup> </ImportGroup>
<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')" </ImportGroup>
Label="LocalAppDataPlatform" /> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</ImportGroup> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
Label="LocalAppDataPlatform" /> </ImportGroup>
</ImportGroup> <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" </ImportGroup>
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" <PropertyGroup Label="UserMacros" />
Label="LocalAppDataPlatform" /> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</ImportGroup> <ClCompile>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <WarningLevel>Level3</WarningLevel>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" <SDLCheck>true</SDLCheck>
Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
Label="LocalAppDataPlatform" /> <ConformanceMode>true</ConformanceMode>
</ImportGroup> <LanguageStandard>stdcpp20</LanguageStandard>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<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>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking> <FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions> <IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<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>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<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>
</ClCompile> <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<Link> </ClCompile>
<SubSystem>Console</SubSystem> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <SubSystem>Console</SubSystem>
<AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
</ItemDefinitionGroup> </Link>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> </ItemDefinitionGroup>
<ClCompile> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<WarningLevel>Level3</WarningLevel> <ClCompile>
<FunctionLevelLinking>true</FunctionLevelLinking> <WarningLevel>Level3</WarningLevel>
<IntrinsicFunctions>true</IntrinsicFunctions> <FunctionLevelLinking>true</FunctionLevelLinking>
<SDLCheck>true</SDLCheck> <IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode> <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<LanguageStandard>stdcpp20</LanguageStandard> <ConformanceMode>true</ConformanceMode>
<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>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>SDL2.lib;SDL2main.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(ProjectDir)libs\SDL2\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Asset\ObjLoader.cpp" /> <ClCompile Include="Asset\ObjLoader.cpp" />
<ClCompile Include="Core\DepthBuffer.cpp" /> <ClCompile Include="Core\DepthBuffer.cpp" />
<ClCompile Include="Core\FrameBuffer.cpp" /> <ClCompile Include="Core\FrameBuffer.cpp" />
<ClCompile Include="Core\Renderer.cpp" /> <ClCompile Include="Core\Renderer.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Rasterizer\Rasterizer.cpp" /> <ClCompile Include="Rasterizer\Rasterizer.cpp" />
<ClCompile Include="Rasterizer\TriangleRasterizer.cpp" /> <ClCompile Include="Rasterizer\TriangleRasterizer.cpp" />
<ClCompile Include="Scene\Camera.cpp" /> <ClCompile Include="Scene\Camera.cpp" />
<ClCompile Include="Shading\BlinnPhongShader.cpp" /> <ClCompile Include="Shading\BlinnPhongShader.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.md" /> <None Include="..\README.md" />
<None Include="TODO.md" /> <None Include="TODO.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Asset\ObjLoader.h" /> <ClInclude Include="Asset\ObjLoader.h" />
<ClInclude Include="Core\DepthBuffer.h" /> <ClInclude Include="Core\DepthBuffer.h" />
<ClInclude Include="Core\FrameBuffer.h" /> <ClInclude Include="Core\FrameBuffer.h" />
<ClInclude Include="Core\Renderer.h" /> <ClInclude Include="Core\Renderer.h" />
<ClInclude Include="Math\MathUtil.h" /> <ClInclude Include="Math\MathUtil.h" />
<ClInclude Include="Math\Matrix4x4.h" /> <ClInclude Include="Math\Matrix4x4.h" />
<ClInclude Include="Math\Vector2.h" /> <ClInclude Include="Math\Vector2.h" />
<ClInclude Include="Math\Vector3.h" /> <ClInclude Include="Math\Vector3.h" />
<ClInclude Include="Math\Vector4.h" /> <ClInclude Include="Math\Vector4.h" />
<ClInclude Include="Rasterizer\Rasterizer.h" /> <ClInclude Include="Rasterizer\Rasterizer.h" />
<ClInclude Include="Rasterizer\TriangleRasterizer.h" /> <ClInclude Include="Rasterizer\TriangleRasterizer.h" />
<ClInclude Include="RenderData\BoundingBox.h" /> <ClInclude Include="RenderData\BoundingBox.h" />
<ClInclude Include="RenderData\Color.h" /> <ClInclude Include="RenderData\Color.h" />
<ClInclude Include="RenderData\Triangle.h" /> <ClInclude Include="RenderData\Triangle.h" />
<ClInclude Include="Scene\Camera.h" /> <ClInclude Include="Scene\Camera.h" />
<ClInclude Include="Scene\Mesh.h" /> <ClInclude Include="Scene\Mesh.h" />
<ClInclude Include="Scene\Model.h" /> <ClInclude Include="Scene\Model.h" />
<ClInclude Include="Scene\Transform.h" /> <ClInclude Include="Scene\Transform.h" />
<ClInclude Include="Scene\Vertex.h" /> <ClInclude Include="Scene\Vertex.h" />
<ClInclude Include="Shading\BlinnPhongShader.h" /> <ClInclude Include="Shading\BlinnPhongShader.h" />
<ClInclude Include="Shading\ShaderTypes.h" /> <ClInclude Include="Shading\ShaderTypes.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
</Project> </Project>

View File

@ -1,146 +1,150 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="源文件"> <Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter> </Filter>
<Filter Include="头文件"> <Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter> </Filter>
<Filter Include="资源文件"> <Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter> </Filter>
<Filter Include="头文件\Core"> <Filter Include="头文件\Core">
<UniqueIdentifier>{e546c002-17ba-4911-9a70-a1cf7ce337fd}</UniqueIdentifier> <UniqueIdentifier>{e546c002-17ba-4911-9a70-a1cf7ce337fd}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="头文件\Math"> <Filter Include="头文件\Math">
<UniqueIdentifier>{b92096d9-3d39-4064-b9a2-efa279ad0775}</UniqueIdentifier> <UniqueIdentifier>{b92096d9-3d39-4064-b9a2-efa279ad0775}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="头文件\Scene"> <Filter Include="头文件\Scene">
<UniqueIdentifier>{7b6f5c6b-60bb-46f2-925b-65346e4d8c4b}</UniqueIdentifier> <UniqueIdentifier>{7b6f5c6b-60bb-46f2-925b-65346e4d8c4b}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="头文件\Shading"> <Filter Include="头文件\Shading">
<UniqueIdentifier>{1aa3c6ac-a580-480c-a2fe-2d57c98693ff}</UniqueIdentifier> <UniqueIdentifier>{1aa3c6ac-a580-480c-a2fe-2d57c98693ff}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="头文件\Rasterizer"> <Filter Include="头文件\Rasterizer">
<UniqueIdentifier>{a7d67eb7-b4bc-4b5a-86f2-e80bcd1518d5}</UniqueIdentifier> <UniqueIdentifier>{a7d67eb7-b4bc-4b5a-86f2-e80bcd1518d5}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="头文件\Asset"> <Filter Include="头文件\Asset">
<UniqueIdentifier>{55224e49-7917-4fee-9a61-f1c14ebf8d5e}</UniqueIdentifier> <UniqueIdentifier>{55224e49-7917-4fee-9a61-f1c14ebf8d5e}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="源文件\Core"> <Filter Include="源文件\Core">
<UniqueIdentifier>{6eda961b-ec6a-4670-b093-be46b27fdeb7}</UniqueIdentifier> <UniqueIdentifier>{6eda961b-ec6a-4670-b093-be46b27fdeb7}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="源文件\Asset"> <Filter Include="源文件\Asset">
<UniqueIdentifier>{4345cc0e-3d61-4dd9-b37f-4b42c30aa8d3}</UniqueIdentifier> <UniqueIdentifier>{4345cc0e-3d61-4dd9-b37f-4b42c30aa8d3}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="源文件\Rasterizer"> <Filter Include="源文件\Rasterizer">
<UniqueIdentifier>{4b52509e-dde8-45e0-aeb3-d18131b94265}</UniqueIdentifier> <UniqueIdentifier>{4b52509e-dde8-45e0-aeb3-d18131b94265}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="源文件\Shading"> <Filter Include="源文件\Shading">
<UniqueIdentifier>{1644176d-c2fe-404b-9f42-45eb0bc85222}</UniqueIdentifier> <UniqueIdentifier>{1644176d-c2fe-404b-9f42-45eb0bc85222}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="头文件\RenderData"> <Filter Include="头文件\RenderData">
<UniqueIdentifier>{c77ae566-281a-4d76-80bd-41496deb0aeb}</UniqueIdentifier> <UniqueIdentifier>{c77ae566-281a-4d76-80bd-41496deb0aeb}</UniqueIdentifier>
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">
<Filter>源文件</Filter> <Filter>源文件</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Core\DepthBuffer.cpp"> <ClCompile Include="Core\DepthBuffer.cpp">
<Filter>源文件\Core</Filter> <Filter>源文件\Core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Core\FrameBuffer.cpp"> <ClCompile Include="Core\FrameBuffer.cpp">
<Filter>源文件\Core</Filter> <Filter>源文件\Core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Core\Renderer.cpp"> <ClCompile Include="Core\Renderer.cpp">
<Filter>源文件\Core</Filter> <Filter>源文件\Core</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Asset\ObjLoader.cpp"> <ClCompile Include="Asset\ObjLoader.cpp">
<Filter>源文件\Asset</Filter> <Filter>源文件\Asset</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Shading\BlinnPhongShader.cpp"> <ClCompile Include="Shading\BlinnPhongShader.cpp">
<Filter>源文件\Shading</Filter> <Filter>源文件\Shading</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Rasterizer\Rasterizer.cpp"> <ClCompile Include="Rasterizer\Rasterizer.cpp">
<Filter>源文件\Rasterizer</Filter> <Filter>源文件\Rasterizer</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Rasterizer\TriangleRasterizer.cpp"> <ClCompile Include="Rasterizer\TriangleRasterizer.cpp">
<Filter>源文件\Rasterizer</Filter> <Filter>源文件\Rasterizer</Filter>
</ClCompile> </ClCompile>
</ItemGroup> <ClCompile Include="Scene\Camera.cpp">
<ItemGroup> <Filter>源文件</Filter>
<None Include="TODO.md"> </ClCompile>
<Filter>资源文件</Filter> </ItemGroup>
</None> <ItemGroup>
</ItemGroup> <None Include="TODO.md">
<ItemGroup> <Filter>资源文件</Filter>
<ClInclude Include="Core\DepthBuffer.h"> </None>
<Filter>头文件\Core</Filter> <None Include="..\README.md" />
</ClInclude> </ItemGroup>
<ClInclude Include="Core\FrameBuffer.h"> <ItemGroup>
<Filter>头文件\Core</Filter> <ClInclude Include="Core\DepthBuffer.h">
</ClInclude> <Filter>头文件\Core</Filter>
<ClInclude Include="Core\Renderer.h"> </ClInclude>
<Filter>头文件\Core</Filter> <ClInclude Include="Core\FrameBuffer.h">
</ClInclude> <Filter>头文件\Core</Filter>
<ClInclude Include="Math\MathUtil.h"> </ClInclude>
<Filter>头文件\Math</Filter> <ClInclude Include="Core\Renderer.h">
</ClInclude> <Filter>头文件\Core</Filter>
<ClInclude Include="Math\Matrix4x4.h"> </ClInclude>
<Filter>头文件\Math</Filter> <ClInclude Include="Math\MathUtil.h">
</ClInclude> <Filter>头文件\Math</Filter>
<ClInclude Include="Math\Vector2.h"> </ClInclude>
<Filter>头文件\Math</Filter> <ClInclude Include="Math\Matrix4x4.h">
</ClInclude> <Filter>头文件\Math</Filter>
<ClInclude Include="Math\Vector3.h"> </ClInclude>
<Filter>头文件\Math</Filter> <ClInclude Include="Math\Vector2.h">
</ClInclude> <Filter>头文件\Math</Filter>
<ClInclude Include="Math\Vector4.h"> </ClInclude>
<Filter>头文件\Math</Filter> <ClInclude Include="Math\Vector3.h">
</ClInclude> <Filter>头文件\Math</Filter>
<ClInclude Include="Scene\Camera.h"> </ClInclude>
<Filter>头文件\Scene</Filter> <ClInclude Include="Math\Vector4.h">
</ClInclude> <Filter>头文件\Math</Filter>
<ClInclude Include="Scene\Mesh.h"> </ClInclude>
<Filter>头文件\Scene</Filter> <ClInclude Include="Scene\Camera.h">
</ClInclude> <Filter>头文件\Scene</Filter>
<ClInclude Include="Scene\Model.h"> </ClInclude>
<Filter>头文件\Scene</Filter> <ClInclude Include="Scene\Mesh.h">
</ClInclude> <Filter>头文件\Scene</Filter>
<ClInclude Include="Scene\Transform.h"> </ClInclude>
<Filter>头文件\Scene</Filter> <ClInclude Include="Scene\Model.h">
</ClInclude> <Filter>头文件\Scene</Filter>
<ClInclude Include="Scene\Vertex.h"> </ClInclude>
<Filter>头文件\Scene</Filter> <ClInclude Include="Scene\Transform.h">
</ClInclude> <Filter>头文件\Scene</Filter>
<ClInclude Include="Shading\BlinnPhongShader.h"> </ClInclude>
<Filter>头文件\Shading</Filter> <ClInclude Include="Scene\Vertex.h">
</ClInclude> <Filter>头文件\Scene</Filter>
<ClInclude Include="Shading\ShaderTypes.h"> </ClInclude>
<Filter>头文件\Shading</Filter> <ClInclude Include="Shading\BlinnPhongShader.h">
</ClInclude> <Filter>头文件\Shading</Filter>
<ClInclude Include="Rasterizer\Rasterizer.h"> </ClInclude>
<Filter>头文件\Rasterizer</Filter> <ClInclude Include="Shading\ShaderTypes.h">
</ClInclude> <Filter>头文件\Shading</Filter>
<ClInclude Include="Rasterizer\TriangleRasterizer.h"> </ClInclude>
<Filter>头文件\Rasterizer</Filter> <ClInclude Include="Rasterizer\Rasterizer.h">
</ClInclude> <Filter>头文件\Rasterizer</Filter>
<ClInclude Include="Asset\ObjLoader.h"> </ClInclude>
<Filter>头文件\Asset</Filter> <ClInclude Include="Rasterizer\TriangleRasterizer.h">
</ClInclude> <Filter>头文件\Rasterizer</Filter>
<ClInclude Include="RenderData\Triangle.h"> </ClInclude>
<Filter>头文件\RenderData</Filter> <ClInclude Include="Asset\ObjLoader.h">
</ClInclude> <Filter>头文件\Asset</Filter>
<ClInclude Include="RenderData\Color.h"> </ClInclude>
<Filter>头文件\RenderData</Filter> <ClInclude Include="RenderData\Triangle.h">
</ClInclude> <Filter>头文件\RenderData</Filter>
<ClInclude Include="RenderData\BoundingBox.h"> </ClInclude>
<Filter>头文件\RenderData</Filter> <ClInclude Include="RenderData\Color.h">
</ClInclude> <Filter>头文件\RenderData</Filter>
</ItemGroup> </ClInclude>
<ClInclude Include="RenderData\BoundingBox.h">
<Filter>头文件\RenderData</Filter>
</ClInclude>
</ItemGroup>
</Project> </Project>

View File

@ -1,24 +1,25 @@
#include "FrameBuffer.h" #include "FrameBuffer.h"
#include <cstdint> #include <cstdint>
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
using namespace Math; using namespace Math;
namespace Core namespace Core
{ {
void FrameBuffer::clear(const uint32_t color) void FrameBuffer::clear(const uint32_t color)
{ {
std::fill(buffer.begin(), buffer.end(), color); std::fill(buffer.begin(), buffer.end(), color);
} }
void FrameBuffer::set_pixel(const int32_t x, const int32_t y, const uint32_t 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) if (x < 0 || x >= width || y < 0 || y >= height)
{ {
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;
} }
} }

View File

@ -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)); }

View File

@ -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
);
}
} }

View File

@ -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;
}; };
} }

View File

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