Lesson 4: Using DirectX functions

The following example shows how to use DirectX functions for creating some effects on the screen. You'll need to download and install the DirectX SDK by Microsoft before you can use DirectX function in a plugin; make sure that it's the same version that the engine uses. The DirectX SDK version used by the engine is mentioned in a comment in the avars.h header file. As lite-C also natively supports DirectX functions, you don't need to write a plugin for using DirectX.

All DirectX initialization is done by the engine, thus it's sufficient just to call the draw functions. The Direct3D functions are accessed through a LPDIRECT3DDEVICE9 pointer that is available through the ENGINE_VARS *ev struct declared in avars.h, or can be obtained through the draw_begin function.

The example paints a multicolored triangle onto the screen. For details refer to the DirectX documentation that is available, along with the DirectX 9.0c SDK, from the Microsoft site. You'll see the triangle briefly flashing in the upper left corner when you call PaintD3DTriangle() once. If you call it in a wait(1)-loop, the triangle will be permanently on the screen.

#include <d3dx9.h> // from the DIRECTX9 SDK

// function PaintD3DTriangle();
// draws a red/blue/green triangle
DLLFUNC void PaintD3DTriangle (void)
{
// define a suited vertex struct
  struct VERTEX_FLAT { float x,y,z; float rhw; D3DCOLOR color; };
#define D3DFVF_FLAT (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

// define the three corner vertices
  VERTEX_FLAT v[3];
  v[0].x = 10.0; v[0].y = 10.0; v[0].color = 0xFFFF0000; // the red corner
  v[1].x = 310.0; v[1].y = 10.0; v[1].color = 0xFF0000FF; // the blue corner
  v[2].x = 10.0; v[2].y = 310.0; v[2].color = 0xFF00FF00; // the green corner
  v[0].z = v[1].z = v[2].z = 0.0; // z buffer - paint over everything
  v[0].rhw = v[1].rhw = v[2].rhw = 1.0; // no perspective

// open the scene and get the active D3D device
  LPDIRECT3DDEVICE9 pd3dDev = (LPDIRECT3DDEVICE9)draw_begin();
  if (!pd3dDev) return;

// set some render and stage states (you have to set some more, normally)
  pd3dDev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
  pd3dDev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
  pd3dDev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SELECTARG2);

// now draw the triangle
  pd3dDev->SetFVF(D3DFVF_FLAT);
  pd3dDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,1,(LPVOID)v,sizeof(VERTEX_FLAT));

// no need to close the scene - this is handled by the engine
}

By the way, the same code also runs under lite-C - you can find an example under draw_begin.

Depending on the 3D hardware, sometimes the engine has to release and reallocate the Direct3D device when the video output is switched between window and fullscreen mode, or the resolution is changed. If you use the pd3ddev for allocating an object, like a nonmanaged texture or buffer, you have to release the object before switching video, and recreate it afterwards. Use the on_d3d_reset and on_d3d_lost events for this. Otherwise the device can't be released and you'll receive an Uninitialized Device error message.

One final consideration. On accessing system resources like sound, video, joystick and so on, the DLL must take care of possible resource conflicts. The engine shares its resources and expects the same from the code inside the DLL. For instance, code that requires exclusive access to the sound device (like some old MOD players) won't work. Some resources (like the midi player) can't be shared - if midi music is played by the DLL, the engine must not play a midi file at the same time and vice versa.

 

► latest version online