Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
96 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:


 the Source

 The Application

 Cleaning Up

 Printable version


  The Series

 The Basics
 First Steps to

 Building Worlds
 With X Files



The first method, which is exported by the framework is OneTimeSceneInit():

HRESULT CMyD3DApplication::OneTimeSceneInit() { // Initializes vertices used to render the background D3DVECTOR vFar = D3DVECTOR(0.0f, 0.0f, 0.5f); m_Background[0] = D3DTLVERTEX(vFar, 0.5f, 0xffffffff, 0, 0.0f, 1.0f); m_Background[1] = D3DTLVERTEX(vFar, 0.5f, 0xffffffff, 0, 0.0f, 0.0f); m_Background[2] = D3DTLVERTEX(vFar, 0.5f, 0xffffffff, 0, 1.0f, 1.0f); m_Background[3] = D3DTLVERTEX(vFar, 0.5f, 0xffffffff, 0, 1.0f, 0.0f); // Load in textures D3DTextr_CreateTextureFromFile( "lake.bmp" ); return S_OK; }

The background is held by four vertices. The "TL" indicates that these are vertices that your application - not Direct3D - should light and transform. These vertices skip the transformation and lightning pipeline altogether and pass straight to the rasterizer.

It wouldn't make any sense to transform or light the vertices which "hold" the background texture.

The D3D_OVERLOADS constructors defined in row 11 offers a convenient way for C++ programmers to create transformed and lit vertices with D3DTLVERTEX.

_D3DTLVERTEX(const D3DVECTOR& v, float _rhw, D3DCOLOR _color, D3DCOLOR _specular, float _tu, float _tv) { sx = v.x; sy = v.y; sz = v.z; rhw = _rhw; color = _color; specular = _specular; tu = _tu; tv = _tv; }

The system requires a vertex position that has already been transformed. So the x and y values must be in screen coordinates, and z must be the depth value of the pixel, which could be used in a z-buffer (we won't use a z-buffer here). Z values can range from 0.0 to 1.0, where 0.0 is the closest possible position to the viewer, and 1.0 is the farthest position still visible within the viewing area. Immediately following the position, transformed and lit vertices must include an RHW (reciprocal of homogeneous W) value.

Before rasterizing the vertices, they have to be converted from homogeneous vertices to non-homogeneous vertices, because the rasterizer expects them this way. Direct3D converts the homogeneous vertices to non-homogeneous vertices by dividing the x-, y-, and z-coordinates by the w-coordinate, and produces an RHW value by inverting the w-coordinate. This is only done for vertices which are transformed and lit by Direct3D.

The RHW value is used in multiple ways: for calculating fog, for performing perspective-correct texture mapping, and for w-buffering (an alternate form of depth buffering).

With D3D_OVERLOADS defined, D3DVECTOR is declared as


D3DVALUE is the fundamental Direct3D fractional data type. It's declared in d3dtypes.h as

typedef float D3DVALUE, *LPD3DVALUE;

The source shows that the x and y values for the D3DVECTOR are always 0.0f (this will be changed in InitDeviceObjects()). rhw is always 0.5f, color is 0xfffffff and specular is set to 0. Only the tu1 and tv1 values are differing between the four vertices. These are the coordinates of the background texture.

In order to map texels onto primitives, Direct3D requires a uniform address range for all texels in all textures. Therefore, it uses a generic addressing scheme in which all texel addresses are in the range of 0.0 to 1.0 inclusive.

If, instead, you decide to assign texture coordinates to make Direct3D use the bottom half of the texture, the texture coordinates your application would assign to the vertices of the primitive in this example are (0.0,0.0), (1.0,0.0), (1.0,0.5), and (0.0,0.5). Direct3D will apply the bottom half of the texture as the background.

Note: By assigning texture coordinates outside that range, you can create certain special texturing effects.

You will find the declaration of D3DTextr_CreateTextureFromFile() in the Framework source in d3dtextr.cpp. It creates a local bitmap from a passed file. Textures could be created from *.bmp and *.tga files. Textures are managed in the framework in a linked list, which holds the info per texture, called texture container.

struct TextureContainer { TextureContainer* m_pNext; // Linked list ptr TCHAR m_strName[80]; // Name of texture (doubles as image filename) DWORD m_dwWidth; DWORD m_dwHeight; DWORD m_dwStage; // Texture stage (for multitexture devices) DWORD m_dwBPP; DWORD m_dwFlags; BOOL m_bHasAlpha; LPDIRECTDRAWSURFACE7 m_pddsSurface; // Surface of the texture HBITMAP m_hbmBitmap; // Bitmap containing texture image DWORD* m_pRGBAData; public: HRESULT LoadImageData(); HRESULT LoadBitmapFile( TCHAR* strPathname ); HRESULT LoadTargaFile( TCHAR* strPathname ); HRESULT Restore( LPDIRECT3DDEVICE7 pd3dDevice ); HRESULT CopyBitmapToSurface(); HRESULT CopyRGBADataToSurface(); TextureContainer( TCHAR* strName, DWORD dwStage, DWORD dwFlags ); ~TextureContainer(); };


Any texture has to be restored before it can be used. This is done inside of InitDeviceObjects() by a call to D3DTextr_RestoreAllTextures():

HRESULT CMyD3DApplication::InitDeviceObjects() { D3DTextr_RestoreAllTextures( m_pd3dDevice ); // Set up the dimensions for the background image D3DVIEWPORT7 vp; m_pd3dDevice->GetViewport(&vp); m_Background[0].sy = (FLOAT)vp.dwHeight; m_Background[2].sy = (FLOAT)vp.dwHeight; m_Background[2].sx = (FLOAT)vp.dwWidth; m_Background[3].sx = (FLOAT)vp.dwWidth; return S_OK; }

The D3DTextr_RestoreAllTextures() method calls at least the method TextureContainer::Restore() which checks, for example, the device caps, sets up a new surface for the texture with these device caps and adjusts the texture size to be a power of 2 (take a look at that method in d3dtextr.cpp).

It turns on the texture management for hardware devices, limits the texture size, if the driver can't handle large textures (for example the Voodoo 2 and 3 boards can't handle textures bigger than 256x256). There's also a routine which makes the texture square, if the driver requires it . Another routine enumerate the texture formats and finds the closest format, which is supported by the device etc.

The IDirect3DDevice7::GetViewport() method retrieves the viewport parameters currently set for the device in a D3DVIEWPORT7 structure. dwWidth and dwHeight are the dimensions of the viewport on the render target surface, in pixels. Unless you are rendering only to a subset of the surface, these members should be set to the dimensions of the render target surface.

Next : Rendering