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