Texture Stage States
Texture stage states can be set to control the texture blending and the manipulation of texture co-ordinates.
You can blend many textures onto geometry in one pass, the number depends on the graphic cards capabilities (MaxTextureBlendStages). 8 stages is the maximum and is quite common on modern hardware. The great part is that you can feed the output from one stage into the next stage and create a chain of effect. At the bottom of this page I give some examples of what you can do.
Setting the texture stage state
The device method:
HRESULT SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
- Stage - the stage value, ranges from 0 to 7 (a count of 8)
- State - this is a flag representing one of the texture states that you want to change.
- Value - each state can have a value, what goes here depends totally on the State value.
The complete list of states is shown below: State Types
Note: there was a really useful sample application that came with the DirectX SDK called MFCTex. It allowed you to mess around with different sampler states and see the result. Unfortunately as everything moves into shaders this utility is no longer included with the SDK. I plan on creating one myself to replace it. This will appear here shortly.
- D3DTSS_COLOROP - used to define the colour blending operation. There are many options like D3DTOP_MODULATE which multiplies the colour arguments together. You can also select to add them or blend them together or just select the first colour argument or just the second etc. There are a large number of possibilities.
- D3DTSS_COLORARG1 - this is the first colour argument supplied to the above operation, it can be D3DTA_CURRENT which means this argument is set to the result of the previous stage (unless this is the first stage where by it is equal to the diffuse colour) or D3DTA_DIFFUSE which sets this argument to the current diffuse colour or D3DTA_TEXTURE which sets the argument to the texture colour. There are others available.
- D3DTSS_COLORARG2 - this is the second argument used in the operation and can be set to the same set of values as argument 1 above.
These states provide a host of possibilities especially when you consider that they can be chained together across stages. So the result of one stage can be fed into the input of the next stage. For the first stage the defaults are:
If we interpret this we can see that the operation is to multiply together the colour value in the texture with the diffuse colour (interpolated from vertex components during Gouraud shading). Current normally means the result of the previous stage but since this is the first stage it simply uses the diffuse colour.
Subsequent stages are disabled by default (their operation is set to D3DTOP_DISABLE).
These three states take the same values as those specified for the colour states but they act on the alpha channel only. The defaults for the first stage are:
This means that the alpha value is set to what is in the texture. Subsequent stages have the alpha operation disabled.
- D3DTSS_TEXCOORDINDEX - you can specify up to 8 texture coordinate sets in your vertex declaration. Here you can define which of those sets should be used for this stage. An advanced method is to let Direct3D generate the coordinates e.g. use the camera space vertex normal.
- D3DTSS_TEXTURETRANSFORMFLAGS - allows you to apply a calculation to the texture coordinates.
There are other states available e.g. ones that deal with bump mapping, that are beyond the scope of these notes. Please see the DirectX help or the MSDN page for more details: SetTextureStageState.
There is a lot of power in these states especially when you start feeding the output of one into the input of another. There are loads of possibilities.
You may wish to apply a light map to your geometry. You can do this in two stages:
Set the first texture, perhaps a wall, then:
device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
device->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
device->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
device->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
In this first stage we are saying modulate (multiply) the colour from the texture and from the existing diffuse colour value calculated on the triangle. The alpha channel is simply set to the diffuse colour.
Set the second texture, a light map, then:
device->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE );
device->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
device->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
device->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
device->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
Now we modulate the second texture colour with the result of the previous stage. This modulates our light map onto existing texture and hence on to the geometry. The alpha channel value is set to the alpha value in this texture.
device->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
device->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
We do nothing in this stage apart from disable all operations.
We can play around with these values as well. If we were to set the second stage operation to D3DTOP_MODULATE2 we would get a much brighter effect from the light map.
I hope to add more examples to this page soon.
Listed below is the complete list of possible state types that can be set per stage.
- D3DTSS_COLOROP per-stage blending controls for colour channels
- D3DTSS_COLORARG1 texture argument
- D3DTSS_COLORARG2 texture argument
- D3DTSS_ALPHAOP per-stage blending controls for alpha channel
- D3DTSS_ALPHAARG1 texture argument
- D3DTSS_ALPHAARG2 texture argument
- D3DTSS_BUMPENVMAT00 bump mapping matrix
- D3DTSS_BUMPENVMAT01 bump mapping matrix
- D3DTSS_BUMPENVMAT10 bump mapping matrix
- D3DTSS_BUMPENVMAT11 bump mapping matrix
- D3DTSS_TEXCOORDINDEX identifies which set of texture coordinates index this texture
- D3DTSS_BUMPENVLSCALE scale for bump map luminance
- D3DTSS_BUMPENVLOFFSET offset for bump map luminance
- D3DTSS_TEXTURETRANSFORMFLAGS controls texture transform
- D3DTSS_COLORARG0 third argument for triadic ops
- D3DTSS_ALPHAARG0 third argument for triadic ops
- D3DTSS_RESULTARG argument for result
- D3DTSS_CONSTANT per-stage constant