|
IntroductionThis page provides source code for a framework for developing graphics
applications using DirectX 8. The framework provides a quick starting
point, while not imposing any high level functionality.
Using the FrameworkTo use the framework, you will need to write a minimum of three functions:
The framework is written under Visual C++ 6.0, and has not yet been compiled on other compilers. There is no guarantee of fitness for other compilers, and may require modification. If anyone adapts this for another compiler, I'd love to hear about it, and possibly post it here with your permission. Direct this or other comments to rdunlop@mvps.org. YOURPROGRAM.CPP#include "stdafx.h"
DXContext *lpDX=NULL;
static char szClass[] = "YourProgramClass";
static char szCaption[] = "Your Program";
void render_frame(float elapsed)
{
lpDX->lpDevice->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0x00000000,1.0f,0);
if (D3D_OK==lpDX->lpDevice->BeginScene()) {
// Place your rendering code here
lpDX->lpDevice->EndScene();
}
lpDX->lpDevice->Present(NULL,NULL,NULL,NULL);
}
void Cleanup()
{
if (lpDX)
lpDX->Cleanup();
}
LRESULT CALLBACK
WindowProc(HWND hWnd, unsigned uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
Cleanup();
PostQuitMessage(0);
break;
case WM_SIZE:
// clear or set activity flag to reflect focus
if (lpDX) {
if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
lpDX->active = FALSE;
else
lpDX->active = TRUE;
}
break;
case WM_KEYUP:
switch (wParam) {
case VK_ESCAPE:
// exit the program on escape
DestroyWindow(hWnd);
break;
}
break;
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0L;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
// create application handler and link to our WindowProc
lpDX=new DXContext(hInstance,szClass,szCaption,WindowProc);
if (!lpDX)
return FALSE;
// check for error
if (lpDX->lastErr!=S_OK) {
delete lpDX;
return FALSE;
}
// initialize full screen graphics to 640 x 480 x 32 bit, with 2 back buffers
if (!lpDX->Init(640,480,16,2,TRUE)) {
delete lpDX;
return FALSE;
}
// run the game loop, passing pointer to our rendering routine
lpDX->Run(render_frame);
SafeDelete(lpDX);
return TRUE;
}
STDAFX.H
#include <windows.h>
#include <mmsystem.h>
#include <d3d8.h>
#include <d3dx8.h>
#include <d3dx8mesh.h>
#include "dxcontext.h"
#define SafeRelease(x) if (x) {x->Release(); x=NULL;}
#define SafeDelete(x) if (x) {delete x; x=NULL;}
DXCONTEXT.H
class DXContext
{
public:
void SetRenderFunc(void (*ptr)(float));
BOOL TestDepth(D3DFORMAT fmt);
BOOL TestFormat(D3DFORMAT fmt);
void (*renderPtr)(float);
DXContext(HINSTANCE hInstance,LPCSTR pClass,LPCSTR pCaption,WNDPROC pProc);
~DXContext();
BOOL Init(WORD wWidth,WORD wHeight,WORD wDepth,WORD wBackBuffers,BOOL bWindowed);
int Run(void (*ptr)(float));
void Cleanup();
HRESULT hRes;
HRESULT lastErr;
D3DFORMAT format;
D3DFORMAT zFormat;
WORD height;
WORD width;
LPDIRECT3D8 lpD3D;
LPDIRECT3DDEVICE8 lpDevice;
BOOL active;
HWND hwnd;
};
#define DXC_ERR_REGWIN -2
#define DXC_ERR_CREATEWIN -3
#define DXC_ERR_CREATE3D -4
#define DXC_ERR_GETFORMAT -5
#define DXC_ERR_FORMAT -6
#define DXC_ERR_CREATEDEV -7
DXCONTEXT.CPP#include "stdafx.h"
#include "DXContext.h"
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"d3d8.lib")
#ifdef _DEBUG
#pragma comment(lib, "d3dx8d.lib")
#else
#pragma comment(lib, "d3dx8.lib")
#endif
DXContext:: DXContext(HINSTANCE hInstance,LPCSTR pClass,LPCSTR pCaption,WNDPROC pProc)
{
WNDCLASS wc;
// clear the error register
lastErr=S_OK;
// clear the active flag
active=FALSE;
// Set up and register window class
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) pProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(DWORD);
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = pClass;
if (!RegisterClass(&wc)) {
lastErr=-2;
return;
}
// Get dimensions of display
int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
hwnd = CreateWindow(pClass, // class
pCaption, // caption
WS_OVERLAPPEDWINDOW, // style
0, // left
0, // top
ScreenWidth, // width
ScreenHeight, // height
NULL, // parent window
NULL, // menu
hInstance, // instance
NULL); // parms
if (!hwnd) {
lastErr=-3;
return;
}
}
DXContext::~DXContext()
{
// call cleanup in case program did not
// the cleanup routine will only release objects once, despite repeated calls
Cleanup();
}
void DXContext::Cleanup()
{
// clear active flag
active=FALSE;
// release 3D interfaces
SafeRelease(lpDevice);
SafeRelease(lpD3D);
}
BOOL DXContext::TestFormat(D3DFORMAT fmt)
{
if (D3D_OK==lpD3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,fmt,fmt,FALSE))
return TRUE;
return FALSE;
}
BOOL DXContext::TestDepth(D3DFORMAT fmt)
{
if (D3D_OK!=lpD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,format,
D3DUSAGE_DEPTHSTENCIL,D3DRTYPE_SURFACE,fmt))
return FALSE;
if (D3D_OK!=lpD3D->CheckDepthStencilMatch(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,
format,format,fmt))
return FALSE;
return TRUE;
}
#define DXTestFmt(x) if (TestFormat(x)) {format=x; break;}
#define DXTestDepth(x) if (TestDepth(x)) zFormat=x
BOOL DXContext::Init(WORD wWidth,WORD wHeight,WORD wDepth,WORD wBackBuffers,BOOL bWindowed)
{
// save screen parameters
width=wWidth;
height=wHeight;
SetWindowPos(hwnd,HWND_TOP,0,0,width,height,SWP_SHOWWINDOW);
lpD3D=Direct3DCreate8(D3D_SDK_VERSION);
if (!lpD3D) {
lastErr=-4;
return FALSE;
}
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp,sizeof(d3dpp));
if (bWindowed) {
d3dpp.Windowed=TRUE;
D3DDISPLAYMODE d3ddm;
if( FAILED( hRes=lpD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) {
lastErr=-5;
return FALSE;
}
format=d3dpp.BackBufferFormat=d3ddm.Format;
} else {
d3dpp.Windowed=FALSE;
switch (wDepth) {
case 32:
DXTestFmt(D3DFMT_A8R8G8B8);
DXTestFmt(D3DFMT_X8R8G8B8);
case 16:
DXTestFmt(D3DFMT_R5G6B5);
DXTestFmt(D3DFMT_X1R5G5B5);
default:
format=D3DFMT_UNKNOWN;
}
if (format==D3DFMT_UNKNOWN) {
lastErr=-6;
return FALSE;
}
d3dpp.BackBufferFormat=format;
d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;
d3dpp.FullScreen_PresentationInterval=D3DPRESENT_INTERVAL_ONE;
}
d3dpp.BackBufferWidth=width;
d3dpp.BackBufferHeight=height;
d3dpp.BackBufferCount=wBackBuffers;
d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
zFormat=D3DFMT_UNKNOWN;
DXTestDepth(D3DFMT_D32);
else DXTestDepth(D3DFMT_D32);
else DXTestDepth(D3DFMT_D24S8);
else DXTestDepth(D3DFMT_D24X4S4);
else DXTestDepth(D3DFMT_D24X8);
else DXTestDepth(D3DFMT_D16);
else DXTestDepth(D3DFMT_D15S1);
else DXTestDepth(D3DFMT_D16_LOCKABLE);
if (zFormat!=D3DFMT_UNKNOWN) {
d3dpp.EnableAutoDepthStencil=TRUE;
d3dpp.AutoDepthStencilFormat=zFormat;
}
if( FAILED( hRes=lpD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,&lpDevice ) ) ) {
lastErr=-7;
return FALSE;
}
// return success
return TRUE;
}
int DXContext::Run(void (*ptr)(float))
{
renderPtr=ptr;
LONGLONG cur_time; // current time
BOOL perf_flag=FALSE; // flag determining which timer to use
LONGLONG last_time=0; // time of previous frame
float time_elapsed; // time since previous frame
float time_scale; // scaling factor for time
// select timer, get current time, and calculate time scale
if (QueryPerformanceFrequency((LARGE_INTEGER *) &cur_time)) {
time_scale=1.0f/cur_time;
QueryPerformanceCounter((LARGE_INTEGER *) &last_time);
perf_flag=TRUE;
} else {
time_scale=0.001f;
last_time=timeGetTime();
}
// set status as active
active=TRUE;
// Now we're ready to recieve and process Windows messages.
BOOL bGotMsg;
MSG msg;
PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
while( WM_QUIT != msg.message ) {
if (!active) {
bGotMsg=GetMessage(&msg, NULL, 0U, 0U);
if( bGotMsg ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
} else {
bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
if( bGotMsg ) {
TranslateMessage( &msg );
DispatchMessage( &msg );
} else {
// use the appropriate method to get time
// and calculate elapsed time since last frame
if (perf_flag)
QueryPerformanceCounter((LARGE_INTEGER *) &cur_time);
else
cur_time=timeGetTime();
// calculate elapsed time
time_elapsed=(cur_time-last_time)*time_scale;
// save frame time
last_time=cur_time;
if (renderPtr)
renderPtr(time_elapsed);
}
}
}
// return final message
return msg.wParam;
}
void DXContext::SetRenderFunc(void (__cdecl *ptr)(float))
{
renderPtr=ptr;
} |
Visitors Since 1/1/2000:
|