Skip to content

Commit ece810d

Browse files
author
Floyd Huizinga
committed
Start of "3D Rendering" chapter
1 parent 4ed8145 commit ece810d

File tree

5 files changed

+33
-222
lines changed

5 files changed

+33
-222
lines changed

docs/1-introduction/1-3-basics/1-3-4-3d-rendering.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
# 3D Rendering
22

3-
!!! error
4-
render a cube, without depth buffer/state
3+
Coming from the previous chapter, two changes have been made, instead of a single triangle, we've added a list of vertices and indices in order to create a cube mesh, and to make things more clear, we're relying on colors instead of a texture for now.
54

6-
!!! error
7-
explain the 'broken' cube / missing depth buffer,
5+
Without any other changes to our main code, our cube will show up in 3D just as it did with our triangle, quite easy huh!
6+
7+
![](../../images/1-3-4-insidecube.png)
8+
9+
But something seems wrong, our triangle didn't look so weird, why are we looking inside the cube and seeing the other side sometimes?
10+
11+
Well, we're still missing one critical part in order to get 3D rendering to work properly.
12+
13+
## The Depth Buffer
14+
15+
In order to fix our weird looking cube we'll need a depth buffer, this is a special kind of render target that keeps track of the "depth" of each fragment on the screen, basically saying "how far away is this pixel on the screen".
16+
This depth buffer can then be used by special hardware on the GPU to see if the fragment we're working on is behind or in front of the previous fragment.
17+
18+
This is called "Depth Testing", a very important concept within common rendering.
819

920
!!! error
1021
add depth buffer + state
51.9 KB
Loading

src/Cpp/1-getting-started/1-3-4-3DRendering/1-3-4-3DRendering.vcxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
6565
<ConformanceMode>true</ConformanceMode>
6666
<LanguageStandard>stdcpp17</LanguageStandard>
67-
<AdditionalOptions>/D FREEIMAGE_LIB %(AdditionalOptions)</AdditionalOptions>
6867
</ClCompile>
6968
<Link>
7069
<SubSystem>Console</SubSystem>
@@ -91,7 +90,6 @@ xcopy /Y $(ProjectDir)Assets\Textures\*.* $(OutDir)Assets\Textures\</Command>
9190
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
9291
<ConformanceMode>true</ConformanceMode>
9392
<LanguageStandard>stdcpp17</LanguageStandard>
94-
<AdditionalOptions>/D FREEIMAGE_LIB %(AdditionalOptions)</AdditionalOptions>
9593
</ClCompile>
9694
<Link>
9795
<SubSystem>Console</SubSystem>

src/Cpp/1-getting-started/1-3-4-3DRendering/3DRenderingApplication.cpp

Lines changed: 17 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@
99
#include <DirectXMath.h>
1010
#include <d3dcompiler.h>
1111

12-
#include <DirectXTex.h>
13-
#include <FreeImage.h>
14-
1512
#include <iostream>
1613

1714
#pragma comment(lib, "d3d11.lib")
@@ -20,11 +17,6 @@
2017
#pragma comment(lib, "winmm.lib")
2118
#pragma comment(lib, "dxguid.lib")
2219

23-
#if defined(_DEBUG)
24-
#pragma comment(lib, "FreeImageLibd.lib")
25-
#else
26-
#pragma comment(lib, "FreeImageLib.lib")
27-
#endif
2820

2921
template <UINT TDebugNameLength>
3022
inline void SetDebugName(_In_ ID3D11DeviceChild* deviceResource, _In_z_ const char(&debugName)[TDebugNameLength])
@@ -135,168 +127,9 @@ bool Rendering3DApplication::Initialize()
135127
CreateSwapchainResources();
136128

137129
CreateConstantBuffers();
138-
139-
FreeImage_Initialise();
140130
return true;
141131
}
142132

143-
WRL::ComPtr<ID3D11ShaderResourceView> CreateTextureViewFromDDS(ID3D11Device* device, const std::wstring& pathToDDS)
144-
{
145-
DirectX::TexMetadata metaData = {};
146-
DirectX::ScratchImage scratchImage;
147-
if (FAILED(DirectX::LoadFromDDSFile(pathToDDS.c_str(), DirectX::DDS_FLAGS_NONE, &metaData, scratchImage)))
148-
{
149-
std::cout << "DXTEX: Failed to load image\n";
150-
return nullptr;
151-
}
152-
153-
WRL::ComPtr<ID3D11Resource> texture = nullptr;
154-
if (FAILED(DirectX::CreateTexture(
155-
device,
156-
scratchImage.GetImages(),
157-
scratchImage.GetImageCount(),
158-
metaData,
159-
&texture)))
160-
{
161-
std::cout << "DXTEX: Failed to create texture out of image\n";
162-
scratchImage.Release();
163-
return nullptr;
164-
}
165-
166-
ID3D11ShaderResourceView* srv = nullptr;
167-
168-
if (FAILED(DirectX::CreateShaderResourceView(
169-
device,
170-
scratchImage.GetImages(),
171-
scratchImage.GetImageCount(),
172-
metaData,
173-
&srv)))
174-
{
175-
std::cout << "DXTEX: Failed to create shader resource view out of texture\n";
176-
scratchImage.Release();
177-
return nullptr;
178-
}
179-
180-
return srv;
181-
}
182-
183-
184-
WRL::ComPtr<ID3D11ShaderResourceView> CreateTextureView(ID3D11Device* device, const std::wstring& pathToTexture)
185-
{
186-
FIBITMAP* image = nullptr;
187-
//Win32 methods of opening files is called "CreateFile" counterintuitively, we make sure to tell it to only to read pre-existing files
188-
HANDLE file = CreateFileW(pathToTexture.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, 0);
189-
190-
//If the file didn't exist we'll get an invalid handle
191-
if (file == INVALID_HANDLE_VALUE)
192-
{
193-
return nullptr;
194-
}
195-
196-
size_t fileSize = GetFileSize(file, nullptr);
197-
198-
//We open a new local scope here so we don't keep the vector in memory for the entire function call, we can get rid of the memory it holds earlier this way
199-
{
200-
std::vector<BYTE> fileDataRaw(fileSize);
201-
if (!ReadFile(file, fileDataRaw.data(), fileDataRaw.size(), nullptr, nullptr))
202-
{
203-
CloseHandle(file);
204-
return nullptr;
205-
}
206-
207-
//Close our file handle as we don't need it anymore
208-
CloseHandle(file);
209-
210-
FIMEMORY* memHandle = FreeImage_OpenMemory(fileDataRaw.data(), fileDataRaw.size());
211-
FREE_IMAGE_FORMAT imageFormat = FreeImage_GetFileTypeFromMemory(memHandle);
212-
if (imageFormat == FIF_UNKNOWN)
213-
{
214-
FreeImage_CloseMemory(memHandle);
215-
std::cout << "CreateTextureView: Unsupported texture format from file: '" << pathToTexture.c_str() << "'\n";
216-
return nullptr;
217-
}
218-
image = FreeImage_LoadFromMemory(imageFormat, memHandle);
219-
220-
//We no longer need the original data
221-
FreeImage_CloseMemory(memHandle);
222-
223-
} //ending the local scope cleans up fileDataRaw
224-
225-
//Flip the image vertically so this matches up with what DirectXTex loads
226-
FreeImage_FlipVertical(image);
227-
228-
uint32_t textureWidth = FreeImage_GetWidth(image);
229-
uint32_t textureHeight = FreeImage_GetHeight(image);
230-
uint32_t textureBPP = FreeImage_GetBPP(image);
231-
232-
D3D11_TEXTURE2D_DESC textureDesc = {};
233-
D3D11_SUBRESOURCE_DATA initialData = {};
234-
WRL::ComPtr<ID3D11Texture2D> texture = nullptr;
235-
236-
DXGI_FORMAT textureFormat;
237-
switch (textureBPP)
238-
{
239-
case 8:
240-
textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8_UNORM;
241-
break;
242-
case 16:
243-
textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8G8_UNORM;
244-
break;
245-
case 24:
246-
//D3D11 does not support 24 bit formats for textures, we'll need to convert
247-
{
248-
textureBPP = 32;
249-
FIBITMAP* newImage = FreeImage_ConvertTo32Bits(image);
250-
FreeImage_Unload(image);
251-
image = newImage;
252-
textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM;
253-
}
254-
break;
255-
case 32:
256-
textureFormat = DXGI_FORMAT::DXGI_FORMAT_R8G8B8A8_UNORM;
257-
break;
258-
default:
259-
{
260-
//we could try to handle some weird bitcount, but these will probably be HDR or some antique format, just exit instead..
261-
std::cout << "CreateTextureView: Texture has nontrivial bits per pixel ( " << textureBPP << " ), file: '" << pathToTexture.c_str() << "'\n";
262-
return nullptr;
263-
}
264-
break;
265-
}
266-
textureDesc.Format = textureFormat;
267-
textureDesc.ArraySize = 1;
268-
textureDesc.MipLevels = 1;
269-
textureDesc.Height = textureHeight;
270-
textureDesc.Width = textureWidth;
271-
textureDesc.SampleDesc.Count = 1;
272-
textureDesc.Usage = D3D11_USAGE_IMMUTABLE;
273-
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
274-
275-
//populate initial data
276-
initialData.pSysMem = FreeImage_GetBits(image);
277-
initialData.SysMemPitch = (textureBPP / 8) * textureWidth;
278-
279-
if (FAILED(device->CreateTexture2D(&textureDesc, &initialData, texture.GetAddressOf())))
280-
{
281-
FreeImage_Unload(image);
282-
return nullptr;
283-
}
284-
FreeImage_Unload(image);
285-
286-
ID3D11ShaderResourceView* srv = nullptr;
287-
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
288-
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
289-
srvDesc.Format = textureDesc.Format;
290-
srvDesc.Texture2D.MipLevels = textureDesc.MipLevels;
291-
292-
if (FAILED(device->CreateShaderResourceView(texture.Get(), &srvDesc, &srv)))
293-
{
294-
std::cout << "CreateTextureView: Failed to create SRV from texture: " << pathToTexture.c_str() << "\n";
295-
return nullptr;
296-
}
297-
298-
return srv;
299-
}
300133

301134
void Rendering3DApplication::CreateConstantBuffers()
302135
{
@@ -323,43 +156,43 @@ bool Rendering3DApplication::Load()
323156

324157
constexpr VertexPositionColorUv vertices[] = {
325158
//Front
326-
{Position{ -0.5f, -0.5f, 0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 0.5f, 0.0f }},
327-
{Position{ 0.5f, -0.5f, 0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 1.0f, 1.0f }},
328-
{Position{ -0.5f, 0.5f, 0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 0.0f, 1.0f }},
329-
{Position{ 0.5f, 0.5f, 0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 0.0f, 1.0f }},
159+
{Position{ -0.5f, -0.5f, 0.5f }, Color{ 1.0f, 0.0f, 0.0f}, Uv{ 0.0f, 1.0f }},
160+
{Position{ 0.5f, -0.5f, 0.5f }, Color{ 0.0f, 1.0f, 0.0f}, Uv{ 1.0f, 1.0f }},
161+
{Position{ -0.5f, 0.5f, 0.5f }, Color{ 0.0f, 0.0f, 1.0f}, Uv{ 0.0f, 0.0f }},
162+
{Position{ 0.5f, 0.5f, 0.5f }, Color{ 1.0f, 1.0f, 0.0f}, Uv{ 1.0f, 0.0f }},
330163

331164
//Back
332-
{Position{ -0.5f, -0.5f, -0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 0.5f, 0.0f }},
333-
{Position{ 0.5f, -0.5f, -0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 1.0f, 1.0f }},
334-
{Position{ -0.5f, 0.5f, -0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 0.0f, 1.0f }},
335-
{Position{ 0.5f, 0.5f, -0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 0.0f, 1.0f }},
165+
{Position{ -0.5f, -0.5f, -0.5f }, Color{ 0.0f, 1.0f, 1.0f}, Uv{ 0.0f, 1.0f }},
166+
{Position{ 0.5f, -0.5f, -0.5f }, Color{ 1.0f, 0.0f, 1.0f}, Uv{ 1.0f, 1.0f }},
167+
{Position{ -0.5f, 0.5f, -0.5f }, Color{ 0.0f, 0.0f, 0.0f}, Uv{ 0.0f, 0.0f }},
168+
{Position{ 0.5f, 0.5f, -0.5f }, Color{ 1.0f, 1.0f, 1.0f}, Uv{ 1.0f, 0.0f }},
336169
};
337170

338171
constexpr uint32_t indices[] =
339172
{
340173
//Top
341-
2, 6, 7,
174+
7, 6, 2,
342175
2, 3, 7,
343176

344177
//Bottom
345178
0, 4, 5,
346-
0, 1, 5,
179+
5, 1, 0,
347180

348181
//Left
349182
0, 2, 6,
350-
0, 4, 6,
183+
6, 4, 0,
351184

352185
//Right
353-
1, 3, 7,
186+
7, 3, 1,
354187
1, 5, 7,
355188

356189
//Front
357-
0, 2, 3,
190+
3, 2, 0,
358191
0, 1, 3,
359192

360193
//Back
361194
4, 6, 7,
362-
4, 5, 7
195+
7, 5, 4
363196

364197
};
365198

@@ -393,28 +226,6 @@ bool Rendering3DApplication::Load()
393226
return false;
394227
}
395228

396-
_fallbackTextureSrv = CreateTextureView(_device.Get(), L"Assets/Textures/default.png");
397-
assert(_fallbackTextureSrv != nullptr); //as a fallback resource, this "needs" to exist
398-
399-
_textureSrv = CreateTextureViewFromDDS(_device.Get(), L"Assets/Textures/T_Froge.dds");
400-
if (_textureSrv == nullptr)
401-
{
402-
//this is "fine", we can use our fallback!
403-
_textureSrv = _fallbackTextureSrv;
404-
}
405-
406-
407-
D3D11_SAMPLER_DESC linearSamplerStateDescriptor = {};
408-
linearSamplerStateDescriptor.Filter = D3D11_FILTER::D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
409-
linearSamplerStateDescriptor.AddressU = D3D11_TEXTURE_ADDRESS_MODE::D3D11_TEXTURE_ADDRESS_WRAP;
410-
linearSamplerStateDescriptor.AddressV = D3D11_TEXTURE_ADDRESS_MODE::D3D11_TEXTURE_ADDRESS_WRAP;
411-
linearSamplerStateDescriptor.AddressW = D3D11_TEXTURE_ADDRESS_MODE::D3D11_TEXTURE_ADDRESS_WRAP;
412-
if (FAILED(_device->CreateSamplerState(&linearSamplerStateDescriptor, &_linearSamplerState)))
413-
{
414-
std::cout << "D3D11: Failed to create linear sampler state\n";
415-
return false;
416-
}
417-
418229
D3D11_RASTERIZER_DESC rasterDesc{};
419230
rasterDesc.CullMode = D3D11_CULL_NONE;
420231
rasterDesc.FillMode = D3D11_FILL_SOLID;
@@ -483,7 +294,7 @@ void Rendering3DApplication::Update()
483294

484295
static float _yRotation = 0.0f;
485296
static float _scale = 1.0f;
486-
static XMFLOAT3 _cameraPosition = { 0.0f, 0.0f, -1.0f };
297+
static XMFLOAT3 _cameraPosition = { 0.0f, 0.0f, -5.0f };
487298

488299

489300
_yRotation += _deltaTime;
@@ -493,7 +304,7 @@ void Rendering3DApplication::Update()
493304
XMVECTOR camPos = XMLoadFloat3(&_cameraPosition);
494305

495306
XMMATRIX view = XMMatrixLookAtLH(camPos, g_XMZero, { 0,1,0,1 });
496-
XMMATRIX proj = XMMatrixPerspectiveFovLH(90.0f * 0.0174533f,
307+
XMMATRIX proj = XMMatrixPerspectiveFovLH(75.0f * 0.0174533f,
497308
static_cast<float>(_width) / static_cast<float>(_height),
498309
0.1f,
499310
100.0f);
@@ -506,7 +317,7 @@ void Rendering3DApplication::Update()
506317
//This will define our 3D object
507318
XMMATRIX translation = XMMatrixTranslation(0, 0, 0);
508319
XMMATRIX scaling = XMMatrixScaling(_scale, _scale, _scale);
509-
XMMATRIX rotation = XMMatrixRotationRollPitchYaw(0, _yRotation, 0);
320+
XMMATRIX rotation = XMMatrixRotationRollPitchYaw(_yRotation, _yRotation / 2.0f, 0);
510321

511322
//Now we create our model matrix
512323
XMMATRIX modelMatrix = XMMatrixMultiply(translation, XMMatrixMultiply(scaling, rotation));
@@ -569,10 +380,6 @@ void Rendering3DApplication::Render()
569380
_deviceContext->RSSetViewports(1, &viewport);
570381
_deviceContext->RSSetState(_rasterState.Get());
571382

572-
573-
_deviceContext->PSSetShaderResources(0, 1, _textureSrv.GetAddressOf());
574-
_deviceContext->PSSetSamplers(0, 1, _linearSamplerState.GetAddressOf());
575-
576383
ID3D11Buffer* constantBuffers[2] =
577384
{
578385
_perFrameConstantBuffer.Get(),

src/Cpp/1-getting-started/1-3-4-3DRendering/Assets/Shaders/Main.ps.hlsl

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,7 @@ struct VSOutput
55
float2 Uv: TEXCOORD0;
66
};
77

8-
sampler LinearSampler : register(s0);
9-
10-
Texture2D Texture : register(t0);
11-
128
float4 Main(VSOutput input): SV_Target
139
{
14-
float4 texel = Texture.Sample(LinearSampler, input.Uv);
15-
return float4(input.Color, 0.50f) * texel;
10+
return input.Color.xyzz;
1611
}

0 commit comments

Comments
 (0)