Initialiser rapidement DirectX 10.1 avec DXUT

1342671301_50721

Intro :

DXUT est un framework qui vous permet d’initialiser de manière plus rapide et plus simple DirectX 10 à travers des fonctions toutes prêtes.

Prérequis :

Savoir un peu initialiser DirectX.

Exemples :

Voici un exemple d’utilisation :


int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
    DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable );
    DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice );
    DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizedSwapChain );
    DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain );
    DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice );
    DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender );

    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackKeyboard( OnKeyboard );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );

    DXUTInit( true, true, NULL );
    DXUTSetCursorSettings( true, true );
    DXUTCreateWindow( L"DXUT - Introduction" );
    DXUTCreateDevice( true, 640, 480 );
    DXUTMainLoop();

    return DXUTGetExitCode();
}

On remarque bien que quelques lignes suffisent pour démarrer DirectX 10 avec DXUT.

Vous remarquerez aussi que l’on insère des fonctions en tant que paramètres : ce sont des fonctions callbacks (c’est-à-dire des fonctions qui sont appelées de manière interne par DirectX).

Explications :

Initialisation :


DXUTInit(bool, bool, WCHAR*, bool);

Le premier argument indique à DXUT d’interprêter ou non les arguments passés en ligne de comande :

BasicHLSL.exe -windowed -width:400 -height:300

Le deuxième argument indique à DXUT d’afficher ou non une boite de dialogue s’il une erreur à lieu.

Les deux autres arguments ne sont pas nécessaires pour comprendre.

Curseur de la souris :

Voici l’instruction pour configurer le curseur de souris.

DXUTSetCursorSettings(bool, bool);

Le premier paramètre indique à DXUT que le curseur doit ou non
être affichée en mode plein écran.

Le premier paramètre indique à DXUT que le curseur doit
être restreint ou non de traverser les bords de la fenêtre en mode plein écran.

Création d’une fenêtre :


DXUTCreateWindow(const WCHAR, HINSTANCE, HICON, HMENU, INT, INT);

Le premier argument spécifie le titre de la fenêtre.

Le deuxième argument spécifie l’handle de la fenêtre (on peut le mettre à NULL).

Le troisième argument spécifie à la fenêtre quelle icone utiliser (on peut le mettre à NULL aussi).

Les deux autres arguments ne sont pas nécessaires pour comprendre.

Création du device :


DXUTCreateDevice(bool, int, int); 

Le premier argument indique ou non si la fenêtre créée doit être en plein écran ou fenêtrée.

Les deux autres arguments indiquent la résolution (au mieux) de la fenêtre de rendu.

Par ailleurs, après cette instruction, DXUT choisira automatiquement la version de DirectX : D3D9 ou D3D10, selon les capacités du matériel.

Rendu :

Au final l’Instruction pour démarrer la boucle de rendu :


DXUTMainLoop();


Les fonctions Callbacks :

Maintenant pour utiliser DXUT on doit créer un fichier Callbacks.h où mettrez le code des fonctions nécessaire à DXUT :


ID3D10InputLayout* g_pVertexLayout = NULL;

struct SimpleVertex
{
    D3DXVECTOR3 Pos;
    D3DXVECTOR3 Colour;
};

bool CALLBACK IsD3D10DeviceAcceptable(UINT, UINT, D3D10_DRIVER_TYPE,
                                       DXGI_FORMAT, bool, void*);

HRESULT CALLBACK OnD3D10CreateDevice(ID3D10Device*, const DXGI_SURFACE_DESC*,
                                      void*);

HRESULT CALLBACK OnD3D10ResizedSwapChain(ID3D10Device*, IDXGISwapChain*,
                                          const DXGI_SURFACE_DESC*, void*);

void CALLBACK OnD3D10FrameRender(ID3D10Device*, double, float, void*);

void CALLBACK OnD3D10ReleasingSwapChain(void*);

void CALLBACK OnD3D10DestroyDevice(void*);

LRESULT CALLBACK MsgProc(HWND, UINT, WPARAM, LPARAM,
                         bool*, void*);

void CALLBACK OnKeyboard(UINT, bool, bool, void*);

void CALLBACK OnFrameMove(double, float, void*);

bool CALLBACK ModifyDeviceSettings(DXUTDeviceSettings*, void*);

 

Vous mettrez toutes les fonctions énumérées ici prochainement dans un fichier DXUTIntroduction.cpp

La première fonction callback :


// N'est pas utilisée
bool CALLBACK IsD3D10DeviceAcceptable(UINT Adapter, UINT Output, D3D10_DRIVER_TYPE DeviceType,
                                      DXGI_FORMAT BufferFormat, bool bWindowed, void* pUserContext)
{
    return true;
}

 

La deuxième fonction callback :

// Initialize le rendu DirectX
HRESULT CALLBACK OnD3D10CreateDevice(ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc,
                                      void* pUserContext)
{
    HRESULT hr = S_OK;

    // Définit le schéma d'entrée
    D3D10_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = sizeof(layout) / sizeof(layout[0]);

    // Créé le schéma d'entrée
    D3D10_PASS_DESC PassDesc;
    g_pTechnique->GetPassByIndex(0)->GetDesc(&PassDesc);
    V_RETURN( pd3dDevice->CreateInputLayout(layout, numElements, PassDesc.pIAInputSignature,
                                             PassDesc.IAInputSignatureSize, &g_pVertexLayout));

    // Set the input layout
    pd3dDevice->IASetInputLayout(g_pVertexLayout);

    SimpleVertex vertices[] =
    {
        { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 1.0f ) },
        { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ) },
        { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR4( 0.0f, 1.0f, 1.0f, 1.0f ) },
        { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ) },
        { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 1.0f, 1.0f ) },
        { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR4( 1.0f, 1.0f, 0.0f, 1.0f ) },
        { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ) },
        { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 1.0f ) },
    };

    D3D10_BUFFER_DESC bd;
    bd.Usage = D3D10_USAGE_DEFAULT;
    bd.ByteWidth = sizeof(SimpleVertex) * 24;
    bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    bd.MiscFlags = 0;
    D3D10_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = vertices;
    V_RETURN( pd3dDevice->CreateBuffer(&bd, &InitData, &g_pVertexBuffer));

    // Définit le vertex buffer
    UINT stride = sizeof(SimpleVertex);
    UINT offset = 0;
    pd3dDevice->IASetVertexBuffers(0, 1, &g_pVertexBuffer, &stride, &offset);

    // Set primitive topology
    pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    return S_OK;
}

 

La troisième fonction callback :

HRESULT CALLBACK OnD3D10ResizedSwapChain(ID3D10Device* pd3dDevice, IDXGISwapChain* pSwapChain,
                                          const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext)
{
    return S_OK;
}

 

La quatrième fonction callback :

// Appelée à chaque étape de boucle de rendu
void CALLBACK OnD3D10FrameRender(ID3D10Device* pd3dDevice, double fTime,
                                 float fElapsedTime, void* pUserContext)
{
    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f };
    ID3D10RenderTargetView* pRTV = DXUTGetD3D10RenderTargetView();
    pd3dDevice->ClearRenderTargetView( pRTV, ClearColor );

    ID3D10DepthStencilView* pDSV = DXUTGetD3D10DepthStencilView();
    pd3dDevice->ClearDepthStencilView( pDSV, D3D10_CLEAR_DEPTH, 1.0, 0 );

    pd3dDevice->Draw(3, 0);
}

 

La cinquième fonction callback :

// N'est pas utilisée
void CALLBACK OnD3D10ReleasingSwapChain(void* pUserContext)
{
}

 

La sixième fonction callback :


// Détruit les composants de DirectX
void CALLBACK OnD3D10DestroyDevice( void* pUserContext )
{
    g_pVertexLayout->Release();
    g_pVertexLayout = NULL.
}

 

La septième fonction callback :


// N'est pas utilisée
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
    return true;
}

 

La huitième fonction callback :


LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
                          void* pUserContext )
{
    return 0;
}

 

La dernière fonction callback :


void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
    if( bKeyDown )
    {
        switch( nChar )
        {
            case VK_F1: // Change as needed                
                break;
        }
    }
}

 

Résumé :

DXUT vous permet de restreindre d’initialiser de manière laborieuse DirectX 10.
Vous pouvez retrouver le code source de ce petit tutoriel ici.

Références :

Documentation DirectX SDK June 2010

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *