These notes describe how to create and render a quad made of two triangles in screen space. It is useful to be able to make quads as they can be used for HUD and UI elements, sprites in 2D games and overlays e.g. mapping a transparent 'scope' texture over the whole screen to show that the player is looking through a gun sight.
Normally when working in 3D we define our vertices in model space. They are then transformed by the graphics pipeline into world space (via the world matrix), view space (via the view matrix) and finally into screen space (via the projection matrix). So when we want to draw triangles directly to the screen we need to provide already transformed vertex positions. You may think this would be just x and y however the end of the 3D transformation pipeline actually outputs x,y,z and RHW values. The z is a value from 0 to 1.0 (where 1 is furthest away) and is required to draw things correctly based on depth (and to write into the depth buffer). The RHW value stands for Reciprocal Homogenous W (it is 1/W) and is used for perspective. This can just be set to 1.0 for a screen space vertex. For a more¬ detailed explanation of RHW see the note below.
In Direct3D we need to create a structure for our vertex and specify an FVF. If we just want to draw a coloured quad on the screen our vertex may be like this:
¬ ¬ float x, y, z, rhw;
¬ ¬ D3DCOLOR color
#define SCREEN_SPACE_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
We would then need to¬ create a vertex buffer, lock it and fill in the values. The z value could be 1.0f and the RHW is always 1.0f. The x and y values are the screen positions of the vertex. Note that these are screen positions so 0,0 is the top left corner and you must define your triangles in clockwise order for Direct3D. If we want to use¬ DrawIndexedPrimitive¬ we would also need to create an¬ index buffer. We could then define 4 vertices for the corners of the quad and our index buffer define two triangles via two sets of 3 indices.
Note: if we wanted to draw a textured quad then our vertex definition would need to include a texture co-ordinate (and normally no colour).
Rendering our quad is just done the same as normal (see¬ Rendering Steps). If you find you cannot see it check first the winding order of your vertices to make sure they are defined clockwise.
RHW is a result of the fact that we use 4 by 4 matrices to do transformations and is required in clip space to set perspective. A 4 by 4 matrix is used so we can represent all rotational, translational and scaling factors in one matrix. Now normally the 4th component (w) is just 1 however when transforming into screen space and doing a perspective transformation the 4th value gets set to a value proportional to the z value of the input. This means the perspective effect can then be applied by the graphics pipeline by dividing everything by w. So why is RHW not just w? Well dividing by something is the same as multiplying by the reciprocal (1/W) which is normally faster than dividing.¬ The reason we have to include RHW here is that we are skipping the early part of the graphics pipeline that does the transformations and so we need to say what W would have been so the pipeline can divide by it. When drawing a quad we generally just want to supply exact screen positions and so RHW is just set to 1 which means multiply by 1/1 i.e. no change.