Sampling is the process of taking values from an input at regular intervals. The more values we take the more accurate the resultant representation.
It is important to remember that we are rendering our graphics onto a finite sized grid of pixels (the size of the grid is the screen resolution) and it is this restriction that can cause problems. E.g. if you render a 16 by 16 texture onto an object that is close up to the camera it may actually take up 100 by 100 screen pixels and so will need to be stretched. The effect will be a horrible blocky texture. To solve this we can apply filtering techniques like bilinear filtering.
Setting a sampler state
The device method:
HRESULT SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD Value );
- Sampler - the sampler stage index (you can have a number of stages)
- State - this is a flag representing one of states that you want to change.
- Value - each state can have a value. What goes here depends totally on the State value.
e.g. to turn on bilinear filtering for texturing:
device->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
device->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
device->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
Texture Addressing Modes
Textures are mapped onto geometry using U and V values. UV value of 1,1 is the bottom right of the texture while 0,0 is the top left. If looking at a texture U values increase to the right and V values increase downward. If we go beyond 1 we can repeat (tile) the texture. How these situations are handled can be define via these states.
- D3DSAMP_ADDRESSU - texture address mode for the u co-ordinate. This can be D3DTADDRESS_WRAP which means the texture is repeated if values are beyond 1. So if we set a U value to 10 the texture would repeat 10 times in the U direction. D3DTADDRESS_MIRROR is like wrap but each tile is mirrored from the previous one. D3DTADDRESS_CLAMP restricts texture look up to the range 0 to 1. E.g. if the value goes beyond 1 the colour will be what is at 1. Look in the DirectX help for a full list of value options.
- D3DSAMP_ADDRESSV - as above but for the V co-ordinate.
- D3DSAMP_ADDRESSW - as above for the W co-ordinate
All the above default to D3DTADDRESS_WRAP.
When a texture is rendered to the screen at a larger size than it was created we say it has been magnified. If it is rendered at a smaller size we say it has been minified.
- D3DSAMP_MAGFILTER - if the texture is rendered larger than its created size it will look blocky. We can improve the look by setting a filter, choices are D3DTEXF_POINT where the closest texel is chosen, D3DTEXF_LINEAR which applies bilinear filtering (a method where a weighted average of the 2 by 2 texels surrounding the pixel is used) , D3DTEXF_ANISOTROPIC which takes into account the angle a primitive is rendered, D3DTEXF_PYRAMIDALQUAD which takes 4 samples and uses a tent filter and D3DTEXF_GAUSSIANQUAD which also takes 4 samples but uses a Gaussian filter.
- D3DSAMP_MINFILTER - if the texture is rendered smaller than its created size crawling effects and other nasty artefacts can occur. To solve this we can apply the same filters as above.
- D3DSAMP_MIPFILTER - mip maps can be used to both improve the look of textures and reduce the data size being rendered. When you supply the texture you also supply a chain of textures of different sizes. When rendering Direct3D chooses the size that is closest to the screen size the texture is rendered at. This can be improved further by filtering between the two mip map textures each side of the correct size. This value defines that filter - the choices are the same as for the magnification filter.
Note: not all graphic cards will support all filtering methods. All cards support point and most nowadays support linear. For the others you need to check what the card supports. To do this you can first use the CheckDeviceFormat function with D3DUSAGE_QUERY_FILTER to see if texture filtering is supported.
E.g to test if a graphic card supports texture filtering in hardware:
device->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL , adapterFormat, D3DUSAGE_QUERY_FILTER,D3DRTYPE_TEXTURE, textureFormat)
adapterFormat and textureFormat will depend on your implementation.
If this call succeeds the texture filtering is supported. To find out what methods are supported requires querying of the device caps (device capabilities) - to do this use the GetDeviceCaps device function.
I have described the most common sampler states, for others and for more detail please look in the DirectX help or see the MSDN page here: SetSamplerState
Sampler State Default Value
- ADDRESSU, D3DTADDRESS_WRAP
- ADDRESSV, D3DTADDRESS_WRAP
- ADDRESSW, D3DTADDRESS_WRAP
- BORDERCOLOR, 0x00000000
- MAGFILTER, D3DTEXF_POINT
- MINFILTER, D3DTEXF_POINT
- MIPFILTER, D3DTEXF_NONE
- MIPMAPLODBIAS, 0.0f
- MAXMIPLEVEL, 0
- MAXANISOTROPY, 1
- SRGBTEXTURE, 0
- ELEMENTINDEX, 0
- DMAPOFFSET, 256