#1 Direct3D9, initialiseren.

 

Inleiding

 

Allereerst ga ik uitleggen wat ik allemaal van plan ben. Ik ga dus een serie tutorials schrijven over Direct3D. Dit is de eerste van een hele serie en deze gaat over het initialiseren van Direct3D en we zullen verder gaan op meshes, textures, lightning en nog veel meer.

 

Ik wil wel even duidelijk maken, dat ik op het moment ook nog Direct3D aan het leren ben. Ik schrijf ondertussen ook tutorials, terwijl ik dit leer. Dus er kunnen nog wat fouten of foute programmeer wijzes in zitten. Neem me dit a.u.b niet kwalijk.

 

Nu gauw de eerste tutorial.

 

Direct3D initialiseren

 

Ik neem aan dat jullie weten hoe DirectX in mekaar steekt, zo niet. Kijk dan even in een andere tutorial die ik heb geschreven. Hier ga ik ook op COM en dat soort zaken in. Ook staat daarin hoe je DirectX installeert en instelt.

 

Goed hier alvast de eerste stuk van de code.

 

[code]

 

/// INCLUDES ///

#include <d3d9.h>

#include <windows.h>

#include <windowsx.h>

 

/// DEFINES ///

#define WIN32_LEAN_AND_MEAN

#define WINDOW_CLASS_NAME "winclass1"

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

#define SafeRelease(pObject) if(pObject != NULL) {pObject->Release(); pObject=NULL;}

 

 

/// GLOBALS ///

HWND main_window_handle = NULL;

HINSTANCE main_instance = NULL;

 

/// Direct3D globals

LPDIRECT3D9 g_pd3d    = NULL;

LPDIRECT3DDEVICE9 g_pd3ddevice = NULL;

 

/// FUNCTIONS ///

HRESULT Init3D();

void Render();

void CleanUp();

 

[/code]

 

Goed, wat doen we hier nou. Eigenlijk niet heel veel. We maken wat dingen aan zodat we het straks iets makkelijker hebben en dat is wat we willen. Maak het je zelf niet moeilijk, hou het simpel. Dat werkt stukken makkelijker.

 

We hebben de standaar file includes, daar is nu dan d3d9.h bij gekomen. Bij de defines staan wel wat nieuwe dingen. Allereerst de KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) Hiermee controleren we of de gewenste toets is ingedrukt. De SafeRelease() zal ik later uitleggen, maar hiermee kunnen we veilig de Direct3D object loslaten.

 

Daarna declareren we een aantal functie die we straks gaan gebruiken.

 

Op naar het volgende stukje code.

 

//// INIT3D ////

HRESULT Init3D()

{

                // first create the main Direct3D object

                g_pd3d = Direct3DCreate9(D3D_SDK_VERSION);

                if(g_pd3d == NULL)

                {

                                return E_FAIL;

                }

 

                // get the current Display Mode

                D3DDISPLAYMODE d3ddm;

                if(FAILED(g_pd3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))

                {

                                return E_FAIL;

                }

 

                //Create a structure to hold the settings for our device

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));

 

    //Fill the structure.

    //We want our program to be windowed, and set the back buffer to a format

    //that matches our current display mode

    d3dpp.Windowed = TRUE;

    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

    d3dpp.BackBufferFormat = d3ddm.Format;

 

 

                // create 3D Device

                if(FAILED(g_pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, main_window_handle,

                                                                                                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3ddevice)))

                {

                                return E_FAIL;

                }

                return S_OK;

}

 

Dit is als het goed is nieuw voor je. Hier maken we dus het hele Direct3D verhaal aan.

 

Allereerst maken we het hoofd Direct3D object aan, deze stoppen we in g_pd3d. Dit is niet veel anders dan met DirectDraw. Als het mislukt sturen we de foutmelding van DirectX terug. Goed nu hebben we dus een direct3d object, voordat we nu een device aan kunnen maken hebben we wat gegevens nodig. Even tussendoor een device is in dit geval dus de videokaart.

 

Nu gaan we wat gegevens verzamelen. We willen wat weten over de videokaart en daar komen we achter met behulp van de functie GetAdapterDisplayMode. Die gegevens stop je in een aparte pointer. Nu gaan we die gegevens aanpassen naar onze behoefte. We geven aan dat we in een window zitten etcetera.

 

Dan zijn we klaar om een device aan te maken. Wat we daarna doen en dan hebben we dus verbinding met de videokaart en kunnen we er mee doen wat we willen. Het echte teken werk gebeurt in de functie Render() die jullie hieronder kunnen zien.

 

 

 

 

 

//// RENDER ////

void Render()

{

                if(g_pd3ddevice == NULL)

                {

                                return;

                }

 

                // clear backbuffer to a blue color

                g_pd3ddevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

 

                // begin scene

                g_pd3ddevice->BeginScene();

 

                // render

 

                // end scene

                g_pd3ddevice->EndScene();

 

                // flip back en front buffer

                g_pd3ddevice->Present(NULL, NULL, NULL, NULL);

 

}

 

Zoals jullie kunnen zien gebeurt hier (nog) niet veel. Want we willen ook alleen maar een scherm met een blauwe achtergrond.

 

Als eerste controleren we of de device wel is aangemaakt, zoniet dan gaan we uit de functie. Bestaat hij wel, dan gaan we verder. In dit geval gaan we de backbuffer leegmaken en naar ons zin maken. We maken hem leeg en zetten blauwe achtergrond neer.

 

Op het eind wisselen we de back en de front buffer met elkaar en voila het beeld is te zien.

 

De back buffer is de teken buffer, de front buffer is de buffer die je ziet op je monitor.

 

Dan gaan we nu het spul opruimen met behulp van de CleanUp functie.

 

//// CLEAN UP ////

void CleanUp()

{

                SafeRelease(g_pd3ddevice);

                SafeRelease(g_pd3d);

}

 

Hier komt dus de SafeRelease() macro naar boven. Zoals je ziet krijg je op zo'n manier een lekkere compacte functie en het bespaart je later veel typ werk. De SafeRelease controleert allereerst op de pointer bestaat, dis is uit voorzorg. Want als je probeert een pointer te verwijderen die niet bestaat geeft dat problemen. Dan releast hij hem en daarna word de pointer op NULL in gesteld.

 

En dit was eigenlijk het hele Direct3D verhaal. Hieronder staat de hele source met het windows verhaal erbij. Voor uitleg van dat moet je bij mijn windows artikel wezen.

 

Voor meer vragen over Direct3D of deze tutorial, stel ze in het forum.

 

Groetjes,

Paul

Contact: ICQ -> 57088090

               E-Mail: paul@dancecore.nl

/// INCLUDES ///

#include <d3d9.h>

#include <windows.h>

#include <windowsx.h>

 

/// DEFINES ///

#define WIN32_LEAN_AND_MEAN

#define WINDOW_CLASS_NAME "winclass1"

#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)

#define SafeRelease(pObject) if(pObject != NULL) {pObject->Release(); pObject=NULL;}

 

 

/// GLOBALS ///

HWND main_window_handle = NULL;

HINSTANCE main_instance = NULL;

 

/// Direct3D globals

LPDIRECT3D9 g_pd3d    = NULL;

LPDIRECT3DDEVICE9 g_pd3ddevice = NULL;

 

/// FUNCTIONS ///

HRESULT Init3D();

void Render();

void CleanUp();

 

//// INIT3D ////

HRESULT Init3D()

{

                // first create the main Direct3D object

                g_pd3d = Direct3DCreate9(D3D_SDK_VERSION);

                if(g_pd3d == NULL)

                {

                                return E_FAIL;

                }

 

                // get the current Display Mode

                D3DDISPLAYMODE d3ddm;

                if(FAILED(g_pd3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))

                {

                                return E_FAIL;

                }

 

                //Create a structure to hold the settings for our device

    D3DPRESENT_PARAMETERS d3dpp;

    ZeroMemory(&d3dpp, sizeof(d3dpp));

 

    //Fill the structure.

    //We want our program to be windowed, and set the back buffer to a format

    //that matches our current display mode

    d3dpp.Windowed = TRUE;

    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

    d3dpp.BackBufferFormat = d3ddm.Format;

 

 

                // create 3D Device

                if(FAILED(g_pd3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, main_window_handle,

                                                                                                D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3ddevice)))

                {

                                return E_FAIL;

                }

                return S_OK;

}

 

//// RENDER ////

void Render()

{

                if(g_pd3ddevice == NULL)

                {

                                return;

                }

 

                // clear backbuffer to a blue color

                g_pd3ddevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);

 

                // begin scene

                g_pd3ddevice->BeginScene();

 

                // render

 

                // end scene

                g_pd3ddevice->EndScene();

 

                // flip back en front buffer

                g_pd3ddevice->Present(NULL, NULL, NULL, NULL);

 

}

 

//// CLEAN UP ////

void CleanUp()

{

                SafeRelease(g_pd3ddevice);

                SafeRelease(g_pd3d);

}

//// WINDOW PROC ////

 

LRESULT CALLBACK WinProc(HWND hwnd, UINT msg,

                                                                                              WPARAM wparam, LPARAM lparam)

{

                PAINTSTRUCT ps;

                HDC                                       hdc;

 

                switch(msg)

                {

                case WM_CREATE:

                                {

                                               // initialize stuff

                                               return 0;

                                }

                                break;

 

                case WM_PAINT:

                                {

                                               // validate window

                                               hdc = BeginPaint(hwnd,&ps);

 

                                               EndPaint(hwnd, &ps);

 

                                               // return succes

                                               return(0);

                                }

                                break;

                              

                case WM_DESTROY:

                                {

                                               // kill application

                                               CleanUp();

                                               PostQuitMessage(0);

 

                                               return (0);

                                }

                                break;

 

                default: break;

                } // end switch

 

                // treat not handled messages

                return (DefWindowProc(hwnd,msg, wparam, lparam));

 

}

 

//// WINMAIN ////

 

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance,

                                                                 LPSTR lpcmdline, int nshowcmd)

{

                WNDCLASSEX                   winclass;

                HWND                                   hwnd;

                MSG                                                      msg;

 

                // fill in the WNDCLASSEX

                winclass.cbSize = sizeof(WNDCLASSEX);

                winclass.style = CS_DBLCLKS | CS_OWNDC |

                          CS_HREDRAW | CS_VREDRAW;

                winclass.lpfnWndProc = WinProc;

                winclass.cbClsExtra = 0;

                winclass.cbWndExtra = 0;

                winclass.hInstance = hinstance;

                winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);

                winclass.hCursor = LoadCursor(NULL, IDC_ARROW);

                winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

                winclass.lpszMenuName = NULL;

                winclass.lpszClassName = WINDOW_CLASS_NAME;

                winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

 

                if(!RegisterClassEx(&winclass))

                                return(0);

               

                // create the window

 

                if (!(hwnd = CreateWindowEx(NULL, // extended style

                            WINDOW_CLASS_NAME, // class

                "3D Tutorial", // title

                WS_OVERLAPPEDWINDOW | WS_VISIBLE,

                 0,0, // initial x,y

                400,400, // initial width, height

                NULL, // handle to parent

                NULL, // handle to menu

                hinstance,// instance of this application

                NULL))) // extra creation parms

                return(0);

               

                // save information in globals

 

                main_window_handle = hwnd;

                main_instance = hinstance;

 

                // initialize Direct3D

                Init3D();

 

                // start the main loop

 

                while(TRUE)

                {

                                if(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))

                                {

                                               // is it a quit?

                                               if(msg.message == WM_QUIT)

                                                               break;

 

                                               // translate accelerator keys

                                               TranslateMessage(&msg);

 

                                               // send to window proc

                                               DispatchMessage(&msg);

                                } // end if

                                else

                                {

                                               Render();

                                }

 

                } // end while

 

                return(msg.wParam);

} //end winmain