DirectX8, Fmod and CFL

Setting up DX8

Open source as .cpp as .html

Now things get a bit more interesting. In order to get this chapter's source to build you must link it with d3d8.lib and d3dx8.lib. These, naturally, come with the directx8 sdk. (Notice the absence of dxguid.lib!)

Let's go through the new bits, top-down:

LPDIRECT3D8             d3d;        // Direct3d8 object
LPDIRECT3DDEVICE8       d3dd;       // Rendering device
LPD3DXFONT              debugfont;  // Debug font (only used in winmain)

The d3d and d3dd objects should be familiar to you if you have read my d3dx7 tutorial. What's missing is the d3dx object. I find it funny how in dx8 the 'normal' programming interface has come closer to the dx7 d3dx model, and d3dx8 simplifies life even further.

The font usage system in d3dx8 has improved vastly from dx7, in fact so much that they can now be used for more than just debug printing, as we're doing here. More on the font when we get to winmain.

Next we have the rendering function; currently it's empty, but we'll fill it in the next chapter. The cleanup function releases our directx objects, and in chapter 4 it will also clean shut down fmod. The windowproc has got a new call to cleanup() on the WM_DESTROY message.

Winmain has most of the changes:

// Create d3d object, or if fail, quit.
if (NULL == (d3d = Direct3DCreate8(D3D_SDK_VERSION))) return E_FAIL;

The D3D_SDK_VERSION parameter makes sure you're using the same header files as the directx libraries were. Next, we'll ask the 'fullscreen?' question:

// Ask user whether we want to go fullscreen or not.
int fullscreen=0;
if (MessageBox(hWnd,"Go fullscreen?",progname,MB_YESNO)==IDYES) fullscreen=1;

The 'presentation', eg. screen mode, backbuffers, zbuffer, stencil buffer, how to flip back buffer to front, etc. This is the biggest new mess in dx8 - why didn't they do some default initialization, pray tell? d3dx7 was much simpler..

So first we set up the D3DPRESENT_PARAMETERS, depending on whether we're going fullscreen or not.

// Set up presentation. This is the biggest mess in dx8 and could have
// been designed better in my opinnion.

D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

if (fullscreen) {
    d3dpp.Windowed=FALSE;
    d3dpp.BackBufferWidth=640;
    d3dpp.BackBufferHeight=480;
    d3dpp.BackBufferFormat=D3DFMT_X8R8G8B8;//D3DFMT_R5G6B5;
    d3dpp.BackBufferCount=3;
    d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
    d3dpp.EnableAutoDepthStencil=TRUE;
    d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;
} else {
    D3DDISPLAYMODE d3ddm;
    if( FAILED( d3d->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
        return E_FAIL;
    d3dpp.Windowed   = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.EnableAutoDepthStencil=TRUE;
    d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8;
}

The windowed mode in dx8 is interesting; you can resize the window and it copes with it, and you don't need to know about it.. scaled windows will run much slower, though.

Next, we'll try to create the d3dd device object, trying out several options. Please note that we're creating software vertex processing object here (eg, no t&l will be enabled).

// Basically, try to create the device first with whatever we wanted, 
// then with 16-bit zbuffer and then with 16-bit color buffer. If all
// of this fails, die.
if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
                                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
{
    if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
                                    D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
    {
        d3dpp.AutoDepthStencilFormat=D3DFMT_D16;
        if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
                                        D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
        {
            d3dpp.BackBufferFormat=D3DFMT_R5G6B5;
            if( FAILED( d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
                                            D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3dd ) ) )
            {
                return 0;
            }
        }
    }
}

Now for the font. The font usage is much closer to GDI - you can use truetype fonts, and as you'll see when you look at the rendering loop the drawing function takes pretty much the same parameters as its GDI counterpart does.

// Now that dx is up, create a debug font so we can see the framerate:
D3DXCreateFont(d3dd,(HFONT)GetStockObject(SYSTEM_FONT),&debugfont);

The rest of the rendering loop has nothing really strange in it; read the comments in the code.

Next we'll draw some graphics..