// Select which engine to use for rendering
// 0: Nuclear Fusion will be used -- shows the bugs
// 1: Raw Direct3D 9 will be used -- shows how it's supposed to look
#define D3D9_MODE 0
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// !!! BUGS !!!
//----
// The following are a set of 'toggles' for checking between NF bugs
//
// Set to '1' to activate the code associated with the workaround (this will
// cause the desired effect to be achieved)
//
// Set to '0' to deactivate the workaround code; i.e., show the bug (if NF was
// working as believed to be correct, this should have no effect)
//
// If D3D9_MODE is set to 1 (i.e., raw Direct3D 9 code is being used) altering
// these will have no effect.
//----
// Toggle workaround for first bug (object must be visible to render)
#define WORKAROUND_BUG1 0
// Toggle workaround for second bug (stateblocks must be used to see objects)
#define WORKAROUND_BUG2 1 //NOTE: WORKAROUND_BUG1 must be 1 to see this bug
// Toggle workaround for third bug (texture can only be seen with 2D text on)
#define WORKAROUND_BUG3 0 //XXX: This isn't really a bug... still annoying
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//------------------------------------------------------------------------------
#ifndef D3D9_MODE
# define D3D9_MODE 0
#endif
#include <d3d9.h>
#include <windows.h>
#if D3D9_MODE==0
# ifndef NF_RUN_MODE
# ifdef _DEBUG
# define NF_RUN_MODE NF_ERROR_EXCEPTION
# else
# define NF_RUN_MODE NF_ERROR_PRO
# endif
# endif
# include <nf.h>
#elif defined( _MSC_VER )
# pragma comment( lib, "d3d9.lib" )
#endif
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef NFCALL
# define NFCALL __stdcall
#endif
#ifndef NORETURN
# ifdef __GNUC__
# define NORETURN __attribute__( ( noreturn ) )
# else
# define NORETURN __declspec( noreturn )
# endif
#endif
//------------------------------------------------------------------------------
NORETURN void err_fatal_( const char *file, int line, const char *func ) {
DWORD lastWindowsError = GetLastError();
int lastPosixError = errno;
char errDesc[ 1024 ];
errDesc[ 0 ] = '\0';
if( lastWindowsError ) {
FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastWindowsError, 0,
errDesc, sizeof( errDesc ) - 1, NULL );
errDesc[ sizeof( errDesc ) - 1 ] = 0;
} else {
#ifdef __STDC_WANT_SECURE_LIB__
strerror_s( errDesc, sizeof( errDesc ), lastPosixError );
#else
strncpy( errDesc, strerror( lastPosixError ), sizeof( errDesc ) - 1 );
errDesc[ sizeof( errDesc ) - 1 ] = '\0';
#endif
}
char buf[ 512 + sizeof( errDesc ) ];
#ifndef __STDC_WANT_SECURE_LIB__
# define sprintf_s snprintf
#endif
sprintf_s( buf, sizeof( buf ), "[%s(%i) %s] ERROR\n%s", file, line, func,
errDesc );
buf[ sizeof( buf ) - 1 ] = '\0';
#ifndef __STDC_WANT_SECURE_LIB__
# undef sprintf_s
#endif
#if D3D9_MODE==0
MakeConsole();
SetConsoleTitleA( "D3D9Sandbox Error" );
WriteConsoleLine( buf );
#else
fprintf( stderr, "%s\n", buf );
fflush( stderr );
#endif
MessageBoxA( GetActiveWindow(), buf, "Error", MB_ICONERROR|MB_OK );
if( IsDebuggerPresent() ) {
DebugBreak();
}
exit( EXIT_FAILURE );
}
#ifndef __GNUC__
# define __func__ __FUNCTION__
#endif
#define err_fatal() err_fatal_( __FILE__, __LINE__, __func__ )
#define err_assert( expr )\
if( !( expr ) )\
err_fatal()
static inline bool __check_hr( HRESULT hr ) {
if( FAILED( hr ) ) {
SetLastError( hr );
return false;
}
return true;
}
#define err_assert_hr( hr )\
if( !__check_hr( hr ) )\
err_fatal()
//------------------------------------------------------------------------------
#if D3D9_MODE==0
NUKE window = NULL;
#else
HWND window = NULL;
#endif
IDirect3D9 *direct3d = NULL;
IDirect3DDevice9 *device = NULL;
#define APP_TITLE "Sandbox Test"
#define SCREEN_RES_X 640
#define SCREEN_RES_Y 480
#define BACKGROUND_COLOR 0xFF224488
inline DWORD dxsb_color( DWORD value ) {
#if D3D9_MODE==0
return ( value&0xFF00FF00 )|( ( value&0x00FF0000 )>>16 )|
( ( value&0x000000FF )<<16 );
#else
return value;
#endif
}
#ifndef STATEBLOCK_ENABLED
# if D3D9_MODE==0
# if WORKAROUND_BUG2
# define STATEBLOCK_ENABLED 1
# else
# define STATEBLOCK_ENABLED 0
# endif
# else
# define STATEBLOCK_ENABLED 0
# endif
#endif
#if STATEBLOCK_ENABLED==1
IDirect3DStateBlock9 *defaultStateBlock = NULL;
inline void stateblock_init() {
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// !!! BUG !!!
// Have to use state blocks with NF to see any objects already in the scene
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
HRESULT hr;
hr = device->CreateStateBlock( D3DSBT_ALL, &defaultStateBlock );
err_assert_hr( hr );
}
inline void stateblock_fini() {
if( !defaultStateBlock ) {
return;
}
defaultStateBlock->Release();
defaultStateBlock = NULL;
}
inline void stateblock_predraw() {
defaultStateBlock->Capture();
static const float zero = 0.0f;
static const float one = 1.0f;
// reset all states to default
device->SetVertexShader( NULL );
device->SetPixelShader( NULL );
#define SET(k,v) device->SetRenderState( D3DRS_##k, v )
SET( ZENABLE, D3DZB_FALSE );
SET( FILLMODE, D3DFILL_SOLID );
SET( SHADEMODE, D3DSHADE_GOURAUD );
SET( ZWRITEENABLE, TRUE );
SET( ALPHATESTENABLE, FALSE );
SET( LASTPIXEL, TRUE );
SET( SRCBLEND, D3DBLEND_ONE );
SET( DESTBLEND, D3DBLEND_ZERO );
SET( CULLMODE, D3DCULL_CCW );
SET( ZFUNC, D3DCMP_LESSEQUAL );
SET( ALPHAREF, 0 );
SET( ALPHAFUNC, D3DCMP_ALWAYS );
SET( ALPHABLENDENABLE, FALSE );
SET( FOGENABLE, FALSE );
SET( SPECULARENABLE, FALSE );
SET( FOGCOLOR, 0 );
SET( FOGTABLEMODE, D3DFOG_NONE );
SET( FOGSTART, *( DWORD * )&zero );
SET( FOGEND, *( DWORD * )&one );
SET( FOGDENSITY, *( DWORD * )&one );
SET( RANGEFOGENABLE, FALSE );
SET( STENCILENABLE, FALSE );
SET( STENCILFAIL, D3DSTENCILOP_KEEP );
SET( STENCILZFAIL, D3DSTENCILOP_KEEP );
SET( STENCILPASS, D3DSTENCILOP_KEEP );
SET( STENCILFUNC, D3DCMP_ALWAYS );
SET( STENCILREF, 0 );
SET( STENCILMASK, 0xFFFFFFFF );
SET( STENCILWRITEMASK, 0xFFFFFFFF );
SET( TEXTUREFACTOR, 0xFFFFFFFF );
SET( WRAP0, 0 );
SET( WRAP1, 0 );
SET( WRAP2, 0 );
SET( WRAP3, 0 );
SET( WRAP4, 0 );
SET( WRAP5, 0 );
SET( WRAP6, 0 );
SET( WRAP7, 0 );
SET( LIGHTING, TRUE );
SET( FOGVERTEXMODE, D3DFOG_NONE );
SET( COLORVERTEX, TRUE );
SET( LOCALVIEWER, TRUE );
SET( NORMALIZENORMALS, FALSE );
SET( DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );
SET( SPECULARMATERIALSOURCE, D3DMCS_COLOR2 );
SET( AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL );
SET( EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL );
SET( CLIPPLANEENABLE, 0 );
SET( POINTSIZE_MIN, *( DWORD * )&one );
SET( POINTSPRITEENABLE, FALSE );
SET( MULTISAMPLEANTIALIAS, TRUE );
SET( MULTISAMPLEMASK, 0xFFFFFFFF );
SET( PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE );
SET( POINTSIZE_MAX, *( DWORD * )&one );
SET( COLORWRITEENABLE, 0x0000000F );
SET( BLENDOP, D3DBLENDOP_ADD );
SET( POSITIONDEGREE, D3DDEGREE_CUBIC );
SET( NORMALDEGREE, D3DDEGREE_LINEAR );
SET( SCISSORTESTENABLE, FALSE );
SET( MINTESSELLATIONLEVEL, *( DWORD * )&one );
SET( MAXTESSELLATIONLEVEL, *( DWORD * )&one );
SET( ADAPTIVETESS_X, *( DWORD * )&zero );
SET( ADAPTIVETESS_Y, *( DWORD * )&zero );
SET( ADAPTIVETESS_Z, *( DWORD * )&one );
SET( ADAPTIVETESS_W, *( DWORD * )&zero );
SET( ENABLEADAPTIVETESSELLATION, FALSE );
SET( TWOSIDEDSTENCILMODE, FALSE );
SET( CCW_STENCILFAIL, D3DSTENCILOP_KEEP );
SET( CCW_STENCILZFAIL, D3DSTENCILOP_KEEP );
SET( CCW_STENCILPASS, D3DSTENCILOP_KEEP );
SET( CCW_STENCILFUNC, D3DCMP_ALWAYS );
SET( COLORWRITEENABLE1, 0x0000000F );
SET( COLORWRITEENABLE2, 0x0000000F );
SET( COLORWRITEENABLE3, 0x0000000F );
SET( BLENDFACTOR, 0xFFFFFFFF );
SET( SRGBWRITEENABLE, 0 );
SET( DEPTHBIAS, 0 );
SET( WRAP8, 0 );
SET( WRAP9, 0 );
SET( WRAP10, 0 );
SET( WRAP11, 0 );
SET( WRAP12, 0 );
SET( WRAP13, 0 );
SET( WRAP14, 0 );
SET( WRAP15, 0 );
SET( SEPARATEALPHABLENDENABLE, FALSE );
SET( SRCBLENDALPHA, D3DBLEND_ONE );
SET( DESTBLENDALPHA, D3DBLEND_ZERO );
SET( BLENDOPALPHA, D3DBLENDOP_ADD );
SET( DITHERENABLE, FALSE );
SET( VERTEXBLEND, D3DVBF_DISABLE );
SET( POINTSIZE, *( DWORD * )&one );
SET( POINTSCALEENABLE, FALSE );
SET( POINTSCALE_A, *( DWORD * )&one );
SET( POINTSCALE_B, *( DWORD * )&zero );
SET( POINTSCALE_C, *( DWORD * )&zero );
SET( INDEXEDVERTEXBLENDENABLE, FALSE );
SET( TWEENFACTOR, *( DWORD * )&zero );
SET( ANTIALIASEDLINEENABLE, FALSE );
#undef SET
// set all texture stage states
device->SetTexture( 0, NULL );
device->SetTexture( 1, NULL );
device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
device->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
device->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
device->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
device->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
device->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
device->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_CURRENT );
device->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
device->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTTFF_DISABLE );
// default matrices
static const D3DMATRIX identity = {
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1
};
device->SetTransform( D3DTS_WORLD, &identity );
device->SetTransform( D3DTS_VIEW, &identity );
device->SetTransform( D3DTS_PROJECTION, &identity );
}
inline void stateblock_postdraw() {
defaultStateBlock->Apply();
}
#else
inline void stateblock_init() {
}
inline void stateblock_fini() {
}
inline void stateblock_predraw() {
}
inline void stateblock_postdraw() {
}
#endif
//------------------------------------------------------------------------------
static IDirect3DTexture9 *texture_load_test() {
static const DWORD pixels[ 4*4 ] = {
0x00FF0000, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
0xFFFF0000, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF,
0xFF00FF00, 0x00FFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFF0000FF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00FFFFFF
};
IDirect3DTexture9 *texture;
HRESULT hr;
hr = device->CreateTexture( 4, 4, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
&texture, NULL );
err_assert_hr( hr );
D3DLOCKED_RECT lockedRect;
hr = texture->LockRect( 0, &lockedRect, NULL, D3DLOCK_DISCARD );
err_assert_hr( hr );
if( lockedRect.Pitch==4*sizeof( DWORD ) ) {
memcpy( lockedRect.pBits, ( const void * )pixels, sizeof( pixels ) );
} else {
for( int y=0; y<4; ++y ) {
for( int x=0; x<4; ++x ) {
*( DWORD * )( ( ( char * )lockedRect.pBits ) +
y*lockedRect.Pitch + x*sizeof( DWORD ) ) =
pixels[ y*4 + x ];
}
}
}
hr = texture->UnlockRect( 0 );
err_assert_hr( hr );
return texture;
}
IDirect3DTexture9 *testTexture = NULL;
void texture_init() {
testTexture = texture_load_test();
}
void texture_fini() {
if( testTexture!=NULL ) {
testTexture->Release();
testTexture = NULL;
}
}
//----------------
#if D3D9_MODE==1
POINT lastCursorPos;
#endif
float in_mouse_x() {
#if D3D9_MODE==0
return ( float )MouseX( window );
#else
return ( float )lastCursorPos.x;
#endif
}
float in_mouse_y() {
#if D3D9_MODE==0
return ( float )MouseY( window );
#else
return ( float )lastCursorPos.y;
#endif
}
void render_basic_primitive() {
// let's draw something behind the alpha'd texture
static const struct {
const float x, y, z, w;
const DWORD color;
} vertices[] = {
{ 25, 25, 0, 1, 0xFFFF0000 },
{ 25, 225, 0, 1, 0xFF00FF00 },
{ 225, 25, 0, 1, 0xFF0000FF },
{ 225, 225, 0, 1, 0xFFFFFFFF }
};
// we'll adjust the render state for this primitive directly
device->SetTexture( 0, NULL );
device->SetRenderState( D3DRS_LIGHTING, FALSE );
device->SetRenderState( D3DRS_ZENABLE, FALSE );
device->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
// draw the primitive
device->SetFVF( D3DFVF_XYZRHW|D3DFVF_DIFFUSE );
device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, &vertices[ 0 ],
sizeof( vertices[ 0 ] ) );
}
void render_alpha_texture() {
struct {
float x, y, z, w;
DWORD d;
float s, t;
} quad[ 4 ];
// no shaders or textures
device->SetVertexShader( NULL );
device->SetPixelShader( NULL );
device->SetTexture( 0, NULL );
device->SetTexture( 1, NULL );
// set all basic render states
device->SetRenderState( D3DRS_LIGHTING, FALSE );
device->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
device->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
device->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
// set the alpha states
device->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
device->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
device->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
device->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
#if 1
device->SetRenderState( D3DRS_ALPHAREF, 0x00000001 );
device->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
device->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
#endif
// set the texture states
device->SetTexture( 0, testTexture );
device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
device->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
device->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
device->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
device->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );
device->SetSamplerState( 0, D3DSAMP_BORDERCOLOR, 0xFFFFFFFF );
device->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_NONE );
device->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_NONE );
device->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE );
// fill in the quad
quad[ 0 ].x = in_mouse_x();
quad[ 0 ].y = in_mouse_y();
quad[ 0 ].z = 0;
quad[ 0 ].w = 1;
quad[ 0 ].d = 0xFFFFFFFF;
quad[ 0 ].s = 0;
quad[ 0 ].t = 0;
quad[ 1 ].x = quad[ 0 ].x;
quad[ 1 ].y = quad[ 0 ].y + 128;
quad[ 1 ].z = 0;
quad[ 1 ].w = 1;
quad[ 1 ].d = 0xFFFFFFFF;
quad[ 1 ].s = 0;
quad[ 1 ].t = 1;
quad[ 2 ].x = quad[ 0 ].x + 128;
quad[ 2 ].y = quad[ 0 ].y;
quad[ 2 ].z = 0;
quad[ 2 ].w = 1;
quad[ 2 ].d = 0xFFFFFFFF;
quad[ 2 ].s = 1;
quad[ 2 ].t = 0;
quad[ 3 ].x = quad[ 2 ].x;
quad[ 3 ].y = quad[ 1 ].y;
quad[ 3 ].z = 0;
quad[ 3 ].w = 1;
quad[ 3 ].d = 0xFFFFFFFF;
quad[ 3 ].s = 1;
quad[ 3 ].t = 1;
// draw the quad
device->SetFVF( D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1 );
device->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, &quad[ 0 ],
sizeof( quad[ 0 ] ) );
}
void NFCALL render_f( void *vp, bool is2d, int reserved ) {
// unused
( void )vp;
( void )is2d;
( void )reserved;
// do the rendering thing
stateblock_predraw();
render_basic_primitive();
render_alpha_texture();
stateblock_postdraw();
}
//----------------
#if D3D9_MODE==0
//:::NUCLEAR-FUSION:::----------------------------------------------------------
void dxsb_init() {
window = MakeWindowDX( SCREEN_RES_X, SCREEN_RES_Y );
err_assert( window!=NULL );
string title = APP_TITLE " - Nuclear Fusion";
title = title + " " + GetEngineVersion();
SetWindowTitle( window, title.c_str() );
direct3d = ( IDirect3D9 * )GetDirect3D9Handle();
device = ( IDirect3DDevice9 * )GetDirect3D9DeviceHandle();
err_assert( direct3d!=NULL );
err_assert( device!=NULL );
NUKE vp = GetDefaultViewport();
SetViewportColor( vp, dxsb_color( BACKGROUND_COLOR ) );
SetDeveloperData( NDEV_VP3D_DRAWHOOK, &render_f, vp );
#if WORKAROUND_BUG1
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// !!! BUG !!!
// We *MUST* have an object in the scene for the render hook to be called
NUKE ent = MakeCube();
// The object *MUST* be visible too
NUKE cam = GetDefaultCamera();
PositionEnt( cam, 0, 3, 5 );
PointEntAtEnt( cam, ent );
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#endif
#if WORKAROUND_BUG3
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// !!! BUG !!!
// Text is required to see the texture
MakeText2D( "." );
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#endif
}
void dxsb_fini() {
device = NULL;
direct3d = NULL;
if( window!=NULL ) {
KillWindow( window );
window = NULL;
}
}
bool dxsb_loop() {
// engine says no?
bool r = Sync();
if( !r ) {
return false;
}
// check escape key
if( KeyHit( 1, window ) ) {
return false;
}
// continue along then
return true;
}
#else
//:::DIRECT3D-9:::--------------------------------------------------------------
LRESULT CALLBACK wnd_message_procedure( HWND hwnd, UINT msg, WPARAM wparm,
LPARAM lparm ) {
switch( msg ) {
case WM_CLOSE:
DestroyWindow( hwnd );
return 0;
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
}
return DefWindowProcA( hwnd, msg, wparm, lparm );
}
void dxsb_init() {
// register the window class
WNDCLASSEXA wndClass;
wndClass.cbSize = sizeof( wndClass );
wndClass.style = 0;
wndClass.lpfnWndProc = &wnd_message_procedure;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = GetModuleHandleA( NULL );
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
wndClass.hbrBackground = NULL;
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = "D3D9Sandbox";
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
err_assert( RegisterClassExA( &wndClass )!=0 );
// calculate the size the window should be
DWORD screenRes[ 2 ] = {
GetSystemMetrics( SM_CXSCREEN ),
GetSystemMetrics( SM_CYSCREEN )
};
RECT wndRect = {
0, 0,
SCREEN_RES_X, SCREEN_RES_Y
};
DWORD style = WS_CAPTION | WS_SYSMENU;
AdjustWindowRect( &wndRect, style, FALSE );
DWORD wndRes[ 2 ] = {
wndRect.right - wndRect.left,
wndRect.bottom - wndRect.top
};
DWORD wndPos[ 2 ] = {
screenRes[ 0 ]/2 - wndRes[ 0 ]/2,
screenRes[ 1 ]/2 - wndRes[ 1 ]/2
};
// create the window
#define WND_TITLE APP_TITLE " - Raw Direct3D"
window = CreateWindowExA( 0, "D3D9Sandbox", WND_TITLE, style, wndPos[ 0 ],
wndPos[ 1 ], wndRes[ 0 ], wndRes[ 1 ], NULL, NULL, NULL, NULL );
err_assert( window!=NULL );
#undef WND_TITLE
// create the direct3d object
direct3d = Direct3DCreate9( D3D_SDK_VERSION );
err_assert( direct3d!=NULL );
// create the direct3d device
D3DPRESENT_PARAMETERS presentParms;
presentParms.BackBufferWidth = SCREEN_RES_X;
presentParms.BackBufferHeight = SCREEN_RES_Y;
presentParms.BackBufferFormat = D3DFMT_A8R8G8B8;
presentParms.BackBufferCount = 1;
presentParms.MultiSampleType = D3DMULTISAMPLE_NONE;
presentParms.MultiSampleQuality = 0;
presentParms.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParms.hDeviceWindow = window;
presentParms.EnableAutoDepthStencil = FALSE;
presentParms.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
presentParms.Flags = 0;
presentParms.FullScreen_RefreshRateInHz = 0;
presentParms.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
HRESULT hr;
hr = direct3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_PUREDEVICE, &presentParms,
&device );
err_assert_hr( hr );
// display the window
ShowWindow( window, SW_SHOW );
UpdateWindow( window );
}
void dxsb_fini() {
if( device!=NULL ) {
device->Release();
device = NULL;
}
if( direct3d!=NULL ) {
direct3d->Release();
direct3d = NULL;
}
if( window!=NULL ) {
DestroyWindow( window );
window = NULL;
}
UnregisterClassA( "D3D9Sandbox", GetModuleHandleA( NULL ) );
}
bool dxsb_loop() {
// check if we get asked to leave
MSG message;
while( PeekMessageA( &message, NULL, 0, 0, PM_REMOVE ) ) {
TranslateMessage( &message );
DispatchMessageA( &message );
if( message.message==WM_QUIT ) {
return false;
}
}
// exit on escape key
if( GetAsyncKeyState( VK_ESCAPE ) ) {
return false;
}
// update input
err_assert( GetCursorPos( &lastCursorPos )==TRUE );
err_assert( ScreenToClient( window, &lastCursorPos )==TRUE );
// render
HRESULT hr;
hr = device->BeginScene();
err_assert_hr( hr );
device->Clear( 0, NULL, D3DCLEAR_TARGET, BACKGROUND_COLOR, 0, 0 );
render_f( NULL, false, 0 );
hr = device->EndScene();
err_assert_hr( hr );
hr = device->Present( NULL, NULL, NULL, NULL );
err_assert_hr( hr );
// success
return true;
}
#endif
//------------------------------------------------------------------------------
void NFCALL AppMain() {
dxsb_init();
stateblock_init();
texture_init();
while( dxsb_loop() ) {
}
texture_fini();
stateblock_fini();
dxsb_fini();
}
#if D3D9_MODE==1
int main() {
AppMain();
return EXIT_SUCCESS;
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) {
AppMain();
return EXIT_SUCCESS;
}
#endif