Skip to content

Commit 0e8d34a

Browse files
author
Floyd Huizinga
committed
finish up "Setting up 3D Rendering"
1 parent 3829810 commit 0e8d34a

35 files changed

+1152
-1996
lines changed

docs/1-introduction/1-3-basics/1-3-3-setting-up-3d-rendering.md

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
# Setting up 3D Rendering
22

3+
Now that we know how to work with simple predefined 2D geometry, it's time to take the next step.
4+
5+
Here we're dive into the 3rd dimension, but before we do that, we need to explain some things we're going to need in order to properly display a 3D object.
6+
7+
In this chapter we'll talk about the following items:
8+
9+
- Math ( The matrix compositions we need to get from 3D to our screen (2D) )
10+
- Constant Buffers
11+
312
Even though the API is called "Direct 3D 11" weirdly enough we can't just simply render a bunch of vertices and have it show up as we expect it to look.
413
Because our screen is 2D, we need to be able to "transform" our 3D model into a 2D space.
514

15+
## The Math
16+
617
For this we'll need to take a light dive into "Matrix Math", whilst understanding the math behind it all can be really helpful (especially once you start doing more advanced stuff), We'll use a library for all of this and only stick to top-level concepts as not to make this tutorial a math-lesson.
718

819
The "Transformation" we're concerned with is composed out of a set of multiple matrices:
@@ -33,6 +44,27 @@ Multiplying these two matrices together results in our "ViewProjection matrix" o
3344
Now that we have our Model matrix and ViewProjection we can make our final matrix, the "world matrix" which we get by multiplying them together: `WorldMatrix = ModelMatrix * ViewProjection`
3445
This matrix is what we transform every vertex with in order to get our 3D object on our 2D screen.
3546

47+
The code to do all of this looks like this:
48+
49+
Our camera will be defined by the view and projection matrix:
50+
XMVECTOR camPos = XMLoadFloat3(&_cameraPosition);
51+
52+
XMMATRIX view = XMMatrixLookAtLH(camPos, g_XMZero, { 0,1,0,1 });
53+
XMMATRIX proj = XMMatrixPerspectiveFovLH(90.0f * 0.0174533f, //degrees to radians
54+
static_cast<float>(_width) / static_cast<float>(_height),
55+
0.1f,
56+
100.0f);
57+
//combine the view & proj matrix
58+
XMMATRIX viewProjection = XMMatrixMultiply(view, proj);
59+
60+
And our 3D object will use the resulting model matrix:
61+
XMMATRIX translation = XMMatrixTranslation(0, 0, 0);
62+
XMMATRIX scaling = XMMatrixScaling(_scale, _scale, _scale);
63+
XMMATRIX rotation = XMMatrixRotationRollPitchYaw(0, _yRotation, 0);
64+
65+
//Now we create our model matrix
66+
XMMATRIX modelMatrix = XMMatrixMultiply(translation, XMMatrixMultiply(scaling, rotation));
67+
3668
Because all these main matrix multiplications happen infrequently enough, we "can" do this on the CPU, we only have to recalculate the matrices of 3D objects when/if they move/scale/rotate which for most level geometry is almost never. However...
3769

3870
The only exception is the camera, which tends to move almost every frame, however we tend to only have 1 of them (or an insignificant amount in other cases).
@@ -41,17 +73,84 @@ The keen readers might realize that because of the the fact that we recalculate
4173
What we cannot do however (or well, not with high-poly objects) is transform every vertex on the CPU with the world matrix, luckily GPU's are practically built for this and thus are very good at it.
4274
But that means we need a way to get the matrix we need over there somehow.
4375

76+
## Constant Buffers
77+
4478
In D3D11 we have a thing called "Constant Buffers", this is special buffer to contain values that the GPU can expect not to change during a draw call, this means the values are "constant" or "uniform" for the entire shader invocation.
4579
This is a great place to put our matrix.
4680

47-
!!! error
48-
explain and create Constant Buffers
81+
In `CreateConstantBuffers()` we create our buffer pretty much the same as we did our vertex buffer back in Hello Triangle, except now in the BindFlags, we specify D3D11_BIND_FLAG::BIND_CONSTANT_BUFFER
82+
83+
D3D11_BUFFER_DESC desc{};
84+
desc.Usage = D3D11_USAGE::D3D11_USAGE_DYNAMIC;
85+
desc.BindFlags = D3D11_BIND_FLAG::D3D11_BIND_CONSTANT_BUFFER;
86+
desc.ByteWidth = sizeof(PerFrameConstantBuffer);
87+
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
88+
89+
_device->CreateBuffer(&desc, nullptr, &_perFrameConstantBuffer);
90+
91+
desc.ByteWidth = sizeof(PerObjectConstantBuffer);
92+
_device->CreateBuffer(&desc, nullptr, &_perObjectConstantBuffer);
93+
94+
Note that we create two buffers, this is because it is best practice to update constant buffers as little as possible.
95+
96+
So we have one that we adjust every frame, and one that we 'ideally' never have to update (or very little), an example of this could be static geometry as it'll still need a model matrix but we never have to update it after initial creation.
97+
98+
In `Update()` we will update the contents of our constantbuffers :
99+
100+
D3D11_MAPPED_SUBRESOURCE mappedResource;
101+
_deviceContext->Map(_perFrameConstantBuffer.Get(), 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
102+
memcpy(mappedResource.pData, &_perFrameConstantBufferData, sizeof(PerFrameConstantBuffer));
103+
_deviceContext->Unmap(_perFrameConstantBuffer.Get(), 0);
104+
105+
_deviceContext->Map(_perObjectConstantBuffer.Get(), 0, D3D11_MAP::D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
106+
memcpy(mappedResource.pData, &_perObjectConstantBufferData, sizeof(PerObjectConstantBuffer));
107+
_deviceContext->Unmap(_perObjectConstantBuffer.Get(), 0);
108+
109+
These functions will take the data in our "...ConstantBufferData" members and upload it to the GPU.
110+
111+
The last thing we need to do is make our vertex shader aware of these buffers, easily done by calling ID3D11DeviceContext::VSSetConstantBuffers, note that we can set both slots at once by doing the following:
112+
113+
ID3D11Buffer* constantBuffers[2] =
114+
{
115+
_perFrameConstantBuffer.Get(),
116+
_perObjectConstantBuffer.Get()
117+
};
118+
119+
_deviceContext->VSSetConstantBuffers(0, 2, constantBuffers);
49120

50-
!!! error
51-
add to shader, do vertex multiplication with worldmatrix (or model \* camera) there.
121+
That's all we need to do in order to get some data usable on the GPU, finally we now just need to have our vertex shader aware of this data and apply it.
122+
123+
The syntax for this is a little bit different than we're used to in C/C++ but simple enough:
124+
125+
cbuffer PerFrame : register(b0)
126+
{
127+
row_major matrix viewprojection;
128+
};
129+
130+
cbuffer PerObject : register(b1)
131+
{
132+
row_major matrix modelmatrix;
133+
};
134+
135+
We basically declare and define our structure in a single line, `cbuffer` tells the shader it will be a Constant Buffer (and expect the structure like layout), followed by the name of the object `PerFrame`/`PerObject` and lastly which slot to expect it on `: register(b0)`
136+
after that we just tell it to expect a single row_major matrix in both buffers.
137+
138+
Now we're free to use the data in the shader.
139+
140+
matrix world = mul(modelmatrix, viewprojection);
141+
142+
First we get our World Matrix by multiplying the model matrix with the viewproject as we noted before, then all that's left is to transform every vertex we get as an input and output that.
143+
144+
output.Position = mul(world, float4(input.Position, 1.0));
145+
146+
That's all we need to do in order to get our 3D object onto the screen!
147+
148+
![](../../images/1-3-3-worldspacetriangle.png)
149+
150+
However since it's still a single triangle, it won't be very obvious if it were static, so in `Update()` we're actually rotating it around by increasing the rotation we have every frame:
151+
_yRotation += _deltaTime;
52152

53-
!!! error
54-
end up with triangle in 3D space before we move on to next chapter
55153

154+
Next up, we'll get a nice cube going!
56155

57156
[Next chapter](./1-3-4-3d-rendering.md)
37.5 KB
Loading
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Label="ProjectConfigurations">
4+
<ProjectConfiguration Include="Debug|x64">
5+
<Configuration>Debug</Configuration>
6+
<Platform>x64</Platform>
7+
</ProjectConfiguration>
8+
<ProjectConfiguration Include="Release|x64">
9+
<Configuration>Release</Configuration>
10+
<Platform>x64</Platform>
11+
</ProjectConfiguration>
12+
</ItemGroup>
13+
<PropertyGroup Label="Globals">
14+
<VCProjectVersion>16.0</VCProjectVersion>
15+
<Keyword>Win32Proj</Keyword>
16+
<ProjectGuid>{D8B6DA57-19B7-44B2-9C23-C0BD37277060}</ProjectGuid>
17+
<RootNamespace>My13HelloTriangle</RootNamespace>
18+
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
19+
</PropertyGroup>
20+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
21+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
22+
<ConfigurationType>Application</ConfigurationType>
23+
<UseDebugLibraries>true</UseDebugLibraries>
24+
<PlatformToolset>v143</PlatformToolset>
25+
<CharacterSet>Unicode</CharacterSet>
26+
</PropertyGroup>
27+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
28+
<ConfigurationType>Application</ConfigurationType>
29+
<UseDebugLibraries>false</UseDebugLibraries>
30+
<PlatformToolset>v143</PlatformToolset>
31+
<WholeProgramOptimization>true</WholeProgramOptimization>
32+
<CharacterSet>Unicode</CharacterSet>
33+
</PropertyGroup>
34+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
35+
<ImportGroup Label="ExtensionSettings">
36+
</ImportGroup>
37+
<ImportGroup Label="Shared">
38+
</ImportGroup>
39+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
40+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
41+
</ImportGroup>
42+
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
43+
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
44+
</ImportGroup>
45+
<PropertyGroup Label="UserMacros" />
46+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
47+
<LinkIncremental>true</LinkIncremental>
48+
<OutDir>bin\$(Configuration)\</OutDir>
49+
<IntDir>obj\$(Configuration)\</IntDir>
50+
<IncludePath>$(SolutionDir)..\lib\glfw-3.3.6\include\;$(SolutionDir)..\lib\FreeImage\include\;$(SolutionDir)..\lib\DirectXTex\include\;$(SolutionDir)Cpp\Framework\;</IncludePath>
51+
<LibraryPath>$(SolutionDir)..\lib\glfw-3.3.6\lib-vc2022\;$(SolutionDir)..\lib\DirectXTex\lib\$(Configuration)\;$(SolutionDir)..\lib\FreeImage\lib\;$(LibraryPath);$(SolutionDir)Cpp\Framework\lib\$(Configuration)\;</LibraryPath>
52+
</PropertyGroup>
53+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
54+
<LinkIncremental>false</LinkIncremental>
55+
<OutDir>bin\$(Configuration)\</OutDir>
56+
<IntDir>obj\$(Configuration)\</IntDir>
57+
<IncludePath>$(SolutionDir)..\lib\glfw-3.3.6\include\;$(SolutionDir)..\lib\FreeImage\include\;$(SolutionDir)..\lib\DirectXTex\include\;$(SolutionDir)Cpp\Framework\;</IncludePath>
58+
<LibraryPath>$(SolutionDir)..\lib\glfw-3.3.6\lib-vc2022\;$(SolutionDir)..\lib\DirectXTex\lib\$(Configuration)\;$(SolutionDir)..\lib\FreeImage\lib\;$(LibraryPath);$(SolutionDir)Cpp\Framework\lib\$(Configuration)\</LibraryPath>
59+
</PropertyGroup>
60+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
61+
<ClCompile>
62+
<WarningLevel>Level3</WarningLevel>
63+
<SDLCheck>true</SDLCheck>
64+
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
65+
<ConformanceMode>true</ConformanceMode>
66+
<LanguageStandard>stdcpp17</LanguageStandard>
67+
<AdditionalOptions>/D FREEIMAGE_LIB %(AdditionalOptions)</AdditionalOptions>
68+
</ClCompile>
69+
<Link>
70+
<SubSystem>Console</SubSystem>
71+
<GenerateDebugInformation>true</GenerateDebugInformation>
72+
<AdditionalDependencies>Framework.lib;DirectXTex.lib;glfw3.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
73+
<IgnoreSpecificDefaultLibraries>msvcrt</IgnoreSpecificDefaultLibraries>
74+
</Link>
75+
<PostBuildEvent>
76+
<Command>mkdir $(OutDir)Assets\Models\
77+
mkdir $(OutDir)Assets\Shaders\
78+
mkdir $(OutDir)Assets\Textures\
79+
xcopy /Y $(ProjectDir)Assets\Models\*.* $(OutDir)\Assets\Models\
80+
xcopy /Y $(ProjectDir)Assets\Shaders\*.* $(OutDir)Assets\Shaders\
81+
xcopy /Y $(ProjectDir)Assets\Textures\*.* $(OutDir)Assets\Textures\</Command>
82+
</PostBuildEvent>
83+
</ItemDefinitionGroup>
84+
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
85+
<ClCompile>
86+
<WarningLevel>Level3</WarningLevel>
87+
<FunctionLevelLinking>true</FunctionLevelLinking>
88+
<IntrinsicFunctions>true</IntrinsicFunctions>
89+
<SDLCheck>true</SDLCheck>
90+
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
91+
<ConformanceMode>true</ConformanceMode>
92+
<LanguageStandard>stdcpp17</LanguageStandard>
93+
</ClCompile>
94+
<Link>
95+
<SubSystem>Console</SubSystem>
96+
<EnableCOMDATFolding>true</EnableCOMDATFolding>
97+
<OptimizeReferences>true</OptimizeReferences>
98+
<AdditionalDependencies>Framework.lib;DirectXTex.lib;glfw3.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
99+
<AdditionalOptions>/verbose:lib</AdditionalOptions>
100+
</Link>
101+
<PostBuildEvent>
102+
<Command>xcopy /Y $(SolutionDir)..\lib\assimp\lib\assimp.dll $(OutDir)
103+
mkdir $(OutDir)Assets\Models\
104+
mkdir $(OutDir)Assets\Shaders\
105+
mkdir $(OutDir)Assets\Textures\
106+
xcopy /Y $(ProjectDir)Assets\Models\*.* $(OutDir)\Assets\Models\
107+
xcopy /Y $(ProjectDir)Assets\Shaders\*.* $(OutDir)Assets\Shaders\
108+
xcopy /Y $(ProjectDir)Assets\Textures\*.* $(OutDir)Assets\Textures\</Command>
109+
</PostBuildEvent>
110+
</ItemDefinitionGroup>
111+
<ItemGroup>
112+
<None Include="Assets\Shaders\Main.ps.hlsl">
113+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
114+
<FileType>Document</FileType>
115+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
116+
</None>
117+
<None Include="Assets\Shaders\Main.vs.hlsl">
118+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
119+
<FileType>Document</FileType>
120+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
121+
</None>
122+
</ItemGroup>
123+
<ItemGroup>
124+
<ClInclude Include="Definitions.hpp" />
125+
<ClInclude Include="ShaderCollection.hpp" />
126+
<ClInclude Include="ResourceDescriptor.hpp" />
127+
<ClInclude Include="Setting3DApplication.hpp" />
128+
<ClInclude Include="VertexType.hpp" />
129+
</ItemGroup>
130+
<ItemGroup>
131+
<ClCompile Include="Main.cpp" />
132+
<ClCompile Include="ShaderCollection.cpp" />
133+
<ClCompile Include="Setting3DApplication.cpp" />
134+
</ItemGroup>
135+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
136+
<ImportGroup Label="ExtensionTargets">
137+
</ImportGroup>
138+
</Project>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup>
4+
<Filter Include="Source Files">
5+
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
6+
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
7+
</Filter>
8+
<Filter Include="Header Files">
9+
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10+
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
11+
</Filter>
12+
<Filter Include="Resource Files">
13+
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14+
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
15+
</Filter>
16+
</ItemGroup>
17+
<ItemGroup>
18+
<None Include="Assets\Shaders\Main.ps.hlsl" />
19+
<None Include="Assets\Shaders\Main.vs.hlsl" />
20+
</ItemGroup>
21+
<ItemGroup>
22+
<ClInclude Include="Definitions.hpp">
23+
<Filter>Header Files</Filter>
24+
</ClInclude>
25+
<ClInclude Include="ShaderCollection.hpp">
26+
<Filter>Header Files</Filter>
27+
</ClInclude>
28+
<ClInclude Include="ResourceDescriptor.hpp">
29+
<Filter>Header Files</Filter>
30+
</ClInclude>
31+
<ClInclude Include="Setting3DApplication.hpp">
32+
<Filter>Header Files</Filter>
33+
</ClInclude>
34+
<ClInclude Include="VertexType.hpp">
35+
<Filter>Header Files</Filter>
36+
</ClInclude>
37+
</ItemGroup>
38+
<ItemGroup>
39+
<ClCompile Include="Main.cpp">
40+
<Filter>Source Files</Filter>
41+
</ClCompile>
42+
<ClCompile Include="ShaderCollection.cpp">
43+
<Filter>Source Files</Filter>
44+
</ClCompile>
45+
<ClCompile Include="Setting3DApplication.cpp">
46+
<Filter>Source Files</Filter>
47+
</ClCompile>
48+
</ItemGroup>
49+
</Project>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<ShowAllFiles>true</ShowAllFiles>
5+
</PropertyGroup>
6+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
7+
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
8+
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
9+
</PropertyGroup>
10+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
11+
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
12+
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
13+
</PropertyGroup>
14+
</Project>

0 commit comments

Comments
 (0)