-
Notifications
You must be signed in to change notification settings - Fork 433
Using advanced shaders
In this lesson we learn about other built-in shader types and some of their uses.
First create a new project using the instructions from the first two lessons: The basic game loop and Adding the DirectX Tool Kit which we will use for this lesson.
Start by saving wood.dds and cubemap.dds into your new project's directory, and then from the top menu select Project / Add Existing Item.... Select "wood.dds" and click "OK". Repeat for "cubemap.dds"
In the Game.h file, add the following variables to the bottom of the Game class's private declarations (right after the m_graphicsMemory
variable you already added as part of setup):
DirectX::SimpleMath::Matrix m_world;
DirectX::SimpleMath::Matrix m_view;
DirectX::SimpleMath::Matrix m_proj;
std::unique_ptr<DirectX::CommonStates> m_states;
std::unique_ptr<DirectX::GeometricPrimitive> m_shape;
std::unique_ptr<DirectX::EnvironmentMapEffect> m_effect;
std::unique_ptr<DirectX::DescriptorHeap> m_resourceDescriptors;
Microsoft::WRL::ComPtr<ID3D12Resource> m_texture;
Microsoft::WRL::ComPtr<ID3D12Resource> m_cubemap;
enum Descriptors
{
Wood,
EnvMap,
Count
};
In Game.cpp, add to the TODO of CreateDevice after where you have created m_graphicsMemory
:
RenderTargetState rtState(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_D32_FLOAT);
m_resourceDescriptors = std::make_unique<DescriptorHeap>(m_d3dDevice.Get(),
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
Descriptors::Count);
ResourceUploadBatch resourceUpload(m_d3dDevice.Get());
resourceUpload.Begin();
DX::ThrowIfFailed(
CreateDDSTextureFromFile(m_d3dDevice.Get(), resourceUpload, L"wood.dds",
m_texture.ReleaseAndGetAddressOf(), false));
CreateShaderResourceView(m_d3dDevice.Get(), m_texture.Get(),
m_resourceDescriptors->GetCpuHandle(Descriptors::Wood));
bool isCubeMap = false;
DX::ThrowIfFailed(
CreateDDSTextureFromFile(m_d3dDevice.Get(), resourceUpload, L"cubemap.dds",
m_cubemap.ReleaseAndGetAddressOf(), false, 0, nullptr, &isCubeMap));
CreateShaderResourceView(m_d3dDevice.Get(), m_cubemap.Get(),
m_resourceDescriptors->GetCpuHandle(Descriptors::EnvMap), isCubeMap);
m_states = std::make_unique<CommonStates>(m_d3dDevice.Get());
EffectPipelineStateDescription pd(
&GeometricPrimitive::VertexType::InputLayout,
CommonStates::Opaque,
CommonStates::DepthDefault,
CommonStates::CullNone,
rtState);
m_effect = std::make_unique<EnvironmentMapEffect>(m_d3dDevice.Get(), EffectFlags::Lighting, pd);
m_effect->EnableDefaultLighting();
m_effect->SetTexture(m_resourceDescriptors->GetGpuHandle(Descriptors::Wood),
m_states->LinearWrap());
m_effect->SetEnvironmentMap(m_resourceDescriptors->GetGpuHandle(Descriptors::EnvMap),
m_states->LinearWrap());
m_shape = GeometricPrimitive::CreateTeapot();
m_world = Matrix::Identity;
auto uploadResourcesFinished = resourceUpload.End(m_commandQueue.Get());
WaitForGpu();
uploadResourcesFinished.wait();
In Game.cpp, add to the TODO of CreateResources:
m_view = Matrix::CreateLookAt(Vector3(2.f, 2.f, 2.f),
Vector3::Zero, Vector3::UnitY);
m_proj = Matrix::CreatePerspectiveFieldOfView(XM_PI / 4.f,
float(backBufferWidth) / float(backBufferHeight), 0.1f, 10.f);
m_effect->SetView(m_view);
m_effect->SetProjection(m_proj);
In Game.cpp, add to the TODO of OnDeviceLost:
m_states.reset();
m_shape.reset();
m_effect.reset();
m_texture.Reset();
m_cubemap.Reset();
m_resourceDescriptors.reset();
In Game.cpp, add to the TODO of Render:
ID3D12DescriptorHeap* heaps[] = { m_resourceDescriptors->Heap(), m_states->Heap() };
m_commandList->SetDescriptorHeaps(_countof(heaps), heaps);
m_effect->SetWorld(m_world);
m_effect->Apply(m_commandList.Get());
m_shape->Draw(m_commandList.Get());
In Game.cpp, add to the TODO of Update:
float time = float(timer.GetTotalSeconds());
m_world = Matrix::CreateRotationZ(cosf(time) * 2.f);
Build and run to see the teapot rendered with a fancy material.
In Game.cpp add the following to the TODO section of Update:
m_effect->SetFresnelFactor(cosf(time * 2.f));
Build and run to see the effect of animating the Fresnel factor.
-
The NormalMapEffect is similar to the BasicEffect with the addition of a normal texture map and an optional specular texture map. This requires the input layout to contain vertex tangents which can be included when exporting an
.SDKMESH
via the Content Exporter (see-normalmaps
), or can be computed using DirectXMesh. -
DualTextureEffect is used to render a material with two textures applied. This requires the input layout to contain a second set of texture coordinates. This does not perform vertex or per-pixel lighting, as the second texture is most often a lightmap with statically computed lighting information.
.SDKMESH
and the Content Exporter support exporting light-mapped models which utilize this effect (see-lightmaps
). -
The AlphaTestEffect is used to perform pixel rejection based on an alpha reference value and function selection. It's primarily to implement techniques that relied on legacy Direct3D 9 alpha testing render state. This effect is independent of the depth/stencil tests set in
D3D12_DEPTH_STENCIL_DESC.DepthFunc
andStencilFunc
.
DirectX Tool Kit docs Effects
All content and source code for this package are subject to the terms of the MIT License.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
- Universal Windows Platform apps
- Windows desktop apps
- Windows 11
- Windows 10
- Xbox One
- Xbox Series X|S
- x86
- x64
- ARM64
- Visual Studio 2022
- Visual Studio 2019 (16.11)
- clang/LLVM v12 - v18
- MinGW 12.2, 13.2
- CMake 3.20