Aqui estão alguns programas de exemplo em DirectX 9. Eles foram retirados do DirectX SDK de fevereiro de 2010, sendo que a alteração realizada foi a tradução dos comentários de inglês para português.
Esta aplicação foi feita criando-se um novo projeto no MSVC++ Express 2008 escolhendo a opção programa Win32 e projeto vazio. Contudo, para facilitar o próprio DirectX SDK já traz esta amostra pronta. Basta instalá-la diretamente do navegador de amostras e incluir os caminhos do DirectX onde necessários nas propriedades do projeto.
Obs: Alguns tutoriais requerem arquivos extras como modelos .x e figuras .bmp. Provavelmente eles serão colocados aqui em outra oportunidade
|
Table of Contents
|
Tutorial 1 do DX 9 no DX SDK - Criação de janela D3D
#include <d3d9.h> #include <strsafe.h> #include <windows.h> //#pragma warning( disable : 4996 ) // disable deprecated warnings LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; HRESULT InitD3D( HWND hWnd ){ // cria o objeto D3D, que é necessário para criar o D3DDeevice. if( NULL == (g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Configura a estrutura usada para criar o D3DDevice. A maioria dos parâmetros são // zerados. Nós configuraremos Windowed para TRUE, desde que nós queremos D3D em uma // janela, e então configuraremos o SwapEffect para "descarte", que é o método mais // eficiente de apresentar o buffer de trás (back buffer) para a exibição. E nós // requisitamos um formato do buffer traseiro que combina o atual formato de // exibição do desktop D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Crie o dispositivo Direct3D. Aqui nós estamos usando o adaptador padrão ( A maioria dos // sistemas tem só um, a menos que eles tenham múltiplos placas de hardware gráficas // instalados ) e pedimos ao HAL ( que é dizer que nós queremos o dispositivo de hardware // ao invés de um de software ). Processamento vértice de software é especificado desde que // nós sabemos que ele funcionará em todas as placas. Contudo, nas placas que suportam processamento // vértice por hardware, nós veríamos um grande ganho de desempenho por especificar processamento // de vértice por hardware. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ){ return E_FAIL; } // Estado do dispositivo normalmente seria colocado aqui return S_OK; } // Libera todos os objetos inicializados anteriormente VOID Cleanup(){ if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Desenha a cena VOID Render(){ if( NULL == g_pd3dDevice ) return ; // limpa o buffer de trás para uma cor azul g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Inicia a cena if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // renderização dos objetos da cena pode acontecer aqui // termina a cena g_pd3dDevice->EndScene(); } // Apresenta os conteúdos do buffer de trás para a exibição g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // o tratador de mensagem da janela LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ){ case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } // o ponto de entrada da aplicação INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevInstance, LPSTR CmdLine, INT nShowCmd ){ // Registra a classe da janela WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"Direct3D Tutorial", NULL }; RegisterClassEx( &wc ); // Cria a janela da aplicação HWND hWnd = CreateWindow( L"Direct3D Tutorial", L"Direct3D Tutorial 01: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL ); // Inicializa Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ){ // Mostre a janela ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Entre no loop de mensagem MSG msg; while( GetMessage( &msg, NULL, 0, 0) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; }
Tutorial 2 DX9 - DX SDK - Criação de um triângulo
//#include <cstdio> #include <d3d9.h> #include <strsafe.h> #include <windows.h> //#pragma warning( disable : 4996 ) // disable deprecated warnings LPDIRECT3D9 g_pD3D = NULL; // Usada para criar o D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Nosso dispositivo de renderização LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer para armazenar vértices // Uma estrutura para nosso tipo de vértice customizado struct CUSTOMVERTEX{ FLOAT x, y, z, rhw; // A posição transformada para o vértice DWORD color; // A cor do vértice }; // Nosso FVF (Formato de Vértice Flexível) customizado que descreve // nossa estrutura de vértice customizada #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) HRESULT InitD3D( HWND hWnd ){ // cria o objeto D3D, que é necessário para criar o D3DDeevice. if( NULL == (g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Configura a estrutura usada para criar o D3DDevice. A maioria dos parâmetros são // zerados. Nós configuraremos Windowed para TRUE, desde que nós queremos D3D em uma // janela, e então configuraremos o SwapEffect para "descarte", que é o método mais // eficiente de apresentar o buffer de trás (back buffer) para a exibição. E nós // requisitamos um formato do buffer traseiro que combina o atual formato de // exibição do desktop D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Crie o dispositivo Direct3D. Aqui nós estamos usando o adaptador padrão ( A maioria dos // sistemas tem só um, a menos que eles tenham múltiplos placas de hardware gráficas // instalados ) e pedimos ao HAL ( que é dizer que nós queremos o dispositivo de hardware // ao invés de um de software ). Processamento vértice de software é especificado desde que // nós sabemos que ele funcionará em todas as placas. Contudo, nas placas que suportam processamento // vértice por hardware, nós veríamos um grande ganho de desempenho por especificar processamento // de vértice por hardware. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ){ return E_FAIL; } // Estado do dispositivo normalmente seria colocado aqui return S_OK; } // Cria um buffer de vértice e preenche ele com nossos vértices. O buffer de vértice é basicamente // apenas um pedaço de memória que armazena vértices. Depois de criá-lo, nós devemos travar // ( Lock() )/ e destravar ( Unlock() ) ele para preenchê-lo. Para índices, D3D também usa buffers de // índice. A coisa especial sobre vértice e buffers de índice é que eles podem ser criados na memória // do dispositivo, permitindo algumas placas processá-los em hardware, resultando em um ganho de // desempenho dramático. HRESULT InitVB(){ // Inicializa três vértices para renderizar um triângulo CUSTOMVERTEX vertices[] = { { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, }, { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, } }; // Cria o buffer de vértices. Aqui nós estamos alocando memória (do pool padrão) para armazenar // todos os nossos 3 vértices. Onde nós também especificamos o FVF, então o buffer de vértice // conhece que dado ele contém if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) ) ){ return E_FAIL; } // Agora nós preenchemos o buffer de vértice. Para fazer isso, nós precisamos travar ( lock() ) // o VB para ganhar acesso aos vértices. Este mecanismo é requerido porque buffers de // vértice podem estar na memória do equipamento VOID *pVertices; if( FAILED( g_pVB->Lock( 0, sizeof( vertices ), ( void** ) &pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, vertices, sizeof( vertices ) ); g_pVB->Unlock(); return S_OK; } // Libera todos os objetos inicializados anteriormente VOID Cleanup(){ if( g_pVB != NULL ) g_pVB->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Desenha a cena VOID Render(){ if( NULL == g_pd3dDevice ) return ; // limpa o buffer de trás para uma cor azul g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Inicia a cena if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Desenha os triângulos no buffer de vértice. Isto é quebrado em alguns passos. // Nós estamos passando o vértice abaixo para um "fluxo", então primeiro nós // precisamos especificar a origem daquele fluxo, que é nosso buffer de vértice. // Então nós precisamos deixar D3D saber qual shader vértice usar. Shader vértice // completo, customizado são um tópico avançado, mas na maioria dos casos o shader // vértice é apenas o FVF, para que D3D saiba que tipo de vértices nós estamos // lidando. Finalmente, nós chamamos DrawPrimitive() que faz a renderização // verdadeira de nossa geometria (neste caso, apenas um triângulo) g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); // termina a cena g_pd3dDevice->EndScene(); } // Apresenta os conteúdos do buffer de trás para a exibição g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // o tratador de mensagem da janela LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ){ case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } // o ponto de entrada da aplicação INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevInstance, LPSTR CmdLine, INT nShowCmd ){ // Registra a classe da janela WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"Direct3D Tutorial", NULL }; RegisterClassEx( &wc ); // Cria a janela da aplicação HWND hWnd = CreateWindow( L"Direct3D Tutorial", L"Direct3D Tutorial 02: Vertices", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); // Inicializa Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ){ // Cria o buffer de vértice if( SUCCEEDED( InitVB() ) ){ // Mostre a janela ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Entre no loop de mensagem MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ){ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else{ Render(); } } } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; }
Tutorial 3 DX9 - DXSDK - Matrizes
// Este arquivo contém uma aplicação Win32 que cria uma janela e // um D3D9 Device //#include <cstdio> #include <d3dx9.h> #include <strsafe.h> #include <windows.h> //#pragma warning( disable : 4996 ) // disable deprecated warnings LPDIRECT3D9 g_pD3D = NULL; // Usada para criar o D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Nosso dispositivo de renderização LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer para armazenar vértices // Uma estrutura para nosso tipo de vértice customizado struct CUSTOMVERTEX{ FLOAT x, y, z; // A posição transformada para o vértice DWORD color; // A cor do vértice }; // Nosso FVF (Formato de Vértice Flexível) customizado que descreve // nossa estrutura de vértice customizada #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) HRESULT InitD3D( HWND hWnd ){ // cria o objeto D3D, que é necessário para criar o D3DDeevice. if( NULL == (g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Configura a estrutura usada para criar o D3DDevice. A maioria dos parâmetros são // zerados. Nós configuraremos Windowed para TRUE, desde que nós queremos D3D em uma // janela, e então configuraremos o SwapEffect para "descarte", que é o método mais // eficiente de apresentar o buffer de trás (back buffer) para a exibição. E nós // requisitamos um formato do buffer traseiro que combina o atual formato de // exibição do desktop D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Crie o dispositivo Direct3D. Aqui nós estamos usando o adaptador padrão ( A maioria dos // sistemas tem só um, a menos que eles tenham múltiplos placas de hardware gráficas // instalados ) e pedimos ao HAL ( que é dizer que nós queremos o dispositivo de hardware // ao invés de um de software ). Processamento vértice de software é especificado desde que // nós sabemos que ele funcionará em todas as placas. Contudo, nas placas que suportam processamento // vértice por hardware, nós veríamos um grande ganho de desempenho por especificar processamento // de vértice por hardware. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ){ return E_FAIL; } // Desativa o culling, então nós vemos a frente a traseira do triângulo g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // Desativa a iluminação do D3D, desde que nós estamos fornecendo nossas próprias cores de vértice g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); return S_OK; } // cria a geometria da cena HRESULT InitGeometry(){ // Inicializa três vértices para renderizar um triângulo CUSTOMVERTEX g_Vertices[] = { { -1.0f, -1.0f, 0.0f, 0xffff0000, }, { 1.0f, -1.0f, 0.0f, 0xff0000ff, }, { 0.0f, 1.0f, 0.0f, 0xffffffff, } }; // Cria o buffer de vértices. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) ) ){ return E_FAIL; } // Preenche o buffer de vértice. VOID *pVertices; if( FAILED( g_pVB->Lock( 0, sizeof( g_Vertices ), ( void** ) &pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, g_Vertices, sizeof( g_Vertices ) ); g_pVB->Unlock(); return S_OK; } // Libera todos os objetos inicializados anteriormente VOID Cleanup(){ if( g_pVB != NULL ) g_pVB->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Configura as matriz de transformação de projeção, visão e de mundo VOID SetupMatrices(){ // Para nossa matriz de mundo, nós simplesmente rotacionaremos o objeto // ao redor do eixo y D3DXMATRIXA16 matWorld; // Configura a matriz de rotação para gerar 1 rotação completa (2*PI radianos) // a cada 1000 ms. Para evitar a perda de precisão inerente em números de ponto // flutuante muito altos, o tempo do sistema é modulado pelo período da rotação // antes da conversão para um ângulo de radianos; UINT iTime = timeGetTime() % 1000; float fAngle = iTime * ( 2.0f * D3DX_PI ) / 1000.0f; D3DXMatrixRotationY( &matWorld, fAngle ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); // Configure nossa matriz de visualização. Uma matriz de visualização pode ser definida // dado uma posição do olho, um ponto para o qual olhar, e uma direção a qual aponta // para cima. Aqui nós configuramos o olho cinco unidades atrás do eixo z e para cima // três unidades, olhar na origem, e definimos que "para cima" está na direção do eixo y D3DXVECTOR3 vEyePt( 0.0f, 3.0f, -5.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); // para a matriz de projeção, nós configuramos uma transformação perspectiva (que transforma // geometria do espaço de visão 3D para o espaço de porto de visão (viewport) 2D, com uma // divisão perspectiva fazendo objetos menores à distância). Para construir uma transformação // perspectiva, nós precisamos do campo de visão (1/4 de pi é comum), a taxa de aspecto, e os // planos de recorte near e far (que definem a qual distância as geometrias não deveriam mais // ser renderizadas). D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } // Desenha a cena VOID Render(){ // limpa o buffer de trás para uma cor preta g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 ); // Inicia a cena if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Configura as matrizes de projeção, mundo e visão SetupMatrices(); // Desenha os triângulos no buffer de vértice. Isto é quebrado em alguns passos. // Nós estamos passando o vértice abaixo para um "fluxo", então primeiro nós // precisamos especificar a origem daquele fluxo, que é nosso buffer de vértice. // Então nós precisamos deixar D3D saber qual shader vértice usar. Shader vértice // completo, customizado são um tópico avançado, mas na maioria dos casos o shader // vértice é apenas o FVF, para que D3D saiba que tipo de vértices nós estamos // lidando. Finalmente, nós chamamos DrawPrimitive() que faz a renderização // verdadeira de nossa geometria (neste caso, apenas um triângulo) g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); // termina a cena g_pd3dDevice->EndScene(); } // Apresenta os conteúdos do buffer de trás para a exibição g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // o tratador de mensagem da janela LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ){ case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } // o ponto de entrada da aplicação INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevInstance, LPSTR CmdLine, INT nShowCmd ){ // Registra a classe da janela WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"Direct3D Tutorial", NULL }; RegisterClassEx( &wc ); // Cria a janela da aplicação HWND hWnd = CreateWindow( L"Direct3D Tutorial", L"Direct3D Tutorial 03: Matrices", WS_OVERLAPPEDWINDOW, 100, 100, 256, 256, NULL, NULL, wc.hInstance, NULL ); // Inicializa Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ){ // Cria o buffer de vértice if( SUCCEEDED( InitGeometry() ) ){ // Mostre a janela ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Entre no loop de mensagem MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ){ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else{ Render(); } } } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; }
Tutorial 4 DX 9 - DXSDK - Luzes
// Este arquivo contém uma aplicação Win32 que cria uma janela e // um D3D9 Device //#include <cstdio> #include <d3dx9.h> #include <strsafe.h> #include <windows.h> #include <mmsystem.h> //#pragma warning( disable : 4996 ) // disable deprecated warnings LPDIRECT3D9 g_pD3D = NULL; // Usada para criar o D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Nosso dispositivo de renderização LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer para armazenar vértices // Uma estrutura para nosso tipo de vértice customizado struct CUSTOMVERTEX{ D3DXVECTOR3 position; // A posição 3D para o vértice D3DXVECTOR3 normal; // A cor do vértice }; // Nosso FVF (Formato de Vértice Flexível) customizado que descreve // nossa estrutura de vértice customizada #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL) // Inicializa Direct3D HRESULT InitD3D( HWND hWnd ){ // cria o objeto D3D if( NULL == (g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Configura a estrutura usada para criar o D3DDevice. Desde que agora nós estamos // usando geometria mais complexa, nós criaremos um dispositivo com zbuffer D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // Cria o dispositivo Direct3D. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ){ return E_FAIL; } // Desativa o culling, então nós vemos a frente a traseira do triângulo g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // Ativa o zbuffer g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); return S_OK; } // cria a geometria da cena HRESULT InitGeometry(){ // Cria o buffer de vértice if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50 * 2 * sizeof( CUSTOMVERTEX ), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) ) ){ return E_FAIL; } // Preenche o buffer de vértice. Nós estamos algoritmicamente gerando um cilindro // aqui, incluindo as normais, que são usadas para iluminação CUSTOMVERTEX* pVertices; if( FAILED( g_pVB->Lock( 0, 0, ( void** ) &pVertices, 0 ) ) ) return E_FAIL; for( DWORD i = 0; i < 50; i++ ){ FLOAT theta = (2 * D3DX_PI * i ) / (50 - 1); pVertices[ 2 * i + 0 ].position = D3DXVECTOR3( sinf(theta), -1.0f, cosf( theta )); pVertices[ 2 * i + 0 ].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf( theta )); pVertices[ 2 * i + 1 ].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf( theta )); pVertices[ 2 * i + 1 ].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf( theta )); } g_pVB->Unlock(); return S_OK; } // Libera todos os objetos inicializados anteriormente VOID Cleanup(){ if( g_pVB != NULL ) g_pVB->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Configura as matriz de transformação de projeção, visão e de mundo VOID SetupMatrices(){ // Configura a matriz do mundo D3DXMATRIXA16 matWorld; D3DXMatrixIdentity( &matWorld ); D3DXMatrixRotationX( &matWorld, timeGetTime() / 500.0f ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); // Configure nossa matriz de visualização. Uma matriz de visualização pode ser definida // dado uma posição do olho, um ponto para o qual olhar, e uma direção a qual aponta // para cima. Aqui nós configuramos o olho cinco unidades atrás do eixo z e para cima // três unidades, olhar na origem, e definimos que "para cima" está na direção do eixo y D3DXVECTOR3 vEyePt( 0.0f, 3.0f, -5.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); // para a matriz de projeção, nós configuramos uma transformação perspectiva (que transforma // geometria do espaço de visão 3D para o espaço de porto de visão (viewport) 2D, com uma // divisão perspectiva fazendo objetos menores à distância). Para construir uma transformação // perspectiva, nós precisamos do campo de visão (1/4 de pi é comum), a taxa de aspecto, e os // planos de recorte near e far (que definem a qual distância as geometrias não deveriam mais // ser renderizadas). D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } // configura as luzes e materiais para a cena VOID SetupLights(){ // Configura um material. O material aqui tem apenas as cores difusa e ambiente // configuradas para amarelo. Note que somente um material pode ser usado por vez. D3DMATERIAL9 mtrl; ZeroMemory( &mtrl, sizeof( D3DMATERIAL9 ) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; g_pd3dDevice->SetMaterial( &mtrl ); // Configura uma luz direcional, branca, com uma direção de oscilação. // Note que muitas luzes podem estar ativas por vez (mas cada uma // torna mais lenta a renderização de nossa cena). Entretanto, nós // estamos aqui usando apenas uma. Também, nós precisamos configurar // o estado de renderização D3DRS_LIGHTING para habilitar a iluminação D3DXVECTOR3 vecDir; D3DLIGHT9 light; ZeroMemory( &light, sizeof( D3DLIGHT9 ) ); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = light.Diffuse.g = light.Diffuse.b = 1.0f; vecDir = D3DXVECTOR3( cosf( timeGetTime() / 350.0f ), 1.0f, sinf( timeGetTime() / 350.0f ) ); D3DXVec3Normalize( (D3DXVECTOR3 *)&light.Direction, &vecDir ); light.Range = 1000.0f; g_pd3dDevice->SetLight( 0, &light ); g_pd3dDevice->LightEnable( 0, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); // Finalmente ativa alguma luz ambiente g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 ); } // Desenha a cena VOID Render(){ // limpa o buffer de trás e o zbuffer g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Inicia a cena if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Configura as luzes e materiais SetupLights(); // Configura as matrizes de projeção, mundo e visão SetupMatrices(); // Renderiza os conteúdos do buffer de vcértice g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50 - 2 ); // termina a cena g_pd3dDevice->EndScene(); } // Apresenta os conteúdos do buffer de trás para a exibição g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // o tratador de mensagem da janela LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ){ case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } // o ponto de entrada da aplicação INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevInstance, LPSTR CmdLine, INT nShowCmd ){ // Registra a classe da janela WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"Direct3D Tutorial", NULL }; RegisterClassEx( &wc ); // Cria a janela da aplicação HWND hWnd = CreateWindow( L"Direct3D Tutorial", L"Direct3D Tutorial 04: Lights", WS_OVERLAPPEDWINDOW, 100, 100, 256, 256, NULL, NULL, wc.hInstance, NULL ); // Inicializa Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ){ // Cria o buffer de vértice if( SUCCEEDED( InitGeometry() ) ){ // Mostre a janela ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Entre no loop de mensagem MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ){ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else{ Render(); } } } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; }
Tutorial 5 DX9 - DXSDK - Colocando Texturas na cena
// Este arquivo contém uma aplicação Win32 que cria uma janela e // um D3D9 Device //#include <cstdio> #include <d3dx9.h> #include <strsafe.h> #include <windows.h> #include <mmsystem.h> //#pragma warning( disable : 4996 ) // disable deprecated warnings LPDIRECT3D9 g_pD3D = NULL; // Usada para criar o D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Nosso dispositivo de renderização LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer para armazenar vértices LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Nossa textura // #define SHOW_HOW_TO_USE_TC1 // descomente esta linha para ver TexCoords no espaço da câmera // Uma estrutura para nosso tipo de vértice customizado struct CUSTOMVERTEX{ D3DXVECTOR3 position; // A posição D3DCOLOR color; // A cor #ifndef SHOW_HOW_TO_USE_TC1 FLOAT tu, tv; // As coordenadas de textura #endif }; // Nosso FVF (Formato de Vértice Flexível) customizado que descreve // nossa estrutura de vértice customizada #ifdef SHOW_HOW_TO_USE_TC1 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) #else #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) #endif // Inicializa Direct3D HRESULT InitD3D( HWND hWnd ){ // cria o objeto D3D if( NULL == (g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Configura a estrutura usada para criar o D3DDevice. Desde que agora nós estamos // usando geometria mais complexa, nós criaremos um dispositivo com zbuffer D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // Cria o dispositivo Direct3D. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ){ return E_FAIL; } // Desativa o culling, então nós vemos a frente a traseira do triângulo g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // Desativa iluminação D3D g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); // Ativa o zbuffer g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); return S_OK; } // cria as texturas e os buffers de vértices HRESULT InitGeometry(){ // Usa D3DX para criar uma textura de uma imagem baseada em arquivo if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"banana.bmp", &g_pTexture ) ) ){ // se a textura não está na pasta atual, tente a pasta pai if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"..\\banana.bmp", &g_pTexture ) ) ){ MessageBox( NULL, L"Could not find banana.bmp", L"Textures.exe", MB_OK ); return E_FAIL; } } // Cria o buffer de vértice if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50 * 2 * sizeof( CUSTOMVERTEX ), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL) ) ){ return E_FAIL; } // Preenche o buffer de vértice. Nós estamos configurando a coordenadas de textura // tu e tv, que vão de 0.0 para 1.0 CUSTOMVERTEX* pVertices; if( FAILED( g_pVB->Lock( 0, 0, ( void** ) &pVertices, 0 ) ) ) return E_FAIL; for( DWORD i = 0; i < 50; i++ ){ FLOAT theta = (2 * D3DX_PI * i ) / (50 - 1); pVertices[ 2 * i + 0 ].position = D3DXVECTOR3( sinf(theta), -1.0f, cosf( theta )); pVertices[ 2 * i + 0 ].color = 0xffffffff; #ifndef SHOW_HOW_TO_USE_TC1 pVertices[ 2 * i + 0 ].tu = ( (FLOAT) i ) / (50 - 1); pVertices[ 2 * i + 0 ].tv = 1.0f; #endif pVertices[ 2 * i + 1 ].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf( theta )); pVertices[ 2 * i + 1 ].color = 0xff808080; #ifndef SHOW_HOW_TO_USE_TC1 pVertices[ 2 * i + 1 ].tu = ( (FLOAT) i ) / (50 - 1); pVertices[ 2 * i + 1 ].tv = 0.0f; #endif } g_pVB->Unlock(); return S_OK; } // Libera todos os objetos inicializados anteriormente VOID Cleanup(){ if( g_pTexture != NULL ) g_pTexture->Release(); if( g_pVB != NULL ) g_pVB->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Configura as matriz de transformação de projeção, visão e de mundo VOID SetupMatrices(){ // Configura a matriz do mundo D3DXMATRIXA16 matWorld; D3DXMatrixIdentity( &matWorld ); D3DXMatrixRotationX( &matWorld, timeGetTime() / 500.0f ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); // Configure nossa matriz de visualização. Uma matriz de visualização pode ser definida // dado uma posição do olho, um ponto para o qual olhar, e uma direção a qual aponta // para cima. Aqui nós configuramos o olho cinco unidades atrás do eixo z e para cima // três unidades, olhar na origem, e definimos que "para cima" está na direção do eixo y D3DXVECTOR3 vEyePt( 0.0f, 3.0f, -5.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); // para a matriz de projeção, nós configuramos uma transformação perspectiva (que transforma // geometria do espaço de visão 3D para o espaço de porto de visão (viewport) 2D, com uma // divisão perspectiva fazendo objetos menores à distância). Para construir uma transformação // perspectiva, nós precisamos do campo de visão (1/4 de pi é comum), a taxa de aspecto, e os // planos de recorte near e far (que definem a qual distância as geometrias não deveriam mais // ser renderizadas). D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } // Desenha a cena VOID Render(){ // limpa o buffer de trás e o zbuffer g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Inicia a cena if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Configura as matrizes de projeção, mundo e visão SetupMatrices(); // Configure nossa textura. Usando texturas introduz o estados de estágios de textura, // que governam como texturas são misturadas juntas (no caso de múltiplas texturas) e // informação de iluminação. Neste caso, nós estamos modulando (misturando) nossa // textura com a cor difusa dos vértices. g_pd3dDevice->SetTexture( 0, g_pTexture ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); #ifdef SHOW_HOW_TO_USE_TC1 // muito texto para traduzir, Fica para uma próxima :) D3DXMATRIXA16 mTextureTransform; D3DXMATRIXA16 mProj; D3DXMATRIXA16 mTrans; D3DXMATRIXA16 mScale; g_pd3dDevice->GetTransform( D3DTS_PROJECTION, &mProj ); D3DXMatrixTranslation( &mTrans, 0.5f, 0.5f, 0.0f ); D3DXMatrixScaling( &mScale, 0.5f, -0.5f, 1.0f ); mTextureTransform = mProj * mScale * mTrans; g_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mTextureTransform ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION ); #endif g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50 - 2 ); // termina a cena g_pd3dDevice->EndScene(); } // Apresenta os conteúdos do buffer de trás para a exibição g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // o tratador de mensagem da janela LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ){ case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } // o ponto de entrada da aplicação INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevInstance, LPSTR CmdLine, INT nShowCmd ){ // Registra a classe da janela WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"Direct3D Tutorial", NULL }; RegisterClassEx( &wc ); // Cria a janela da aplicação HWND hWnd = CreateWindow( L"Direct3D Tutorial", L"Direct3D Tutorial 05: Textures", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); // Inicializa Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ){ // Cria o buffer de vértice if( SUCCEEDED( InitGeometry() ) ){ // Mostre a janela ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Entre no loop de mensagem MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ){ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else{ Render(); } } } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; }
Tutorial 6 DX9 - DXSDK - Malhas
// Este arquivo contém uma aplicação Win32 que cria uma janela e // um D3D9 Device //#include <cstdio> #include <d3dx9.h> #include <strsafe.h> #include <windows.h> #include <mmsystem.h> //#pragma warning( disable : 4996 ) // disable deprecated warnings LPDIRECT3D9 g_pD3D = NULL; // Usada para criar o D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Nosso dispositivo de renderização LPD3DXMESH g_pMesh = NULL; // Nosso objeto malha no sistema D3DMATERIAL9* g_pMeshMaterials = NULL; // Materiais para nossa malha LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // Texturas para nossa malha DWORD g_dwNumMaterials = 0L; // Número de materiais da malha // Inicializa Direct3D HRESULT InitD3D( HWND hWnd ){ // cria o objeto D3D if( NULL == (g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Configura a estrutura usada para criar o D3DDevice. Desde que agora nós estamos // usando geometria mais complexa, nós criaremos um dispositivo com zbuffer D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // Cria o dispositivo Direct3D. if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ){ return E_FAIL; } // Desativa o culling, então nós vemos a frente a traseira do triângulo g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff ); // Ativa o zbuffer g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); return S_OK; } // cria as texturas e os buffers de vértices HRESULT InitGeometry(){ LPD3DXBUFFER pD3DMtrlBuffer; // Carrega a malha do arquivo especificado if( FAILED( D3DXLoadMeshFromX( L"Tiger.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh) ) ){ // se a textura não está na pasta atual, tente a pasta pai if( FAILED( D3DXLoadMeshFromX( L"..\\Tiger.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh) ) ){ MessageBox( NULL, L"Could not find tiger.x", L"Meshes.exe", MB_OK ); return E_FAIL; } } // Nós precisamos extrair as propriedades do material e os nomes de textura // do pD3DMtrlBuffer D3DXMATERIAL *d3dxMaterials = (D3DXMATERIAL*) pD3DMtrlBuffer->GetBufferPointer(); g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials]; if( g_pMeshMaterials == NULL ) return E_OUTOFMEMORY; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials]; if( g_pMeshTextures == NULL ) return E_OUTOFMEMORY; for( DWORD i = 0; i < g_dwNumMaterials; i++ ){ // Copie o material g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D; // Configure a cor ambiente para o material (D3DX não faz isso) g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse; g_pMeshTextures[i] = NULL; if( d3dxMaterials[i].pTextureFilename != NULL && lstrlenA(d3dxMaterials[i].pTextureFilename ) > 0 ){ // Crie a textura if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice, d3dxMaterials[i].pTextureFilename, &g_pMeshTextures[i] ) ) ){ // se a textura não está na pasta atual, tente a pasta pai const CHAR* strPrefix = "..\\"; CHAR strTexture[MAX_PATH]; strcpy_s( strTexture, MAX_PATH, strPrefix ); strcat_s( strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename ); // se a textura não está na pasta atual, tente a pasta pai if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice, strTexture, &g_pMeshTextures[i] ) ) ){ MessageBox( NULL, L"Could not find texture map", L"Meshes.exe", MB_OK ); } } } } // Pronto com o buffer material pD3DMtrlBuffer->Release(); return S_OK; } // Libera todos os objetos inicializados anteriormente VOID Cleanup(){ if( g_pMeshMaterials != NULL ) delete [] g_pMeshMaterials; if( g_pMeshTextures != NULL ) { for( DWORD i = 0; i < g_dwNumMaterials; i++ ){ if( g_pMeshTextures[i] ) g_pMeshTextures[i]->Release(); } delete[] g_pMeshTextures; } if( g_pMesh != NULL ) g_pMesh->Release(); if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } // Configura as matriz de transformação de projeção, visão e de mundo VOID SetupMatrices(){ // Configura a matriz do mundo D3DXMATRIXA16 matWorld; D3DXMatrixRotationY( &matWorld, timeGetTime() / 1000.0f ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); // Configure nossa matriz de visualização. Uma matriz de visualização pode ser definida // dado uma posição do olho, um ponto para o qual olhar, e uma direção a qual aponta // para cima. Aqui nós configuramos o olho cinco unidades atrás do eixo z e para cima // três unidades, olhar na origem, e definimos que "para cima" está na direção do eixo y D3DXVECTOR3 vEyePt( 0.0f, 3.0f, -5.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); // para a matriz de projeção, nós configuramos uma transformação perspectiva (que transforma // geometria do espaço de visão 3D para o espaço de porto de visão (viewport) 2D, com uma // divisão perspectiva fazendo objetos menores à distância). Para construir uma transformação // perspectiva, nós precisamos do campo de visão (1/4 de pi é comum), a taxa de aspecto, e os // planos de recorte near e far (que definem a qual distância as geometrias não deveriam mais // ser renderizadas). D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } // Desenha a cena VOID Render(){ // limpa o buffer de trás e o zbuffer g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 ); // Inicia a cena if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Configura as matrizes de projeção, mundo e visão SetupMatrices(); // Malhas são sundivididas em subconjuntos, um para cada material. // Renderize elas em um loop for( DWORD i = 0; i < g_dwNumMaterials; i++ ){ // Configure o material e a textura para este subconjunto g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] ); g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] ); // Desenha o subconjunto da malha g_pMesh->DrawSubset( i ); } // termina a cena g_pd3dDevice->EndScene(); } // Apresenta os conteúdos do buffer de trás para a exibição g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // o tratador de mensagem da janela LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ){ switch( msg ){ case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } // o ponto de entrada da aplicação INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE prevInstance, LPSTR CmdLine, INT nShowCmd ){ // Registra a classe da janela WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"Direct3D Tutorial", NULL }; RegisterClassEx( &wc ); // Cria a janela da aplicação HWND hWnd = CreateWindow( L"Direct3D Tutorial", L"Direct3D Tutorial 06: Meshes", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); // Inicializa Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ){ // Cria o buffer de vértice if( SUCCEEDED( InitGeometry() ) ){ // Mostre a janela ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Entre no loop de mensagem MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ){ if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else{ Render(); } } } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; }
Como configurar o DX9 Para funcionar com o WxWidgets
É Só seguir o mesmo raciocínio que o dos exemplos mostrados acima. Basta para isso chamar o método GetHWND da instância de WxFrame (eu não testei se funciona nos outros controles) e fazer um cast para HWND. O código abaixo mostra uma seqüência para criar a janela WxWidgets com suporte a DX 9:
TesteWxWidgetsFrame* frame = new TesteWxWidgetsFrame(0L, _("wxWidgets Application Template")); frame->SetIcon(wxICON(aaaa)); // To Set App Icon HWND hWnd = (HWND) frame->GetHWND(); HRESULT res = setupDirectX( hWnd ); if( res != S_OK ) { Cleanup(); frame->Destroy(); exit(-1); } frame->Show(); return true;
Para mostra o render na janela é só adicionar um paintEvent e não se esquecer da linha de criação do wxPaintDC. Caso esta linha seja esquecida a tua aplicação irá dar um erro no deixar sair, ficando travada ou simplesmente dará um crash nela.
void TesteWxWidgetsFrame::OnPaint(wxPaintEvent& event){ wxPaintDC dc( this ); Render(); }
Para baixar o exemplo apenas clique no link que se segue TesteWxWidgets.zip. Ele é um projeto que fiz no CodeBlocks. Você terá que alterar o local onde estão os arquivos do DirectX e do WxWidgets para refletir a sua instalação





