DirectXTK |
---|
CommonStates is a class which defines the most common combinations of Direct3D rendering states. This is simliar to the XNA Game Studio 4 (Microsoft.Xna.Framework.Graphics.BlendState
, DepthStencilState
, RasterizerState
, SamplerState
) design.
Related tutorials: Sprites and textures
Header
#include <CommonStates.h>
Initialization
The CommonStates constructor requires a Direct3D 12 device.
std::unique_ptr<CommonStates> states;
states = std::make_unique<CommonStates>(device);
For exception safety, it is recommended you make use of the C++ RAII pattern and use a std::unique_ptr
or std::shared_ptr
Many methods of this class are static. You do not need to create an instance of
CommonStates
to use them.
Usage
The static methods provide a D3D12_*_DESC
structure which can be used to create a Pipeline State Object (PSO):
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.RasterizerState = CommonStates::CullNone;
psoDesc.BlendState = CommonStates::Opaque;
psoDesc.DepthStencilState = CommonStates::DepthDefault;
...
DX::ThrowIfFailed(
device->CreateGraphicsPipelineState(&psoDesc,
IID_PPV_ARGS(m_pipelineState.ReleaseAndGetAddressOf())));
They are typically used with EffectPipelineStateDescription:
RenderTargetState rtState(m_deviceResources->GetBackBufferFormat(),
m_deviceResources->GetDepthBufferFormat());
EffectPipelineStateDescription pd(
&VertexPositionColor::InputLayout,
CommonStates::Opaque,
CommonStates::DepthDefault,
CommonStates::CullNone,
rtState);
Blending State
- static const D3D12_BLEND_DESC Opaque;
- static const D3D12_BLEND_DESC AlphaBlend;
- static const D3D12_BLEND_DESC Additive;
- static const D3D12_BLEND_DESC NonPremultiplied;
Typical usage
For standard drawing, typically you should make use of Opaque
.
For drawing alpha-blended objects, you should use AlphaBlend
if using premultiplied alpha, or
NonPremultiplied
if using 'straight' alpha.
For multipass rendering, you'd typically use Additive
.
Depth/Stencil State
- static const D3D12_DEPTH_STENCIL_DESC DepthNone;
- static const D3D12_DEPTH_STENCIL_DESC DepthDefault;
- static const D3D12_DEPTH_STENCIL_DESC DepthRead;
- static const D3D12_DEPTH_STENCIL_DESC DepthReverseZ;
- static const D3D12_DEPTH_STENCIL_DESC DepthReadReverseZ;
Typical usage
For standard rendering with a z-buffer, you should use DepthDefault
. If using a reverse z-buffer, then you should use DepthReverseZ
.
For drawing alpha blended objects (which is typically done after all opaque objects have been drawn), use DepthRead
which will respect the existing z-buffer values, but will not update them with 'closer' pixels.
For drawing objects without any depth-sort at all, use DepthNone
.
Rasterizer State
- static const D3D12_RASTERIZER_DESC CullNone;
- static const D3D12_RASTERIZER_DESC CullClockwise;
- static const D3D12_RASTERIZER_DESC CullCounterClockwise;
- static const D3D12_RASTERIZER_DESC Wireframe;
Typical usage
For default geometry winding use CullCounterClockwise
. For inverted winding (typically when using assets designed for left-handed coordinates but rendering with right-handed coordinates or vice-versa), use CullClockwise
.
For "double-sided" geometry, use CullNone
. Keep in mind this is a potentially large performance hit, so use it sparingly.
Wireframe
is a wireframe rendering mode and shows both sides of the geometry.
Static Sampler State
Each of these takes a shaderRegister
, a shaderVisibility
which defaults to D3D12_SHADER_VISIBILITY_ALL
, and registerSpace
which defaults to 0.
- static const D3D12_STATIC_SAMPLER_DESC StaticPointWrap(shaderRegister, shaderVisbility, registerSpace);
- static const D3D12_STATIC_SAMPLER_DESC StaticPointClamp(shaderRegister, shaderVisbility, registerSpace);
- static const D3D12_STATIC_SAMPLER_DESC StaticLinearWrap(shaderRegister, shaderVisbility, registerSpace);
- static const D3D12_STATIC_SAMPLER_DESC StaticLinearClamp(shaderRegister, shaderVisbility, registerSpace);
- static const D3D12_STATIC_SAMPLER_DESC StaticAnisotropicWrap(shaderRegister, shaderVisbility, registerSpace);
- static const D3D12_STATIC_SAMPLER_DESC StaticAnisotropicClamp(shaderRegister, shaderVisbility, registerSpace);
Typical usage
The static sampler used by SpriteBatch if you don't provide an explicit sampler descriptor is StaticLinearClamp
.
StaticAnisotropicWrap
is the default static sampler in DirectX 12.
Sampler descriptor
This class also provides heap-based descriptors for use with Effects and to override the default SpriteBatch static sampler.
- D3D12_GPU_DESCRIPTOR_HANDLE PointWrap() const;
- D3D12_GPU_DESCRIPTOR_HANDLE PointClamp() const;
- D3D12_GPU_DESCRIPTOR_HANDLE LinearWrap() const;
- D3D12_GPU_DESCRIPTOR_HANDLE LinearClamp() const;
- D3D12_GPU_DESCRIPTOR_HANDLE AnisotropicWrap() const;
- D3D12_GPU_DESCRIPTOR_HANDLE AnisotropicClamp() const;
To use these you must provide the CommonStates Heap to the command-list. Usage for the built-in shaders is typically in conjunction with a DescriptorHeap of texture descriptors as follows:
ID3D12DescriptorHeap* heaps[] = { resourceDescriptors->Heap(), states->Heap() };
commandList->SetDescriptorHeaps(static_cast<UINT>(std::size(heaps)), heaps);
You can also refer to these heap sampler descriptors by index using SamplerIndex
PointWrap
PointClamp
LinearWrap
LinearClamp
AnisotropicWrap
AnisotropicClamp
Because
SamplerIndex
is strongly-named enum to avoid conflicts with the method names, to use it as an integer requires an explicit cast:static_cast<int>( SamplerIndex::AnisotropicWrap )
To provide flexibility, setting the proper descriptor heaps to render with via
SetDescriptorHeaps
is left to the caller. You can create as many heaps as you wish in your application, but remember that you can have only a single texture descriptor heap and a single sampler descriptor heap active at a given time.
Remarks
These common states are equivalent to using the following descriptors:
Blend states
CD3DX12_DEFAULT def;
// Opaque
CD3DX12_BLEND_DESC desc(def);
// AlphaBlend
CD3DX12_BLEND_DESC desc(def);
desc.RenderTarget[0].BlendEnable = TRUE;
desc.RenderTarget[0].SrcBlend =
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE;
desc.RenderTarget[0].DestBlend =
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
// Additive
CD3DX12_BLEND_DESC desc(def);
desc.RenderTarget[0].BlendEnable = TRUE;
desc.RenderTarget[0].SrcBlend =
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend =
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ONE;
// NonPremultiplied
CD3DX12_BLEND_DESC desc(def);
desc.RenderTarget[0].BlendEnable = TRUE;
desc.RenderTarget[0].SrcBlend =
desc.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
desc.RenderTarget[0].DestBlend =
desc.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
Depth/Stencil states
CD3DX12_DEFAULT def;
// DepthNone
CD3DX12_DEPTH_STENCIL_DESC desc(def);
desc.DepthEnable = FALSE;
desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
// DepthDefault
CD3DX12_DEPTH_STENCIL_DESC desc(def);
desc.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
// DepthRead
CD3DX12_DEPTH_STENCIL_DESC desc(def);
desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
// DepthReverseZ
CD3DX12_DEPTH_STENCIL_DESC desc(def);
desc.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;
// DepthReadReverseZ
CD3DX12_DEPTH_STENCIL_DESC desc(def);
desc.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = D3D12_COMPARISON_FUNC_GREATER_EQUAL;
Rasterizer states
// CullNone
CD3DX12_RASTERIZER_DESC desc(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_NONE,
FALSE /* FrontCounterClockwise */,
D3D12_DEFAULT_DEPTH_BIAS,
D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
TRUE /* DepthClipEnable */,
TRUE /* MultisampleEnable */,
FALSE /* AntialiasedLineEnable */,
0 /* ForceSampleCount */,
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF);
// CullClockwise
CD3DX12_RASTERIZER_DESC desc(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_FRONT,
FALSE /* FrontCounterClockwise */,
D3D12_DEFAULT_DEPTH_BIAS,
D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
TRUE /* DepthClipEnable */,
TRUE /* MultisampleEnable */,
FALSE /* AntialiasedLineEnable */,
0 /* ForceSampleCount */,
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF);
// CullCounterClockwise
CD3DX12_RASTERIZER_DESC desc(D3D12_FILL_MODE_SOLID, D3D12_CULL_MODE_BACK,
FALSE /* FrontCounterClockwise */,
D3D12_DEFAULT_DEPTH_BIAS,
D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
TRUE /* DepthClipEnable */,
TRUE /* MultisampleEnable */,
FALSE /* AntialiasedLineEnable */,
0 /* ForceSampleCount */,
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF);
// Wireframe
CD3DX12_RASTERIZER_DESC desc(D3D12_FILL_MODE_WIREFRAME, D3D12_CULL_MODE_NONE,
FALSE /* FrontCounterClockwise */,
D3D12_DEFAULT_DEPTH_BIAS,
D3D12_DEFAULT_DEPTH_BIAS_CLAMP,
D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS,
TRUE /* DepthClipEnable */,
TRUE /* MultisampleEnable */,
FALSE /* AntialiasedLineEnable */,
0 /* ForceSampleCount */,
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF);
Sampler states
// PointWrap
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_POINT,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
0, D3D12_MAX_MAXANISOTROPY, D3D12_COMPARISON_FUNC_NEVER,
{ 0, 0, 0, 0 }, 0, D3D12_FLOAT32_MAX };
// PointClamp
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_POINT,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
0, D3D12_MAX_MAXANISOTROPY, D3D12_COMPARISON_FUNC_NEVER,
{ 0, 0, 0, 0 }, 0, D3D12_FLOAT32_MAX };
// LinearWrap
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_LINEAR,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
0, D3D12_MAX_MAXANISOTROPY, D3D12_COMPARISON_FUNC_NEVER,
{ 0, 0, 0, 0 }, 0, D3D12_FLOAT32_MAX };
// LinearClamp
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_LINEAR,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
0, D3D12_MAX_MAXANISOTROPY, D3D12_COMPARISON_FUNC_NEVER,
{ 0, 0, 0, 0 }, 0, D3D12_FLOAT32_MAX };
// AnisotropicWrap
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_ANISOTROPIC,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
D3D12_TEXTURE_ADDRESS_MODE_WRAP,
0, D3D12_MAX_MAXANISOTROPY, D3D12_COMPARISON_FUNC_NEVER,
{ 0, 0, 0, 0 }, 0, D3D12_FLOAT32_MAX };
// AnisotropicClamp
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_ANISOTROPIC,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
D3D12_TEXTURE_ADDRESS_MODE_CLAMP,
0, D3D12_MAX_MAXANISOTROPY, D3D12_COMPARISON_FUNC_NEVER,
{ 0, 0, 0, 0 }, 0, D3D12_FLOAT32_MAX };
Further reading
Managing Graphics Pipeline State in Direct3D 12
State objects in XNA Game Studio 4.0
Premultiplied alpha
Premultiplied alpha and image composition
Premultiplied alpha in XNA Game Studio 4.0
For Use
- Universal Windows Platform apps
- Windows desktop apps
- Windows 11
- Windows 10
- Xbox One
- Xbox Series X|S
Architecture
- x86
- x64
- ARM64
For Development
- Visual Studio 2022
- Visual Studio 2019 (16.11)
- clang/LLVM v12 - v18
- MinGW 12.2, 13.2
- CMake 3.20
Related Projects
DirectX Tool Kit for DirectX 11
Tools
See also
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.