Curso completo de DirectX 9 com C\C++
Gameprog - Escola de programação de jogos digitais
Contato: gameprog.br@gmail.com
Fase 07-2

index << >>


07.2 Renderização da cena na textura

1.1 Visão geral
É possível renderizar a cena na textura e isso permite a criação de vários efeitos visuais interessantes; entre muitas possibilidades podemos citar a simulação de um espelho retrovisor em um jogo de corrida, um mapa ou um radar na tela, uma simulação de um raio-x, a visualização de uma segunda câmera focando uma outra parte do mundo virtual ou simplesmente a colocação de informações do jogo na tela. Neste processo de renderizar na textura, a textura se transforma numa segunda tela e isso envolve o mesmo trabalho que se tem de fazer na renderização comum configurando cameras, luzes e outros detalhes para produzir a imagem final que vai para a textura. Por fim a textura é colocada numa sprite para ser exibida na tela primária. 1.2 Estrutura principal da aplicação
Arquivo: motor.cpp
inicializar_texRenderizador() cria o objeto da interface ID3DXRenderToSurface que renderiza em textura cria a textura alvo cria o objeto IIDirect3DSurface9 para acessar a superfície da textura alvo pinta a superfície da textura alvo de vermelho cria uma sprite para receber a textura alvo renderizar_naTextura() configura uma janela de visualização inicia a renderização com o objeto da interface ID3DXRenderToSurface renderiza o modelo 3d em forma de pontos finaliza a renderização com o objeto da interface ID3DXRenderToSurface renderizarSprite() configura cor difusa da sprite como branco inicializa a renderização da sprite configura posição da sprite na tela renderiza a sprite com a textura que recebeu a cena finaliza renderização da sprite desenharObjeto() Esta função vai renderizar na tela o objeto da interface ID3DXMesh. Isso envolve a configuração das matrizes parciais de rotação, posição e escala; produzir a matriz final com as matrizes parciais; jogar a matriz final no dispositivo renderizador; configurar o material e textura renderizar o subset zero(0) initGfx() chama configurar_cenaEstados() para preparação inicial da cena. chama inicializar_Camera() para a configuração inicial da câmera chama CarregarModeloTiny() para carregar o modelo 3d. chama inicializar_texRenderizador() para inicializar os objetos envolvidos no processo de renderizar na textura. Renderizar() Limpa a tela chama renderizar_naTextura() para renderizar a cena na textura chama desenharObjeto() para renderizar o modelo 3d. chama renderizarSprite() para apresentar a textura que recebeu a cena Apresenta a cena Limpar() Libera a interface de textura utilizada do modelo 3d Libera a memória alocada para o material Libera o objeto da interface de sprite Libera o objeto da interface que renderiza na textura Libera o objeto da textura alvo Libera o objeto da superfície alvo Libera o objeto da interface ID3DXMesh Libera dispositivo renderizador Libera objeto Direct3d Anula todos os ponteiros utilizados
2.1.1. Aspectos globais - Arquivo: motor.h
//----------------------------------------------------------------------------- // Projeto: prj_Superficie - Arquivo: motor.h // Esta aplicação mostra como renderizar a cena na textura // By www.gameprog.com.br //----------------------------------------------------------------------------- #include <d3d9.h> #include <d3dx9.h> // Inclui as bibliotecas do Direct3D #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") // Desliga aviso de 'função insegura' devido ao uso das // funções de string ( strcat etc... ) #pragma warning( disable:4996 ) #ifndef motor_h #define motor_h // Estrutura para controle de rotação e posição do objeto struct Propriedades3d { D3DXVECTOR3 pos; D3DXVECTOR3 rot; }; // Esta função inicializa o Direct3D HRESULT initGfx (HWND hJanela); // Essa função libera os objetos utilizados void Limpar(); // Essa função desenha a cena void Renderizar(); // Monta a câmera da aplicação void inicializar_Camera(void); // Desenha o modelo 3d void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props); // Carrega o modelo tiny.x void CarregarModeloTiny(void); // Configura alguns estados da cena void configurar_cenaEstados(void); // Inicializa os objetos envolvidos na renderização // da cena na textura void inicializar_texRenderizador(void); // Renderiza a cena na textura void renderizar_naTextura(void); // Renderiza a sprite na tela void renderizarSprite(); // Salva o backbuffer como arquivo de imagem no disco void salvarImagem(void); // Declaração da função que atende as mensagens da janela LRESULT CALLBACK processaJanela ( HWND hJanela, UINT mensagem, WPARAM wParam, LPARAM lParam); #endif
HRESULT initGfx (HWND hJanela); Além de inicializar o motor gráfico initGfx() chama as funções que fazem a preparação inicial do ambiente como a configuração da câmera, a configuração inicial da cena e o carregamento do modelo 3d. Na sequência da preparação inicial vem inicializar_texRenderizador() que inicializa todos os objetos envolvidos no processo de renderizar a cena textura. void Limpar(); A cada nova interface explorada essa função ganha respectivamente um novo objeto para ser liberado. void Renderizar(); Essa função coordena a renderização da cena e esse processo começa primeiro com a renderização da cena na textura. A textura que sofreu a renderização vai para dentro de uma sprite para poder ser exibida. Na sequência essa função renderiza o modelo 3d, mostra a sprite texturizada e apresenta a cena finalmente. void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props); Essa função renderiza o objeto 3d. Essa função é chamada primeiro por renderizar_naTextura() e depois por Renderizar() respectivamente ocorrendo a renderização da cena na textura e depois no backbuffer. void inicializar_texRenderizador(void); Essa função inicializa os objetos envolvidos na renderização da cena na textura. Isso envolve criar o objeto da interface que renderiza na textura via D3DXCreateRenderToSurface(), a criação da textura alvo da renderização, o objeto que representa a superfície da textura e a sprite que recebe a textura com a cena renderizada. void renderizar_naTextura(void); Essa função renderiza a cena na textura. Essa função clona o universo da função Renderizar() uma vez que ela replica todos os processos e cuidados envolvidos na renderização da cena na textura. void renderizarSprite(); Essa função renderiza no backbuffer a sprite com a textura que recebeu a cena. void salvarImagem(void); Essa função mostra como salvar o backbuffer como arquivo de imagem no disco. LRESULT CALLBACK processaJanela ( // (...) ) Essa função, no pressionamento da tecla espaço, vai executar a função salvarImagem() para gravar uma foto do backbuffer no disco. 2.1.2 Aspectos globais - Arquivo: motor.cpp
// Objetos para o contexto de renderizar na textura IDirect3DTexture9 *g_texturaAlvo = NULL; ID3DXRenderToSurface *g_texRenderizador = NULL; IDirect3DSurface9 *g_superficieAlvo = NULL; ID3DXSprite *g_radar = NULL; // Tamanho da textura desejada 256x256 UINT g_texTam = 256;
ID3DXRenderToSurface *g_texRenderizador = NULL; Essa variável equivale ao dispositivo renderizador com a diferença de que opera sobre a superfície de uma textura. IDirect3DTexture9 *g_texturaAlvo = NULL; Essa é a textura da qual a superfície vai ser aproveitada para receber a renderização da cena. Essa textura vai ser criada pela aplicação e vai ter uma superfície quadrada com o tamanho dado por g_texTam (256). IDirect3DSurface9 *g_superficieAlvo = NULL; Esse objeto vai dar acesso à superfície da textura que vai receber a renderização da cena. ID3DXSprite *g_radar = NULL; Essa é a sprite que vai ser utilizada para mostrar a textura renderizada na tela. UINT g_texTam = 256; Esse é o tamanho da textura que vai operar como um 'backbuffer'. 2.2 Inicializando o processo de renderizar na textura
void inicializar_texRenderizador(void) { // Inicializa o Renderizador D3DFORMAT texFormato = D3DFMT_X8R8G8B8; g_hr = D3DXCreateRenderToSurface(g_device, g_texTam, g_texTam, texFormato, true, D3DFMT_D16, &g_texRenderizador ); if(FAILED(g_hr) ) { MessageBox(NULL, "falha: g_texRenderizador", "inicializar_texRenderizador()", MB_OK); } // endif // Cria uma textura alvo da renderização g_hr = D3DXCreateTexture(g_device, g_texTam, g_texTam, 1, D3DUSAGE_RENDERTARGET, texFormato, D3DPOOL_DEFAULT, &g_texturaAlvo); if (FAILED(g_hr) ) { MessageBox (NULL, "falha: g_texturaAlvo", "inicializar_texRenderizador()", MB_OK); return; } // endif // Acessa a superficie de dados da textura g_hr = g_texturaAlvo->GetSurfaceLevel (0, &g_superficieAlvo); if (FAILED(g_hr) ) { MessageBox (NULL, "falha: g_superficieAlvo", "inicializar_texRenderizador()", MB_OK); return; } // endif // Pinta a superficie da textura de vermelho g_device->ColorFill (g_superficieAlvo, NULL, 0xFFFF0000); // Cria uma sprite para a textura g_hr = D3DXCreateSprite(g_device, &g_radar); if (FAILED(g_hr) ) { MessageBox (NULL, "falha: D3DXCreateSprite()", "inicializar_texRenderizador()", MB_OK); return; } // endif } // inicializar_texRenderizador().fim
D3DFORMAT texFormato = D3DFMT_X8R8G8B8; Este formato de superfície vai servir para configurar o renderizador de texturas. g_hr = D3DXCreateRenderToSurface(g_device, g_texTam, g_texTam, texFormato, true, D3DFMT_D16, &g_texRenderizador ); Esta linha cria o objeto que renderiza em texturas. Os argumentos de entrada estão dispostos nesta ordem: dispositivo renderizador, largura, altura, formato da superfície, habilitação do buffer de profundidade\stencil ( true ), formato do buffer de profundidade e finalmente a variável que recebe o ponteiro para o objeto criado da interface ID3DXRenderToSurface. g_hr = D3DXCreateTexture(g_device, g_texTam, g_texTam, 1, D3DUSAGE_RENDERTARGET, texFormato, D3DPOOL_DEFAULT, &g_texturaAlvo); Aqui é criado a textura alvo da renderização. Veja que o uso foi declarado como D3DUSAGE_RENDERTARGET para preparar a textura para ser alvo da renderização. g_hr = g_texturaAlvo->GetSurfaceLevel (0, &g_superficieAlvo); Nesta linha obtemos acesso ao nível zero(0) da textura que representa a superfície sobre a qual queremos renderizar. Lembramos que pode ocorrer de um mesma textura possuir várias cópias da textura principal em tamanhos diversos que são aplicadas quando o objeto está longe ou perto da câmera. Esse recurso é chamado de mipmapping. g_device->ColorFill (g_superficieAlvo, NULL, 0xFFFF0000); Com esta linha pintamos a superfície da textura de vermelho. g_hr = D3DXCreateSprite(g_device, &g_radar); Aqui é criado o objeto sprite. O nome g_radar veio da intenção inicial de criar um radar que mostra a posição do objeto no mundo 3d. 2.3 Renderização na textura
void renderizar_naTextura(void) { // Prepara a configuração da janela de visualização D3DVIEWPORT9 visao; visao.MaxZ = 1.0f; visao.MinZ = 0.0f; visao.X = 10; visao.Y = 10; visao.Width = g_texTam - 20; visao.Height = g_texTam - 20; // Inicia a renderização da cena g_hr = g_texRenderizador->BeginScene(g_superficieAlvo, &visao); if (FAILED(g_hr)) { MessageBox (NULL, "Falha: g_texRenderizador->BeginScene()", "renderizar_naTextura", MB_OK); return; } // endif // Limpa o backbuffer com uma cor branca g_device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, branco, 1.0f, 0); g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT); // Vamos renderizar a geometria g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.pos = D3DXVECTOR3 (0.0f, 0.2f, -50.0f); desenharObjeto( g_objeto3d, &g_props); // Finaliza a cena no Renderizador g_texRenderizador->EndScene(D3DX_FILTER_NONE); } // renderizar_naTextura(void);
D3DVIEWPORT9 visao; Essa variável representa uma janela de visualização, isto é, a área da textura que vai ser utilizada para a renderização. Em nossa configuração vamos suprimir 20 pixels de cada lado dessa janela para manter uma borda vermelha ao redor da cena na textura. visao.MaxZ = 1.0f; visao.MinZ = 0.0f; Isso representa os limites do buffer de profundidade. visao.X = 10; visao.Y = 10; visao.Width = g_texTam - 20; visao.Height = g_texTam - 20; Aqui é a definição da área renderizável. g_hr = g_texRenderizador->BeginScene(g_superficieAlvo, &visao); Aqui começa a renderização da cena na textura. Veja que o renderizador recebeu como argumentos a superfície da textura alvo e as definições da janela de visualização.
// Limpa o backbuffer com uma cor branca g_device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, branco, 1.0f, 0); g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT); // Vamos renderizar a geometria g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.pos = D3DXVECTOR3 (0.0f, 0.2f, -50.0f); desenharObjeto( g_objeto3d, &g_props);
Aqui não tem novidade. Estas linhas são partes já conhecidas do processo comum de renderização. Porém tudo ocorre na textura. g_texRenderizador->EndScene(D3DX_FILTER_NONE); Aqui finalizamos o processo de renderizar na textura. D3DX_FILTER_NONE informa que nenhum filtro vai ser aplicado na textura produzida. 2.4 Renderização da sprite
void renderizarSprite() { // Cor difusa da sprite DWORD cor_difusa = branco; // Inicia a renderização considerando efeito de transparência g_radar->Begin (D3DXSPRITE_ALPHABLEND); // Configura posição da sprite na tela D3DXMatrixTranslation(&g_mtxMundo, 10.0f, 10.0f, 1.0f); g_radar->SetTransform (&g_mtxMundo); // Renderiza sprite conforme configuração previamente definida g_radar->Draw(g_texturaAlvo, 0, 0, 0, cor_difusa); // Finaliza processo de renderização de sprites g_radar->End(); } // renderizarSprite().fim
DWORD cor_difusa = branco; Aqui está a cor difusa da sprite. g_radar->Begin (D3DXSPRITE_ALPHABLEND); Aqui começa a renderização da sprite com a habilitação dos efeitos de mistura de cor (alpha blending). D3DXMatrixTranslation(&g_mtxMundo, 10.0f, 10.0f, 1.0f); g_radar->SetTransform (&g_mtxMundo); Aqui é a configuração do posicionamento da sprite. g_radar->Draw(g_texturaAlvo, 0, 0, 0, cor_difusa); Aqui a sprite renderiza na tela a textura em sua totalidade. g_radar->End(); O processo de renderização da sprite é finalizado nesta linha. 2.5 Gravação da imagem da tela no disco
void salvarImagem(void) { // Cria uma superfície para receber o backbuffer IDirect3DSurface9 *backbuffer; // Obtém os dados de cor do backbuffer g_device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); // Salva o backbuffer como imagem jpg no disco D3DXSaveSurfaceToFile("foto_tela.jpg", D3DXIFF_JPG, backbuffer, 0, 0); // Libera a superfície criada backbuffer->Release(); // Notifica o salvamento na barra de títulos SetWindowText(hJanela, "prj_Superficie: Ok. Imagem salva no disco"); // Aguarda um segundo para alertar melhor usuário Sleep(1000); } // void salvarImagem().fim
IDirect3DSurface9 *backbuffer; Criamos aqui uma superfície temporária para receber os dados do backbuffer. g_device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); Com esta linha jogamos uma cópia do backbuffer dentro da superfície temporária. D3DXSaveSurfaceToFile("foto_tela.jpg", D3DXIFF_JPG, backbuffer, 0, 0); Aqui o backbuffer é gravado como uma imagem jpg no disco. backbuffer->Release(); Aqui liberamos a superfície temporária. SetWindowText(hJanela, "prj_Superficie: Ok. Imagem salva no disco"); Avisamos aqui o usuário que a imagem foi salva. // Aguarda um segundo para alertar melhor usuário Sleep(1000); Aqui damos uma pequena pausa no programa para alertar o usuário de que alguma coisa aconteceu. 2.6 Inicialização do motor gráfico Segue abaixo a listagem de initGfx().
// initGfx() - Inicializa o Direct3D HRESULT initGfx( HWND hJanela ) { // Cria o objeto Direct3D que é necessário para criar o dispositivo gráfico g_Direct3d = Direct3DCreate9( D3D_SDK_VERSION); // Verifica se o objeto Direct3D foi criado if(g_Direct3d == NULL) { MessageBox (NULL, "Falha na inialização do Direct3D", "InitGfx()", MB_OK); return E_FAIL; } // endif // Declara a variável para os parâmetros de apresentação D3DPRESENT_PARAMETERS pps; // Limpa a estrutura ZeroMemory( &pps, sizeof(pps) ); // Vamos ativar o buffer de profundidade pps.EnableAutoDepthStencil = true; pps.AutoDepthStencilFormat = D3DFMT_D16; // Configura os parâmetros de apresentação // A aplicação vai ter janela pps.Windowed = TRUE; // Esse método transfere rapidamente o backbuffer para a tela imediata pps.SwapEffect = D3DSWAPEFFECT_DISCARD; // Esse formato vai procurar se encaixar no modo de video corrente pps.BackBufferFormat = D3DFMT_UNKNOWN; // Configuração do renderizador a ser criado // Adaptador default (0) int nAdaptador = D3DADAPTER_DEFAULT; // Tipo de dispositivo Hardware ou emulador de referência (software) D3DDEVTYPE dispositivo_tipo = D3DDEVTYPE_HAL; // Flags de configuração do dispositivo DWORD create_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Criamos aqui o dispositivo renderizador g_hr = g_Direct3d->CreateDevice( nAdaptador, dispositivo_tipo, hJanela, create_flags, &pps, &g_device ); // Verifica se houve falha no processo if( FAILED( g_hr ) ) { MessageBox (NULL, "Falha na criação: g_device", "initGfx()", MB_OK); return E_FAIL; } // endif // Monta a câmera da aplicação inicializar_Camera(); // Configura alguns estados da cena configurar_cenaEstados(); // Carrega o modelo tiny.x CarregarModeloTiny(); // Inicializa os objetos envolvidos na renderização // da cena na textura inicializar_texRenderizador(); return S_OK; } // initGfx().fim
2.7 Renderização da cena Segue abaixo a listagem da função Renderizar(). Perceba que primeiro é feito a renderização na textura com a função apropriada que já foi discutida, o modelo 3d é renderizado no processo principal e depois a textura produzida é renderizada por renderizarSprite().
VOID Renderizar() { // Renderiza na textura primeiro renderizar_naTextura(); // Retorne se o dispositivo estiver nulo if( g_device == NULL) return; g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); // Limpa o backbuffer com uma cor branca g_device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, azul, 1.0f, 0); // Começa a cena if( SUCCEEDED( g_device->BeginScene() ) ) { // Renderiza o modelo 3d g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.pos = D3DXVECTOR3 (-150.0f, 40.0f, -20.0f); desenharObjeto( g_objeto3d, &g_props); // Mostra a textura preparada anteriormente renderizarSprite(); // Finalizando a cena g_device->EndScene(); } // endif // Apresenta o conteúdo do backbuffer na tela g_device->Present( NULL, NULL, NULL, NULL); Sleep(0); } // Renderizar().fim
3. Código fonte do projeto de exemplo: prj_Superficie
//----------------------------------------------------------------------------- // Projeto: prj_Superficie - Arquivo: motor.h // Esta aplicação mostra como renderizar a cena na textura // By www.gameprog.com.br //----------------------------------------------------------------------------- #include <d3d9.h> #include <d3dx9.h> // Inclui as bibliotecas do Direct3D #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") // Desliga aviso de 'função insegura' devido ao uso das // funções de string ( strcat etc... ) #pragma warning( disable:4996 ) #ifndef motor_h #define motor_h // Estrutura para controle de rotação e posição do objeto struct Propriedades3d { D3DXVECTOR3 pos; D3DXVECTOR3 rot; }; // Esta função inicializa o Direct3D HRESULT initGfx (HWND hJanela); // Essa função libera os objetos utilizados void Limpar(); // Essa função desenha a cena void Renderizar(); // Monta a câmera da aplicação void inicializar_Camera(void); // Desenha o modelo 3d void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props); // Carrega o modelo tiny.x void CarregarModeloTiny(void); // Configura alguns estados da cena void configurar_cenaEstados(void); // Inicializa os objetos envolvidos na renderização // da cena na textura void inicializar_texRenderizador(void); // Renderiza a cena na textura void renderizar_naTextura(void); // Renderiza a sprite na tela void renderizarSprite(); // Salva o backbuffer como arquivo de imagem no disco void salvarImagem(void); // Declaração da função que atende as mensagens da janela LRESULT CALLBACK processaJanela ( HWND hJanela, UINT mensagem, WPARAM wParam, LPARAM lParam); #endif
// ----------------------------------------------------------------------------- // Projeto: prj_Superficie - arquivo: motor.cpp // Esta aplicação mostra como renderizar a cena na textura // By www.gameprog.com.br // ----------------------------------------------------------------------------- #include <windows.h> #include <d3d9.h> #include <d3dx9.h> #include <string.h> #include "motor.h" // Variáveis globais // Representa o dispositivo Direct3D LPDIRECT3D9 g_Direct3d = NULL; // Representa o dispositivo Renderizador IDirect3DDevice9* g_device = NULL; // Recipientes de materiais e texturas do mesh D3DMATERIAL9 *g_meshMtl = NULL; IDirect3DTexture9 *g_meshTex = NULL; // Objetos para o contexto de renderizar na textura IDirect3DTexture9 *g_texturaAlvo = NULL; ID3DXRenderToSurface *g_texRenderizador = NULL; IDirect3DSurface9 *g_superficieAlvo = NULL; ID3DXSprite *g_radar = NULL; // Tamanho da textura desejada 256x256 UINT g_texTam = 256; // Quantidade de materiais do modelo 3d DWORD g_mtlQtd = 0; // Interface do objeto 3d ID3DXMesh *g_objeto3d = NULL; // Recipiente de cor, rotação e posição do objeto Propriedades3d g_props; // Controla o ângulo de rotação do objeto 3d float g_angulo = 0.0f; // Essa variável recebe informação de erro do Directx HRESULT g_hr = 0; // Tamanho da janela extern int g_xtela; extern int g_ytela; extern HWND hJanela; // Constante para cores const DWORD branco = 0xFFFFFFFF; const DWORD azul = 0xFF0000FF; // Matrizes de configuração da câmera D3DXMATRIX g_mtxMundo; D3DXMATRIX g_mtxVisao; D3DXMATRIX g_mtxProj; void inicializar_texRenderizador(void) { // Inicializa o Renderizador D3DFORMAT texFormato = D3DFMT_X8R8G8B8; g_hr = D3DXCreateRenderToSurface(g_device, g_texTam, g_texTam, texFormato, true, D3DFMT_D16, &g_texRenderizador ); if(FAILED(g_hr) ) { MessageBox(NULL, "falha: g_texRenderizador", "inicializar_texRenderizador()", MB_OK); } // endif // Cria uma textura alvo da renderização g_hr = D3DXCreateTexture(g_device, g_texTam, g_texTam, 1, D3DUSAGE_RENDERTARGET, texFormato, D3DPOOL_DEFAULT, &g_texturaAlvo); if (FAILED(g_hr) ) { MessageBox (NULL, "falha: g_texturaAlvo", "inicializar_texRenderizador()", MB_OK); return; } // endif // Acessa a superficie de dados da textura g_hr = g_texturaAlvo->GetSurfaceLevel (0, &g_superficieAlvo); if (FAILED(g_hr) ) { MessageBox (NULL, "falha: g_superficieAlvo", "inicializar_texRenderizador()", MB_OK); return; } // endif // Pinta a superficie da textura de vermelho g_device->ColorFill (g_superficieAlvo, NULL, 0xFFFF0000); // Cria uma sprite para a textura g_hr = D3DXCreateSprite(g_device, &g_radar); if (FAILED(g_hr) ) { MessageBox (NULL, "falha: D3DXCreateSprite()", "inicializar_texRenderizador()", MB_OK); return; } // endif } // inicializar_texRenderizador().fim void renderizar_naTextura(void) { // Prepara a configuração da janela de visualização D3DVIEWPORT9 visao; visao.MaxZ = 1.0f; visao.MinZ = 0.0f; visao.X = 10; visao.Y = 10; visao.Width = g_texTam - 20; visao.Height = g_texTam - 20; // Inicia a renderização da cena g_hr = g_texRenderizador->BeginScene(g_superficieAlvo, &visao); if (FAILED(g_hr)) { MessageBox (NULL, "Falha: g_texRenderizador->BeginScene()", "renderizar_naTextura", MB_OK); return; } // endif // Limpa o backbuffer com uma cor branca g_device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, branco, 1.0f, 0); g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_POINT); // Vamos renderizar a geometria g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.pos = D3DXVECTOR3 (0.0f, 0.2f, -50.0f); desenharObjeto( g_objeto3d, &g_props); // Finaliza a cena no Renderizador g_texRenderizador->EndScene(D3DX_FILTER_NONE); } // renderizar_naTextura(void); void renderizarSprite() { // Cor difusa da sprite DWORD cor_difusa = branco; // Inicia a renderização considerando efeito de transparência g_radar->Begin (D3DXSPRITE_ALPHABLEND); // Configura posição da sprite na tela D3DXMatrixTranslation(&g_mtxMundo, 10.0f, 10.0f, 1.0f); g_radar->SetTransform (&g_mtxMundo); // Renderiza sprite conforme configuração previamente definida g_radar->Draw(g_texturaAlvo, 0, 0, 0, cor_difusa); // Finaliza processo de renderização de sprites g_radar->End(); } // renderizarSprite().fim void salvarImagem(void) { // Cria uma superfície para receber o backbuffer IDirect3DSurface9 *backbuffer; // Obtém os dados de cor do backbuffer g_device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); // Salva o backbuffer como imagem jpg no disco D3DXSaveSurfaceToFile("foto_tela.jpg", D3DXIFF_JPG, backbuffer, 0, 0); // Libera a superfície criada backbuffer->Release(); // Notifica o salvamento na barra de títulos SetWindowText(hJanela, "prj_Superficie: Ok. Imagem salva no disco"); // Aguarda um segundo para alertar melhor usuário Sleep(1000); } // void salvarImagem().fim // initGfx() - Inicializa o Direct3D HRESULT initGfx( HWND hJanela ) { // Cria o objeto Direct3D que é necessário para criar o dispositivo gráfico g_Direct3d = Direct3DCreate9( D3D_SDK_VERSION); // Verifica se o objeto Direct3D foi criado if(g_Direct3d == NULL) { MessageBox (NULL, "Falha na inialização do Direct3D", "InitGfx()", MB_OK); return E_FAIL; } // endif // Declara a variável para os parâmetros de apresentação D3DPRESENT_PARAMETERS pps; // Limpa a estrutura ZeroMemory( &pps, sizeof(pps) ); // Vamos ativar o buffer de profundidade pps.EnableAutoDepthStencil = true; pps.AutoDepthStencilFormat = D3DFMT_D16; // Configura os parâmetros de apresentação // A aplicação vai ter janela pps.Windowed = TRUE; // Esse método transfere rapidamente o backbuffer para a tela imediata pps.SwapEffect = D3DSWAPEFFECT_DISCARD; // Esse formato vai procurar se encaixar no modo de video corrente pps.BackBufferFormat = D3DFMT_UNKNOWN; // Configuração do renderizador a ser criado // Adaptador default (0) int nAdaptador = D3DADAPTER_DEFAULT; // Tipo de dispositivo Hardware ou emulador de referência (software) D3DDEVTYPE dispositivo_tipo = D3DDEVTYPE_HAL; // Flags de configuração do dispositivo DWORD create_flags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; // Criamos aqui o dispositivo renderizador g_hr = g_Direct3d->CreateDevice( nAdaptador, dispositivo_tipo, hJanela, create_flags, &pps, &g_device ); // Verifica se houve falha no processo if( FAILED( g_hr ) ) { MessageBox (NULL, "Falha na criação: g_device", "initGfx()", MB_OK); return E_FAIL; } // endif // Monta a câmera da aplicação inicializar_Camera(); // Configura alguns estados da cena configurar_cenaEstados(); // Carrega o modelo tiny.x CarregarModeloTiny(); // Inicializa os objetos envolvidos na renderização // da cena na textura inicializar_texRenderizador(); return S_OK; } // initGfx().fim // Esta função é chamada por DispatchMessage() LRESULT CALLBACK processaJanela ( HWND hJanela, UINT mensagem, WPARAM wParam, LPARAM lParam) { switch (mensagem) { case WM_DESTROY: // Coloca uma mensagem WM_QUIT na fila de mensagem Limpar(); PostQuitMessage (0); break; case WM_KEYDOWN: // Salva imagem no pressionamento da tecla espaço if (wParam == VK_SPACE) salvarImagem(); if (wParam == VK_ESCAPE) { Limpar(); PostQuitMessage( 0); } // endif break; // Essa mensagem vai ocorrer a todo momento case WM_PAINT: // Renderiza a cena Renderizar(); // Invalida a tela para chamar WM_PAINT novamente InvalidateRect( hJanela, NULL, false); break; // Processamento default de mensagens não tratada pela aplicação default: return DefWindowProc (hJanela, mensagem, wParam, lParam); } // endswitch return 0; } // processaJanela().fim // Limpar() - Libera todos os objetos previamente inicializados // ----------------------------------------------------------------------------- VOID Limpar() { // Libera a memória de materiais e textura if (g_meshTex != NULL) g_meshTex->Release(); if (g_meshMtl != NULL) delete g_meshMtl; // Libera objetos do processo de renderizar na textura if (g_radar != NULL) g_radar->Release(); if (g_texturaAlvo != NULL) g_texturaAlvo->Release(); if (g_texRenderizador != NULL) g_texRenderizador->Release(); if (g_superficieAlvo != NULL) g_superficieAlvo->Release(); // Libera o objeto mesh if( g_objeto3d != NULL) g_objeto3d->Release(); // Libera o dispositivo gráfico if( g_device != NULL) g_device->Release(); // Libera o motor do Direct3D if( g_Direct3d != NULL) g_Direct3d->Release(); // Anula os ponteiros g_radar = NULL; g_texturaAlvo = NULL; g_texRenderizador = NULL; g_superficieAlvo = NULL; g_objeto3d = NULL; g_device = NULL; g_Direct3d = NULL; g_meshTex = NULL; g_meshMtl = NULL; } // Limpar().fim // ----------------------------------------------------------------------------- // Renderizar() - Desenha a cena // ----------------------------------------------------------------------------- VOID Renderizar() { // Renderiza na textura primeiro renderizar_naTextura(); // Retorne se o dispositivo estiver nulo if( g_device == NULL) return; g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); // Limpa o backbuffer com uma cor branca g_device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, azul, 1.0f, 0); // Começa a cena if( SUCCEEDED( g_device->BeginScene() ) ) { // Renderiza o modelo 3d g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.pos = D3DXVECTOR3 (-150.0f, 40.0f, -20.0f); desenharObjeto( g_objeto3d, &g_props); // Mostra a textura preparada anteriormente renderizarSprite(); // Finalizando a cena g_device->EndScene(); } // endif // Apresenta o conteúdo do backbuffer na tela g_device->Present( NULL, NULL, NULL, NULL); Sleep(0); } // Renderizar().fim void inicializar_Camera(void) { // *************************************************************************** // Inicializa todas as matrizes para elemento neutro D3DXMatrixIdentity( &g_mtxMundo ); D3DXMatrixIdentity( &g_mtxVisao ); D3DXMatrixIdentity( &g_mtxProj ); // *************************************************************************** // Configura a matriz de mundo no dispositivo renderizador g_device->SetTransform( D3DTS_WORLD, &g_mtxMundo ); // *************************************************************************** // Dados para a configuração da matriz de visualização // Aonde está a câmera? - posição da câmera D3DXVECTOR3 cam_pos (0.0f, 0.0f, 700.0f); // Para aonde a câmera está apontada ou olhando? Alvo da câmera D3DXVECTOR3 cam_alvo (0.0f, 0.0f, 0); // A câmera está de cabeça pra baixo? - orientação da câmera D3DXVECTOR3 cam_vetorcima (0.0f, 1.0f, 0.0f); // Configura a matriz de visão D3DXMatrixLookAtLH( &g_mtxVisao, &cam_pos, &cam_alvo, &cam_vetorcima ); // Configura a matriz de visão no dispositivo renderizador g_device->SetTransform( D3DTS_VIEW, &g_mtxVisao ); // *************************************************************************** // Argumentos de configuração da matriz de projeção // Pega o tamanho da área cliente RECT area_cliente; GetWindowRect (hJanela, &area_cliente); g_xtela = area_cliente.right; g_ytela = area_cliente.bottom; // aspecto dos gráficos float aspecto = (float) g_xtela / g_ytela; // campo de visão float campo_visao = D3DX_PI / 4; // Trapézio de visualização da câmera ( Frustrum ) float corte_perto = 1.0f; float corte_longe = 1000.0f; // Configura a matriz de projeção D3DXMatrixPerspectiveFovLH( &g_mtxProj, campo_visao, aspecto, corte_perto, corte_longe); // Configura a matriz de projeção no dispositivo renderizador g_device->SetTransform( D3DTS_PROJECTION, &g_mtxProj ); } // inicializar_Camera().fim void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props) { // Matrizes para controlar posição e rotação do objeto 3d D3DXMATRIX obj_rot; D3DXMATRIX obj_pos; // Matriz para combinar todas as transformações do objeto 3d D3DXMATRIX mtxCombinada; // Vamos inicializar as matrizes para um valor neutro D3DXMatrixIdentity( &obj_rot ); D3DXMatrixIdentity( &obj_pos ); D3DXMatrixIdentity( &mtxCombinada ); // Atualiza ângulo de rotação g_angulo += 0.02f; // Configura rotação do objeto 3d D3DXMatrixRotationYawPitchRoll(&obj_rot, props->rot.y, props->rot.x + g_angulo, props->rot.z); // Ajusta posição do objeto 3d; D3DXMatrixTranslation(&obj_pos, props->pos.x, props->pos.y, props->pos.z); // Tranfere posição e rotação para o mundo D3DXMatrixMultiply (&mtxCombinada, &obj_rot, &obj_pos); // Configura matriz mundo para o dispositivo renderizador g_device->SetTransform( D3DTS_WORLD, &mtxCombinada ); g_device->SetMaterial(&g_meshMtl[0] ); g_device->SetTexture(0, g_meshTex ); obj3d->DrawSubset(0); } // desenharObjeto().fim void configurar_cenaEstados(void) { // Configuração de iluminação g_device->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255) ); g_device->SetRenderState (D3DRS_LIGHTING, true); // Configura modo de shading g_device->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD); // Habilita uso de buffer de profundidade g_device->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE); // Desliga o culling g_device->SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE); } // configurar_cenaEstados().fim void CarregarModeloTiny() { // Nome final do arquivo do modelo 3d char arquivo_x[] = "\\gameprog\\gdkmedia\\Modelos\\Tiny\\tiny.x"; // Buffer para o pacote de materiais e texturas do modelo 3d ID3DXBuffer *mtlPack; // Carrega modelo 3d com suas texturas e materiais g_hr = D3DXLoadMeshFromX(arquivo_x, D3DXMESH_SYSTEMMEM, g_device, NULL, &mtlPack, NULL, &g_mtlQtd, &g_objeto3d ); // Verifica falha no carregamento do modelo 3d if(FAILED (g_hr) ) { MessageBox (NULL, "Falha no carregamento do modelo", "CarregarModeloTiny()", MB_OK); return; } // endif // Pacote de materiais da biblioteca auxiliar d3dx D3DXMATERIAL *xMtl = (D3DXMATERIAL *) mtlPack->GetBufferPointer(); // Inicializa a array de materiais g_meshMtl = new D3DMATERIAL9[1 ]; // Copia o ponteiro do material g_meshMtl[0] = xMtl[0].MatD3D; // Configura a cor ambiente do material g_meshMtl[0].Ambient = g_meshMtl[0].Diffuse; // Nome completo da textura do modelo 3d char *arquivo_textura = "\\gameprog\\gdkmedia\\Modelos\\Tiny\\Tiny_skin.bmp"; // Carrega a textura do disco g_hr = D3DXCreateTextureFromFile(g_device, arquivo_textura, &g_meshTex); // Verifica falha no carregamento ou criação das texturas if(FAILED (g_hr) ) { MessageBox (NULL, "Falha na criação da textura", "CarregarModeloTiny()", MB_OK); mtlPack->Release(); return; } // endif // Libera o buffer do pacote de materiais mtlPack->Release(); } // CarregarModeloTiny().fim
//----------------------------------------------------------------------------- // Projeto: prj_Superficie - arquivo: entrada.cpp // Esta aplicação mostra como renderizar a cena na textura // By www.gameprog.com.br //----------------------------------------------------------------------------- #include <windows.h> #include <d3d9.h> #include <d3dx9.h> #include "motor.h" // Variável global da classe da janela char sclasseJanela[ ] = "cls_directx"; // Dimensões da janela int g_xtela = 640; int g_ytela = 480; // alça da janela HWND hJanela; int WINAPI WinMain(HINSTANCE app_instancia, HINSTANCE app_anterior, LPSTR sComando,int nExibir) { // Estrutura de recepção das mensagens MSG mensagem; // Estrutura de descrição da janela WNDCLASSEX wcls; // Estrutura que descreve a janela wcls.hInstance = app_instancia; wcls.lpszClassName = sclasseJanela; wcls.lpfnWndProc = processaJanela; wcls.style = CS_HREDRAW | CS_VREDRAW; wcls.cbSize = sizeof (WNDCLASSEX); // O cursor e os ícones da aplicação são default wcls.hIcon = LoadIcon (NULL, IDI_APPLICATION); wcls.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wcls.hCursor = LoadCursor (NULL, IDC_ARROW); // Aplicação sem menu wcls.lpszMenuName = NULL; // Nada de espaço extra atrelado a classe da janela (wcls) wcls.cbClsExtra = 0; // Nada de espaço extra atrelado a janela wcls.cbWndExtra = 0; // Cor default da janela wcls.hbrBackground = ( HBRUSH) COLOR_BACKGROUND; // Registra a janela e retorna se esta operação falhar int status = RegisterClassEx (&wcls); if(status == 0) { MessageBox(NULL, "Registro falhou!", "WinMain()", MB_OK); return 0; } // endif // Com a classe criada pode-se criar a janela DWORD estiloExtra = 0; const char janelaTitulo[] = "prj_Superficie - Pressione espaço para salvar a imagem"; DWORD controleEstilo = WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX; int xpos = 160; int ypos = 120; HWND hjanelaPai = HWND_DESKTOP; HMENU sem_menu = NULL; LPVOID dadoExtra = NULL; // Cria a janela hJanela = CreateWindowEx(estiloExtra, sclasseJanela, janelaTitulo, controleEstilo, xpos, xpos, g_xtela, g_ytela, hjanelaPai, sem_menu, app_instancia, dadoExtra ); // Verifica se janela foi criada if(hJanela == NULL) { MessageBox(NULL, "Falha na criação da janela!", "WinMain()", MB_OK); return 0; } // endif // Essa variável recebe informação de erro do Directx HRESULT hr; // Inicia o Direct3D hr = initGfx ( hJanela ); // Encerre a aplicação se houve falha if(FAILED (hr) ) { MessageBox (hJanela, "Direct3D: falha na inicialização", "WinMain()", MB_OK); UnregisterClass( sclasseJanela, wcls.hInstance); return E_FAIL; } // endif // Mostra a janela ShowWindow(hJanela, nExibir); UpdateWindow(hJanela ); // Rode a bombeamento de mensagens até GetMessage() retornar 0 while (GetMessage(&mensagem, NULL, 0, 0)) { // Traduz mensagem de tecla virtual em mensagem de caracteres TranslateMessage( &mensagem ); // Despacha a mensagem para a função processaJanela */ DispatchMessage( &mensagem ); } // endwhile // O valor de retorno é zero(0) passado por PostQuitMessage() UnregisterClass( sclasseJanela, wcls.hInstance); return mensagem.wParam; } // WinMain().fim

index << >>

Produzido por Gameprog: Jair Pereira - Agosto/2014 © gameprog.br@gmail.com http://www.gameprog.com.br