Written by Robert
Dunlop
Microsoft DirectX MVP |
|
Demo w/ Source Code for this article
Target Version: DirectX 8.x
may require adaptation for other versions
For those of you looking to perform 2D blits using DirectX Graphics under
DX8, here is a quick function to perform the equivalent of a blit by rendering
two pre-transformed polygons. First, we will need to define a custom
vertex that will contain screen coordinates, color, and texture coordinates.
#define D3DFVF_TLVERTEX D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1
typedef struct _D3DTLVERTEX {
float sx; /* Screen coordinates */
float sy;
float sz;
float rhw; /* Reciprocal of homogeneous w */
D3DCOLOR color; /* Vertex color */
float tu; /* Texture coordinates */
float tv;
_D3DTLVERTEX() { }
_D3DTLVERTEX(const D3DVECTOR& v, float _rhw,
D3DCOLOR _color,
float _tu, float _tv)
{ sx = v.x; sy = v.y; sz = v.z; rhw = _rhw;
color = _color;
tu = _tu; tv = _tv;
}
} D3DTLVERTEX, *LPD3DTLVERTEX;
Now we are ready for the rendering function. Some notes on the function
shown below :
- lpDevice is a pointer to an IDirect3DDevice8
interface.
- The z parameter passed is in the range of 0.0
(near) to 1.0 (far). This represents the depth of the rectangle, and
can be used to set the z-order of rendered images.
- The first line of the function calculates an rhw based on the assumption
that the projection matrix is set for a near plane of 10.0 and a far plane
of 1000.0.
- lpSrc points to a previously loaded texture.
- The whole source image is rendered to the rectangle defined by the (left,top)->(right,bottom)
coordinates
- Alpha or color blended transparency can be applied by setting the
appropriate render states prior to calling this function, and passing a
texture with an alpha channel if source alpha is used.
- Update! The function below has
been updated to compensate for the texel alignment rules of Direct3D.
The vertices of the target rectangle are offset by -0.5 to allow proper mapping
of texels to pixels. Note that the last row and column, specified by
the right and bottom parameters are not drawn, in accordance
with the behavior of the blitting functions of DirectDraw.
- Important Note: Prior to using
this method, D3D lighting must be turned off by setting the render state
D3DRS_LIGHTING to FALSE.
This is because we are providing the lighting values for the vertices, not
D3D. Set this state back to TRUE
afterwards, if you need to render other objects that use D3D lighting.
Without further adieu, here it is :
void BlitRect(LPDIRECT3DDEVICE8 lpDevice,
LPDIRECT3DTEXTURE8 lpSrc,
float left, float top,
float right, float bottom,
D3DCOLOR col,float z)
{
// calculate rhw
float rhw=1.0f/(z*990.0f+10.0f);
// set up rectangle
D3DTLVERTEX verts[4];
verts[0]=D3DTLVERTEX(D3DXVECTOR3(left-0.5f,
top-0.5f, z),rhw,col,0.0f,0.0f);
verts[1]=D3DTLVERTEX(D3DXVECTOR3(right-0.5f, top-0.5f, z),rhw,col,1.0f,0.0f);
verts[2]=D3DTLVERTEX(D3DXVECTOR3(right-0.5f, bottom-0.5f, z),rhw,col,1.0f,1.0f);
verts[3]=D3DTLVERTEX(D3DXVECTOR3(left-0.5f,
bottom-0.5f, z),rhw,col,0.0f,1.0f);
// set the texture
lpDevice->SetTexture(0,lpSrc);
// configure shader for vertex type
lpDevice->SetVertexShader(D3DFVF_TLVERTEX);
// draw the rectangle
lpDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,verts,sizeof(D3DTLVERTEX));
}
The demo provided below implements a simple image viewer
application using the technique shown in this article. The application
will load and display files in TGA, BMP, PNG, JPEG, and DDS formats, scaling the
image to fit if its dimensions are larger than the client area of the
application.