# Tessellation (Direct3D 9)

## Tessellator Unit

The tessellator unit has been enhanced. You can now use it to:

- Perform adaptive tessellation of all higher-order primitives.
- Look up per-vertex displacement values from a displacement map and pass them on to a vertex shader.
- Support rectangle-patch tessellation. This is specified through a vertex declaration using D3DDECLMETHOD_PARTIALU or D3DDECLMETHOD_PARTIALV. If a vertex declaration containing these methods is used to draw a triangle patch,
**IDirect3DDevice9::DrawTriPatch**will fail. For more information about vertex declarations, see**D3DVERTEXELEMENT9**.

In DirectX 8.x, what was called ORDER was really the degree. In Direct3D 9, the degree is now specified by **D3DDEGREETYPE**.

// This used to be D3DORDERTYPE and D3DORDER* typedef enum _D3DDEGREETYPE { D3DDEGREE_LINEAR = 1, D3DDEGREE_QUADRATIC = 2, D3DDEGREE_CUBIC = 3, D3DDEGREE_QUINTIC = 5, D3DDEGREE_FORCE_DWORD = 0x7fffffff, } D3DDEGREETYPE;

The change in degree type affected two other structures.

typedef struct _D3DRECTPATCH_INFO { UINT StartVertexOffsetWidth; UINT StartVertexOffsetHeight; UINT Width; UINT Height; UINT Stride; D3DBASISTYPE Basis; D3DDEGREETYPE Degree; } D3DRECTPATCH_INFO;

typedef struct _D3DTRIPATCH_INFO { UINT StartVertexOffset; UINT NumVertices; D3DBASISTYPE Basis; D3DDEGREETYPE Degree; } D3DTRIPATCH_INFO;

Drivers need to fix compilation errors that will result from this change when they compile with the new headers. No functionality has to be changed.

## Adaptive Tessellation

Adaptive tessellation can be applied to high-order primitives including N-patches, rectangle patches, and triangle patches. This feature is enabled by the D3DRS_ENABLEADAPTIVETESSELLATION and adaptively tessellates a patch, based on the depth value of the control vertex in eye space.

The z-coordinates (Zi) of control vertices (Vi), which are transformed into eye space (Zieye) by performing a dot product with a 4-vector, are used as the depth values. The 4D vector (Mdm) is specified by the application using four render states (D3DRS_ADAPTIVETESS_X, D3DRS_ADAPTIVETESS_Y, D3DRS_ADAPTIVETESS_Z, and D3DRS_ADAPTIVETESS_W). This 4-vector could be the third column of the concatenated world and view matrices. It also could be used to apply a scale to Zieye.

The function to compute a tessellation level Ti from Zieye is assumed to be (MaxTessellationLevel/Zieye), which means that the MaxTessellationLevel is the tessellation level at Z = 1 in eye space. The MaxTessellationLevel is equal to a value set by **IDirect3DDevice9::SetNPatchMode** for N-patches and, for RT-patches, it is equal to pNumSegs. The tessellation level is then clamped to values, defined by the two additional render states D3DRS_MINTESSELLATIONLEVEL and D3DRS_MAXTESSELLATIONLEVEL, which define the minimum and maximum tessellation levels to be clamped to. The Ti's for each vertex along an edge of a patch are averaged to obtain a tessellation level for that edge. The algorithm for computing Ti for rectangle patches, triangle patches, and N-patches differs in what control vertices are used to compute the tessellation level.

For the rectangle patches with a B-spline basis, the four outermost control vertices are used. For example, with D3DORDER_CUBIC order: vertices (1,1) and (1,width-2) are used with pNumSegs[0], vertices (1,width-2) and (height-2,height-2) are used with pNumSegs[1], vertices (height-2,width-2) and (1,width-2) are used with pNumSegs[2], and vertices (2,1) and (1,1) are used with pNumSegs[3].

For the triangle patches, the corner patch vertices are used. With D3DORDER_CUBIC order: vertices (0) and (9) are used with pNumSegs[0], vertices (9) and (6) are used with pNumSegs[1] and vertices (6) and (0) are used with pNumSegs[3].

For N-patches the triangle vertices are used.

For the rectangle and triangle patches with a Bezier basis, the corner-control vertices are used.

Per-vertex tessellation rate control. An application can optionally supply a single positive floating-point value per vertex, which can be used to control the rate of tessellation. This is supplied using the D3DDECLUSAGE_TESSFACTOR, for which usage index must be 0 and input type must be D3DDECLTYPE_FLOAT1. This is multiplied to the per-vertex tessellation level.

### Math

The tessellation level (Te) for an edge e, represented by two control vertices (Ve1, Ve2), is computed as shown below :

Vertex Vi: (Xi, Yi, Zi, TFactori (optional)). Ze1eye = Ve1 . Mdm Ze2eye = Ve2 . Mdm Te1 = MaxTessellationLevel * TFactore1 / Ze1eye Te2 = MaxTessellationLevel * TFactore2 / Ze2eye Te = ( Te1 + Te2 ) / 2; if Te > D3DRS_MAXTESSELLATIONLEVEL || Te < 0, then Te = D3DRS_MAXTESSELLATIONLEVEL if Te < D3DRS_MINTESSELLATIONLEVEL, then Te = D3DRS_MINTESSELLATIONLEVEL

When D3DRS_ENABLEADAPTIVETESSELLATION is **TRUE**, triangle primitives (triangle lists, fans, strips) are drawn as N-patches, **IDirect3DDevice9::SetNPatchMode** has set value less than 1.0.

### API Changes

New render states:

D3DRS_ENABLEADAPTIVETESSELLATION // BOOL D3DRS_MAXTESSELLATIONLEVEL // Float D3DRS_MINTESSELLATIONLEVEL // Float D3DRS_ADAPTIVETESS_X // Float D3DRS_ADAPTIVETESS_Y // Float D3DRS_ADAPTIVETESS_Z // Float D3DRS_ADAPTIVETESS_W // Float // D3DRS_MINTESSELLATIONLEVEL and D3DRS_MAXTESSELLATIONLEVEL // cannot be less than 1

And their default values:

D3DRS_MAXTESSELLATIONLEVEL = 1.0f D3DRS_MINTESSELLATIONLEVEL = 1.0f D3DRS_ADAPTIVETESS_X = 0.0f D3DRS_ADAPTIVETESS_Y = 0.0f D3DRS_ADAPTIVETESS_Z = 1.0f D3DRS_ADAPTIVETESS_W = 0.0f D3DRS_ENABLEADAPTIVETESSELLATION = FALSE

New hardware caps:

D3DDEVCAPS2_ADAPTIVETESSRTPATCH // Can adaptively tessellate RT-patches D3DDEVCAPS2_ADAPTIVETESSNPATCH // Can adaptively tessellate N-patches