Sampler State in DirectX Graphics
Sampler state defines how texture data is sampled (read) from a texture resource. It controls aspects like filtering, addressing modes, and level-of-detail (LOD) bias, which are crucial for achieving various visual effects in 3D graphics.
Sampler States Overview
Sampler states are configured through sampler objects, which are bound to the graphics pipeline. These objects encapsulate the parameters that dictate the sampling process. When a shader samples a texture, it uses the currently bound sampler state to interpret the texture coordinates and retrieve the appropriate texel value.
Key Sampler Parameters:
- Filtering: Determines how texels are interpolated when texture coordinates do not map precisely to texel centers. Common filtering methods include point, bilinear, and anisotropic filtering.
- Addressing Modes: Defines how texture coordinates are handled when they fall outside the [0, 1] range. Options include wrap, mirror, clamp, and border.
- Level of Detail (LOD): Controls how mipmaps are selected and blended, and allows for bias adjustments.
DirectX Sampler Concepts
Texture Filtering
Texture filtering is essential for reducing aliasing artifacts and producing smoother images. DirectX supports several filtering techniques:
- Point Filtering (Nearest Neighbor): Selects the nearest texel to the sampled coordinate. This is the fastest but can result in blocky or pixelated appearances.
- Bilinear Filtering: Interpolates between the four nearest texels to produce a smoother result.
- Trilinear Filtering: Extends bilinear filtering to incorporate mipmaps, interpolating between two texels from adjacent mipmap levels for even smoother results across different distances.
- Anisotropic Filtering: A more advanced technique that samples textures in a directionally dependent manner, significantly improving texture quality at grazing angles.
Addressing Modes
Addressing modes specify how texture coordinates outside the 0-to-1 range are mapped back into the texture space. This is important for handling texture wrapping, clamping, and other effects.
- D3D11_TEXTURE_ADDRESS_WRAP: Repeats the texture. For example, a coordinate of 1.5 would map to 0.5.
- D3D11_TEXTURE_ADDRESS_MIRROR: Repeats the texture by mirroring it. For example, a coordinate of 1.5 would map to 0.5, but a coordinate of 2.5 would map to 0.5 as well (effectively mirroring from 1.0 to 2.0 and then repeating).
- D3D11_TEXTURE_ADDRESS_CLAMP: Clamps the texture coordinates to the edge. For example, any coordinate greater than 1.0 becomes 1.0, and any coordinate less than 0.0 becomes 0.0.
- D3D11_TEXTURE_ADDRESS_BORDER: Uses a border color. The border color is specified in the sampler state.
- D3D11_TEXTURE_ADDRESS_MIRROR_ONCE: Mirrors the texture once. Coordinates are mirrored until they reach 1.0, then clamped.
Level of Detail (LOD)
LOD controls how mipmap levels are selected. It involves:
- Mipmap Filtering: Selecting the appropriate mipmap level (or interpolating between two levels).
- Mipmap LOD Bias: An offset applied to the calculated mipmap level. A positive bias makes the texture appear further away (using smaller mipmaps), while a negative bias makes it appear closer (using larger mipmaps).
- Minimum and Maximum LOD: Restricts the range of mipmap levels that can be sampled.
Configuring Sampler State
In DirectX, sampler states are defined using structures and then created as sampler objects. For Direct3D 11, the primary structure is D3D11_SAMPLER_DESC
.
D3D11_SAMPLER_DESC
Structure
typedef struct D3D11_SAMPLER_DESC
{
D3D11_FILTER Filter;
D3D11_TEXTURE_ADDRESS_MODE AddressU;
D3D11_TEXTURE_ADDRESS_MODE AddressV;
D3D11_TEXTURE_ADDRESS_MODE AddressW;
FLOAT MipLODBias;
UINT MaxAnisotropy;
D3D11_COMPARISON_FUNC ComparisonFunc;
FLOAT BorderColor[4];
FLOAT MinLOD;
FLOAT MaxLOD;
} D3D11_SAMPLER_DESC;
Example: Creating a Bilinear Sampler
The following code snippet demonstrates how to create a sampler state with bilinear filtering and wrap addressing modes for Direct3D 11.
ID3D11Device* pDevice = /* ... get your device */;
ID3D11SamplerState* pSamplerState = nullptr;
D3D11_SAMPLER_DESC samplerDesc = {};
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; // Bilinear filtering
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; // Wrap addressing for U
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; // Wrap addressing for V
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; // Wrap addressing for W
samplerDesc.MipLODBias = 0.0f; // No LOD bias
samplerDesc.MaxAnisotropy = 1; // Not using anisotropic filtering
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; // No comparison
samplerDesc.BorderColor[0] = 0.0f; // Border color (RGBA)
samplerDesc.BorderColor[1] = 0.0f;
samplerDesc.BorderColor[2] = 0.0f;
samplerDesc.BorderColor[3] = 0.0f;
samplerDesc.MinLOD = 0.0f; // Minimum LOD
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; // Maximum LOD
HRESULT hr = pDevice->CreateSamplerState(&samplerDesc, &pSamplerState);
if (SUCCEEDED(hr))
{
// Bind the sampler state to the pipeline
// For pixel shader stage:
// pContext->PSSetSamplers(0, 1, &pSamplerState);
}
// Release pSamplerState when done
Sampler States in Shaders
In HLSL (High-Level Shading Language), sampler states are defined using the sampler
or SamplerState
type. They are typically bound to texture resources.
// In a pixel shader:
Texture2D myTexture;
SamplerState mySamplerState; // Or SamplerComparisonState for comparison samplers
float4 SampleTexture(float2 texCoord)
{
// The texture is sampled using the associated sampler state
return myTexture.Sample(mySamplerState, texCoord);
}