Curso completo de DirectX 9 com C\C++
Gameprog - Escola de programação de jogos digitais
Contato: gameprog.br@gmail.com
Fase 03-2
03.2 Quadrado texturizado
1.1 Visão geral
O processo de texturizar consiste em mapear a textura sobre os
vértices do polígono formado. A coordenada (x,y) da textura é chamada
de (u,v) com u correspondente à x e v correspondente à y.
As coordenadas de mapeamento de textura são expressas pelo tipo float
e variam de 0.0f a 1.0f que equivalem a percentuais de largura ou
altura da imagem.
Por exemplo, no eixo x (expresso por u), zero (0) quer dizer extremo
canto esquerdo e 1.0f extremo canto direito. No eixo y (v), zero (0)
quer dizer extremo canto superior e 1.0f extremo canto inferior. E o
valor 0.5f refere-se à metade do caminho. No processo de texturizar,
a coordenada de textura é associada ao vértice e isso demanda
naturalmente um formato de vértice que aceite as coordenadas (u, v).
É interessante notar que essa forma de associar textura aos vértices,
através de float's que representam percentuais da largura ou altura
da imagem o directx consegue assim trabalhar com imagens de qualquer
tamanho para a textura. Porém, para melhor performance da aplicação,
utilize texturas quadradas com dimensões em potências da base 2,
por exemplo 128x128, 256x256 etc. Isso agiliza processos internos
do directx.
1.2 Estrutura principal da aplicação
Arquivo: motor.cpp
inicializar_Textura()
carrega a textura via D3DXCreateTextureFromFile()
configura alguns estados de texturização
initGfx()
chama inicializar_Textura() para montar o contexto de texturização
chama montar_Geometria() para montar os quadrados texturizados
chama inicializar_Camera() para a configuração inicial da câmera.
montar_Geometria()
Define coordenadas de texturas nomeadas
Faz a montagem de cinco quadrados texturizados com cada um tendo
diferentes coordenadas de textura.
Define um ponteiro para cada quadrado texturizado
renderizar_Geometria()
Declara o formato de vértice utilizado:
CustomVertex_PositionTextured_Format
O temporizador seleciona um quadrado texturizado diferente a cada segundo
Renderiza o quadrado selecionado com g_device->DrawIndexedPrimitiveUP()
Limpar()
Libera a textura utilizada
Libera dispositivo renderizador
Libera objeto Direct3d
Configura os ponteiros para NULL
2.1.1 Aspectos globais - Arquivo: motor.h
// Projeto: prj_Textura - Arquivo: motor.h
// Esse projeto ilustra como renderizar um quadrado com textura
// Produzido por www.gameprog.com.br
#ifndef motor_h
#define motor_h
// Inclui as bibliotecas do Direct3D
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
// Estrutura para suportar coordenadas de textura
struct TexCoord
{
// Coordenada de textura
float tu, tv;
// Construtor default
TexCoord() {}
TexCoord( float _tu, float _tv)
{
// Configura coordenada de textura
tu = _tu;
tv =_tv;
}
}; // fim da estrutura TexCoord
// Estrutura de vértice customizado
struct CustomVertex_PositionTextured
{
// Posição do vértice
float x, y, z;
// Coordenada de textura
float tu, tv;
// Construtor default
CustomVertex_PositionTextured() {}
CustomVertex_PositionTextured( float _x, float _y, float _z, TexCoord texcoord)
{
// Configura posição
x = _x;
y = _y;
z = _z;
// Configura coordenada de textura
tu = texcoord.tu;
tv = texcoord.tv;
}
}; // fim da estrutura CustomVertex_PositionTextured
// Definição do formato de vértice utilizado por esta aplicação
#define CustomVertex_PositionTextured_Format(D3DFVF_XYZ | D3DFVF_TEX1)
// 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();
// Essa função monta formas geométricas
void montar_Geometria (void);
// Renderiza os vértices em formas geométricas
void renderizar_Geometria (void);
// Inicializa a textura
void inicializar_Textura(void);
// Inicializa a câmera
void inicializar_Camera(void);
// Declaração da função que atende as mensagens da janela
LRESULT CALLBACK processaJanela (HWND hJanela, UINT mensagem,
WPARAM wParam, LPARAM lParam);
#endif
Estrutura para coordenadas de textura
// Estrutura para suportar coordenadas de textura
struct TexCoord
{
// Coordenada de textura
float tu, tv;
// Construtor default
TexCoord() {}
TexCoord( float _tu, float _tv)
{
// Configura coordenada de textura
tu = _tu;
tv =_tv;
}
}; // fim da estrutura TexCoord
Esta pequena estrutura TexCoord foi desenvolvida para facilitar o
trabalho com coordenadas de textura. Os elementos (tu, tv)
representam naturalmente as coordenadas (u, v) de textura.
Estrutura para o vértice customizado com posição e coordenada de textura
// Estrutura de vértice customizado
struct CustomVertex_PositionTextured
{
// Posição do vértice
float x, y, z;
// Coordenada de textura
float tu, tv;
// Construtor default
CustomVertex_PositionTextured() {}
CustomVertex_PositionTextured( float _x, float _y, float _z, TexCoord texcoord)
{
// Configura posição
x = _x;
y = _y;
z = _z;
// Configura coordenada de textura
tu = texcoord.tu;
tv = texcoord.tv;
}
}; // fim da estrutura CustomVertex_PositionTextured
Esta estrutura de vértice customizado contém uma estrutura TexCoord
como elemento para suportar coordenadas de textura.
#define CustomVertex_PositionTextured_Format(D3DFVF_XYZ | D3DFVF_TEX1)
Essa macro define o formato de vértice utilizado por esta aplicação.
void Limpar();
Salientamos aqui que depois de liberar a interface utilizada com o
método Release() é importante reconfigurar o ponteiro como NULL:
// Libera a textura
if (g_Textura != NULL) g_Textura->Release();
g_Textura = NULL;
Utilize o NULL como filtro para evitar que sua aplicação entre em
pane por tentar utilizar uma interface que já foi liberada.
void montar_Geometria (void);
Essa função monta cinco quadrados texturizados com cada um deles
tendo coordenadas diferentes de textura produzindo imagens finais
diferentes. Salientamos que com a compreensão desse exemplo,
utilizando os recursos de textura é possível construir uma classe
para manipulação de sprites com funcionalidades melhores do que as
oferecidas pela interface do directx para isso.
void renderizar_Geometria (void);
Essa função renderiza a cada segundo um quadrado com uma texturização
diferente. Essa variação periódica é obtida com o uso da função
clock() que retorna o tempo de operação da aplicação em milessegundos
que é convertido em segundos e restringido aos valores de 0 à 4, na
sequência com esse valor selecionando o recipiente de vértices a
ser renderizado.
void inicializar_Textura(void);
Essa função carrega a textura do disco e inicializa o contexto geral
de texturização configurando alguns estados e instalando a textura
carregada no dispositivo renderizador.
2.1.2 Aspectos globais - Arquivo: motor.cpp
// Interface de textura
IDirect3DTexture9* g_Textura = NULL;
// Controla a mudança periódica do quadrado texturizado
// com diferentes coordenadas de textura
UINT temporizador = 0;
// Memória para os vértices
CustomVertex_PositionTextured g_Verts1[4 ];
CustomVertex_PositionTextured g_Verts2[4 ];
CustomVertex_PositionTextured g_Verts3[4 ];
CustomVertex_PositionTextured g_Verts4[4 ];
CustomVertex_PositionTextured g_Verts5[4 ];
// Um ponteiro para cada conjunto de vértices
CustomVertex_PositionTextured *g_pVerts[5 ];
IDirect3DTexture9* g_Textura = NULL;
Declaramos nesta linha o único objeto textura que vai ser utilizado
por esta aplicação.
CustomVertex_PositionTextured g_Verts1[4];
// (...)
CustomVertex_PositionTextured g_Verts5[4];
Declaramos aqui cinco arrays do tipo CustomVertex_PositionTextured
com quatro vértices para conter cada um dos cinco quadrados
texturizados.
CustomVertex_PositionTextured *g_pVerts[5];
Na sequência é declarado uma array de ponteiros com um elemento para
cada um dos recipientes de vértices criados na linha acima.
UINT temporizador = 0;
Esta variável aqui vai assumir valores de 0 à 4 e vai ser combinada
com g_pVerts na forma g_pVerts[temporizador] para produzir a variação
periódica do quadrado texturizado.
2.2 Inicialização do motor gráfico
// 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) );
// 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 vários quads (quadrados) com diferentes coordenadas
// de textura
montar_Geometria();
// Carrega a textura do disco e configura alguns estados referentes.
inicializar_Textura();
// Configura a câmera
inicializar_Camera();
// Habilita a iluminação default
g_device->SetRenderState (D3DRS_LIGHTING, false);
return S_OK;
} // initGfx().fim
// Monta vários quads (quadrados) com diferentes coordenadas
// de textura
montar_Geometria();
// Carrega a textura do disco e configura alguns estados referentes.
inicializar_Textura();
Estas funções foram descritas de forma geral no subtópico acima 2.1.1
e serão melhor detalhadas em seus respectivos subtópicos particulares.
g_device->SetRenderState (D3DRS_LIGHTING, false);
Configuramos esse estado como false para permitir a iluminação default
provida pelo directx.
2.3 Montagem dos quadrados com textura
void montar_Geometria(void)
{
// *** Coordenadas de texturas ***
// cima-esquerda
TexCoord cimaEsq( 0.0f, 0.0f);
// cima-meio
TexCoord cimaMeio( 0.5f, 0.0f);
// cima-direita
TexCoord cimaDir( 1.0f, 0.0f);
// meio-direita
TexCoord meioDir( 0.0f, 0.5f);
// meio-meio
TexCoord meioMeio( 0.5f, 0.5f);
// meio-esquerda
TexCoord meioEsq( 1.0f, 0.5f);
// baixo-esquerda
TexCoord baixoEsq ( 0.0f, 1.0f);
// baixo-meio
TexCoord baixoMeio ( 0.5f, 1.0f);
// baixo-direita
TexCoord baixoDir ( 1.0f, 1.0f);
// Posicionamento de profundidade
float zpos = 1.0f;
// Configuração normal dos vértices com coordenadas de textura
g_Verts1[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaEsq);
g_Verts1[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaDir);
g_Verts1[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoDir);
g_Verts1[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoEsq);
// Configuração normal dos vértices com coordenadas de textura
g_Verts2[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaEsq);
g_Verts2[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaMeio);
g_Verts2[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, meioMeio);
g_Verts2[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, meioDir);
// Configuração normal dos vértices com coordenadas de textura
g_Verts3[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaMeio);
g_Verts3[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaDir);
g_Verts3[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, meioEsq);
g_Verts3[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, meioMeio);
// Configuração normal dos vértices com coordenadas de textura
g_Verts4[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, meioDir);
g_Verts4[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, meioMeio);
g_Verts4[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoMeio);
g_Verts4[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoEsq);
// Configuração normal dos vértices com coordenadas de textura
g_Verts5[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, meioMeio);
g_Verts5[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, meioEsq);
g_Verts5[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoDir);
g_Verts5[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoMeio);
// Um ponteiro para cada conjunto de vértices
g_pVerts[0] = &g_Verts1[0 ];
g_pVerts[1] = &g_Verts2[0 ];
g_pVerts[2] = &g_Verts3[0 ];
g_pVerts[3] = &g_Verts4[0 ];
g_pVerts[4] = &g_Verts5[0 ];
} // montar_Geometria().fim
Coordenadas nomeadas de textura
// cima-esquerda
TexCoord cimaEsq( 0.0f, 0.0f);
// cima-direita
TexCoord cimaDir( 1.0f, 0.0f);
// baixo-direita
TexCoord baixoDir ( 1.0f, 1.0f);
// (...)
// baixo-esquerda
TexCoord baixoEsq ( 0.0f, 1.0f);
Produzimos várias coordenadas de texturas com a estrutura TexCoord
para facilitar o mapeamento da textura em cada quadrado. Cada
coordenada de textura representa um ponto notável referente
aos meios e extremidades da imagem carregada.
Montagem do quadrado texturizado
g_Verts1[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaEsq);
g_Verts1[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaDir);
g_Verts1[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoDir);
g_Verts1[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoEsq);
Esse conjunto de vértices com essa configuração particular de
coordenadas de textura pertence ao primeiro quadrado que traz
estampado em sua superfície o total da textura. Os demais quadrados
foram definidos de forma muito semelhante a esta amostra comentada.
Guardando o endereço de cada recipiente de vértices
g_pVerts[0] = &g_Verts1[0];
g_pVerts[1] = &g_Verts2[0];
g_pVerts[2] = &g_Verts3[0];
g_pVerts[3] = &g_Verts4[0];
g_pVerts[4] = &g_Verts5[0];
Aqui em cada posição da array g_pVerts é estocado o endereço inicial
de cada conjunto de vértices que produzem o seu respectivo quadrado
texturizado de forma particular. Depois, colocando a variável
temporizador como índice dessa array ocasiona a cada segundo um
diferente buffer de vértices para o método DrawIndexedPrimitiveUP()
fazer o seu trabalho de renderização, produzindo assim a cada segundo
um quadrado texturizado de forma diferente.
2.4 Renderização do quadrado texturizado
void renderizar_Geometria()
{
// Produz a cada segundo um valor de 0 a 4.
temporizador = ( clock() / 1000 ) % 5;
// Argumentos da função DrawIndexedPrimitiveUP()
UINT nVerticeInicial = 0;
UINT nVerticeQtd = 4;
UINT nContagemPrim = 2;
UINT nPasso = sizeof(CustomVertex_PositionTextured);
// Declara o formato de vértice utilizado pela aplicação
g_device->SetFVF( CustomVertex_PositionTextured_Format);
g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST,
nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices,
D3DFMT_INDEX16, g_pVerts[temporizador], nPasso);
} // renderizar_Geometria().fim
temporizador = ( clock() / 1000 ) % 5;
Esta linha simples faz o trabalho formidável de selecionar a cada
segundo um dos cinco recipientes diferentes de vértices cada um com
seu quadrado texturizado de forma particular. Nesta linha o valor
1000 representa o período de 1 segundo para gerar a mudança no
temporizador; se você quiser um período de dois segundos basta alterar
esse valor para 2000. O valor 5 depois do operador módulus (%) vai
restringir o valor máximo do temporizador dado pela subtração 5 - 1.
g_device->SetFVF( CustomVertex_PositionTextured_Format);
Configura o formato de vértice atual no dispositivo renderizador.
g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST,
nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices,
D3DFMT_INDEX16, g_pVerts[temporizador], nPasso);
Renderiza finalmente os vértices resultando em um quadrado texturizado.
2.5 Inicialização da textura
void inicializar_Textura(void)
{
g_hr = D3DXCreateTextureFromFile (g_device,
"\\gameprog\\gdkmedia\\bitmap\\textura2x2.png",
&g_Textura);
if (FAILED (g_hr))
{
MessageBox(NULL, "Falha: D3DXCreateTextureFromFile()",
"inicializar_Textura()", MB_OK);
} // endif
// Configura a textura no dispositivo
g_device->SetTexture (0, g_Textura);
// Corrige visualização blocada da textura - quando textura for
// menor do que a superfície ( atuante nesta aplicação )
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
// Corrige visualização blocada da textura - quando textura for
// maior do que a superfície ( não atuante nesta aplicação )
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
} // inicializar_Textura(void).fim
g_hr = D3DXCreateTextureFromFile (g_device,
"\\gameprog\\gdkmedia\\bitmap\\textura2x2.png", &g_Textura);
Esta linha carrega a imagem e produz um objeto textura.
g_device->SetTexture (0, g_Textura);
Esta linha configura a textura no dispositivo. Para limpar a textura
do dispositivo passe o valor NULL no estágio a ser limpo. Por exemplo,
essa linha anula a textura do estágio 0:
g_device->SetTexture (0, NULL);
O estágio de textura é um canal que contém uma textura que pode
ser utilizado para efeitos especiais de mistura de texturas.
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
Estas linhas fazem a correção visual da textura na ocasião em que a
textura aparece blocada ou pixelizada em função do descompasso do
tamanho da textura com o tamanho da área texturizada.
3. Código fonte do projeto de exemplo: prj_Textura
// Projeto: prj_Textura - Arquivo: motor.h
// Esse projeto ilustra como renderizar um quadrado com textura
// Produzido por www.gameprog.com.br
#ifndef motor_h
#define motor_h
// Inclui as bibliotecas do Direct3D
#pragma comment(lib,
"d3d9.lib")
#pragma comment(lib,
"d3dx9.lib")
// Estrutura para suportar coordenadas de textura
struct TexCoord
{
// Coordenada de textura
float tu, tv;
// Construtor default
TexCoord() {}
TexCoord(
float _tu,
float _tv)
{
// Configura coordenada de textura
tu = _tu;
tv =_tv;
}
}; // fim da estrutura TexCoord
// Estrutura de vértice customizado
struct CustomVertex_PositionTextured
{
// Posição do vértice
float x, y, z;
// Coordenada de textura
float tu, tv;
// Construtor default
CustomVertex_PositionTextured() {}
CustomVertex_PositionTextured(
float _x,
float _y,
float _z,
TexCoord texcoord)
{
// Configura posição
x = _x;
y = _y;
z = _z;
// Configura coordenada de textura
tu =
texcoord.tu;
tv =
texcoord.tv;
}
}; // fim da estrutura CustomVertex_PositionTextured
// Definição do formato de vértice utilizado por esta aplicação
#define CustomVertex_PositionTextured_Format(
D3DFVF_XYZ |
D3DFVF_TEX1)
// 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();
// Essa função monta formas geométricas
void montar_Geometria (
void);
// Renderiza os vértices em formas geométricas
void renderizar_Geometria (
void);
// Inicializa a textura
void inicializar_Textura(
void);
// Inicializa a câmera
void inicializar_Camera(
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_Textura - arquivo: motor.cpp
// Esse projeto ilustra como renderizar um quadrado com textura
// Produzido por www.gameprog.com.br
// -----------------------------------------------------------------------------
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include "motor.h"
// Vamos usar a função clock() para produzir um temporizador
#include <time.h>
// Variáveis globais
// Representa o dispositivo Direct3D
LPDIRECT3D9 g_Direct3d = NULL;
// Representa o dispositivo Renderizador
IDirect3DDevice9* g_device = NULL;
// Matrizes de configuração da câmera
// Matriz de mundo
D3DXMATRIX g_mtxMundo;
// Matriz de visão
D3DXMATRIX g_mtxVisao;
// Matriz de projeção
D3DXMATRIX g_mtxProj;
// 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;
// Constante para cores
const DWORD branco = 0xFFFFFFFF;
// Buffer de índices - indica a ordem de conexão dos vértices
WORD g_Indices[6] = { 0, 1, 2, 2, 3, 0 };
// Interface de textura
IDirect3DTexture9* g_Textura = NULL;
// Controla a mudança periódica do quadrado texturizado
// com diferentes coordenadas de textura
UINT temporizador = 0;
// Memória para os vértices
CustomVertex_PositionTextured g_Verts1[4 ];
CustomVertex_PositionTextured g_Verts2[4 ];
CustomVertex_PositionTextured g_Verts3[4 ];
CustomVertex_PositionTextured g_Verts4[4 ];
CustomVertex_PositionTextured g_Verts5[4 ];
// Um ponteiro para cada conjunto de vértices
CustomVertex_PositionTextured *g_pVerts[5 ];
// 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) );
// 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 vários quads (quadrados) com diferentes coordenadas
// de textura
montar_Geometria();
// Carrega a textura do disco e configura alguns estados referentes.
inicializar_Textura();
// Configura a câmera
inicializar_Camera();
// Habilita a iluminação default
g_device->SetRenderState (D3DRS_LIGHTING, false);
return S_OK;
} // initGfx().fim
void montar_Geometria(void)
{
// *** Coordenadas de texturas ***
// cima-esquerda
TexCoord cimaEsq( 0.0f, 0.0f);
// cima-meio
TexCoord cimaMeio( 0.5f, 0.0f);
// cima-direita
TexCoord cimaDir( 1.0f, 0.0f);
// meio-direita
TexCoord meioDir( 0.0f, 0.5f);
// meio-meio
TexCoord meioMeio( 0.5f, 0.5f);
// meio-esquerda
TexCoord meioEsq( 1.0f, 0.5f);
// baixo-esquerda
TexCoord baixoEsq ( 0.0f, 1.0f);
// baixo-meio
TexCoord baixoMeio ( 0.5f, 1.0f);
// baixo-direita
TexCoord baixoDir ( 1.0f, 1.0f);
// Posicionamento de profundidade
float zpos = 1.0f;
// Configuração normal dos vértices com coordenadas de textura
g_Verts1[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaEsq);
g_Verts1[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaDir);
g_Verts1[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoDir);
g_Verts1[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoEsq);
// Configuração normal dos vértices com coordenadas de textura
g_Verts2[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaEsq);
g_Verts2[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaMeio);
g_Verts2[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, meioMeio);
g_Verts2[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, meioDir);
// Configuração normal dos vértices com coordenadas de textura
g_Verts3[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, cimaMeio);
g_Verts3[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, cimaDir);
g_Verts3[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, meioEsq);
g_Verts3[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, meioMeio);
// Configuração normal dos vértices com coordenadas de textura
g_Verts4[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, meioDir);
g_Verts4[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, meioMeio);
g_Verts4[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoMeio);
g_Verts4[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoEsq);
// Configuração normal dos vértices com coordenadas de textura
g_Verts5[0] = CustomVertex_PositionTextured( 1.0f, 1.0f, zpos, meioMeio);
g_Verts5[1] = CustomVertex_PositionTextured(-1.0f, 1.0f, zpos, meioEsq);
g_Verts5[2] = CustomVertex_PositionTextured(-1.0f, -1.0f, zpos, baixoDir);
g_Verts5[3] = CustomVertex_PositionTextured( 1.0f, -1.0f, zpos, baixoMeio);
// Um ponteiro para cada conjunto de vértices
g_pVerts[0] = &g_Verts1[0 ];
g_pVerts[1] = &g_Verts2[0 ];
g_pVerts[2] = &g_Verts3[0 ];
g_pVerts[3] = &g_Verts4[0 ];
g_pVerts[4] = &g_Verts5[0 ];
} // montar_Geometria().fim
void renderizar_Geometria()
{
// Produz a cada segundo um valor de 0 a 4.
temporizador = ( clock() / 1000 ) % 5;
// Argumentos da função DrawIndexedPrimitiveUP()
UINT nVerticeInicial = 0;
UINT nVerticeQtd = 4;
UINT nContagemPrim = 2;
UINT nPasso = sizeof(CustomVertex_PositionTextured);
// Declara o formato de vértice utilizado pela aplicação
g_device->SetFVF( CustomVertex_PositionTextured_Format);
g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST,
nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices,
D3DFMT_INDEX16, g_pVerts[temporizador], nPasso);
} // renderizar_Geometria().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:
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 textura
if (g_Textura != NULL) g_Textura->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();
// Limpando os ponteiros
g_Direct3d = NULL;
g_device = NULL;
g_Textura = NULL;
} // Limpar().fim
// -----------------------------------------------------------------------------
// Renderizar() - Desenha a cena
// -----------------------------------------------------------------------------
VOID Renderizar()
{
// Retorne se o dispositivo estiver nulo
if( g_device == NULL) return;
// Limpa o backbuffer com uma cor branca
g_device->Clear( 0, NULL, D3DCLEAR_TARGET, branco, 1.0f, 0);
// Começa a cena
if( SUCCEEDED( g_device->BeginScene() ) )
{
// Vamos renderizar a geometria
renderizar_Geometria();
// Finalizando a cena
g_device->EndScene();
} // endif
// Apresenta o conteúdo do backbuffer na tela
g_device->Present( NULL, NULL, NULL, NULL);
} // Renderizar().fim
void inicializar_Textura(void)
{
g_hr = D3DXCreateTextureFromFile (g_device,
"\\gameprog\\gdkmedia\\bitmap\\textura2x2.png",
&g_Textura);
if (FAILED (g_hr))
{
MessageBox(NULL, "Falha: D3DXCreateTextureFromFile()",
"inicializar_Textura()", MB_OK);
} // endif
// Configura a textura no dispositivo
g_device->SetTexture (0, g_Textura);
// Corrige visualização blocada da textura - quando textura for
// menor do que a superfície ( atuante nesta aplicação )
g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
// Corrige visualização blocada da textura - quando textura for
// maior do que a superfície ( não atuante nesta aplicação )
g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
} // inicializar_Textura(void).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, 5.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
// 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
//-----------------------------------------------------------------------------
// Projeto: prj_Textura - arquivo: entrada.cpp
// Esse projeto ilustra como renderizar um quadrado com textura
// Produzido por 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;
int WINAPI WinMain (HINSTANCE app_instancia, HINSTANCE app_anterior,
LPSTR sComando,int nExibir) {
// alça da janela
HWND hJanela;
// 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_Textura";
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