FVF - Flexible Vertex Formats

3D models are created from triangles. Each triangle has 3 vertex. It is the data elements in each vertex that determines how it is rendered as it passes through the Direct3D pipeline.

Direct3D uses what is known as Flexible Vertex Formats (FVF) to describe the make up of a vertex. This allows you to design your own vertex format for your own requirements.

Creating your FVF

When designing your FVF you need to create a structure containing the required elements and also define your FVF make up by combining Direct3D flags (this is used in later calls to Direct3D to tell it what vertex format you are using). An example at this point should help:

If we want our triangles to be lit correctly we need to provide a position (you always have a position) and also a vertex normal. So we create a structure for our vertex:

struct CUSTOMVERTEX
{
      D3DXVECTOR3 p; // Vertex position
      D3DXVECTOR3 n; // Vertex normal
};

Note: it is common in Direct3D code to name FVF structures in capitals.
Note: the order you declare the above is important e.g. the position must come before the normal that must come before the texture co-ordinates etc.

The above is our custom vertex describing the data needed for every vertex in our 3D model. We now need to create a define describing this FVF so when we render Direct3D knows the make up of our structure. We do this by combining some Direct3D flags, so for the above structure we would create a define like this:

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL)

There are many possible elements we can add to our vertex. Another example might be similar to the above but this time we add texture co-ordinates as we want our triangles to be textured:

struct CUSTOMVERTEX
{
      D3DXVECTOR3 p; // Vertex position
      D3DXVECTOR3 n; // Vertex normal
      float tu,tv;   // Texture co-ordinate
};

The FVF for this would be:

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ  |  D3DFVF_NORMAL  |  D3DFVF_TEX1 )

This says our vertex has position, normal and a texture co-ordinate. Note that you do not need to use the D3DXVECTOR3 type. You can use your own structure if it defines three floats or simply declare three floats. The following is exactly the same as the structure above:

struct CUSTOMVERTEX
{
      float x,y,z; // vertex position
      float nx,ny,nz; // vertex normal
      float tu,tv; // texture co-ordinate
};

Another example is a vertex with colour and position:

struct MYVERTEX
{
       D3DXVECTOR3 p
       DWORD colour;
}

#define MYVERTEX_FVF (D3DFVF_XYZ | D3DFVF_DIFFUSE)

Note: with this example you would need to turn off the Direct3D lighting before rendering (as we are providing the colour anyway). You do this via: d3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

There are many other things you can add to your custom vertex, the most common ones being:

D3DFVF_XYZ              - position in 3D space
D3DFVF_XYZRHW           - already transformed co-ordinate (2D space)
D3DFVF_NORMAL           - normal
D3DFVF_DIFFUSE          - diffuse colour
D3DFVF_SPECULAR         - specular colour
D3DFVF_TEX1             - one texture co-ordinate
D3DFVF_TEX2             - two texture co-ordinates

Once you have created your vertex format you can fill in all the values and create a vertex buffer. With this you can render your 3D model. You tell Direct3D about your format like this device function:

gD3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

The Next Step

Now that we have defined our vertex we must create buffers to hold the vertices and indices and then render them. See the next notes on creating the buffers: Buffers

Further Reading

On this site: Buffers, Rendering Steps, Direct3D FAQ



© 2004-2016 Keith Ditchburn