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

index << >>


03.3 Modos de endereçamento de textura

1.1 Visão geral
A faixa normal de valores para mapeamento de textura reside no intervalo [0.0f - 1.0f]. Para valores fora dessa faixa é necessário especificar como o directx vai se comportar configurando os modos de endereçamento de textura. Um dos modos mais interessantes que está aplicado na ilustração acima é o D3DTADDRESS_WRAP que usa as coordenadas de textura como taxa de repetição para distribuir a textura pelo polígono formado. Os modos de endereçamento de textura são configurados dessa forma: g_device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); g_device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); * Para ter o melhor efeito, é necessário valores maior que 1.0f nas coordenadas de textura. Veja as imagens da documentação original do directx que ilustram os modos de endereçamento de textura com os extremos das coordenadas configurados com 3.0f: D3DTADDRESS_WRAP e D3DTADDRESS_MIRROR D3DTADDRESS_BORDER Nesse modo é necessário configurar a cor de borda conforme essa linha: g_device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, dwVermelho); D3DTADDRESS_CLAMP Com exceção dos modos D3DTADDRESS_WRAP e D3DTADDRESS_MIRROR, na nossa opinião, é difícil visualizar uma aplicação útil para os demais modos. 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 o quadrado texturizado. chama inicializar_Camera() para a configuração inicial da câmera. montar_Geometria() Define coordenadas de texturas nomeadas. Faz a montagem do quadrado texturizado. config_janelaTexto Mostra na barra de títulos da janela o modo de endereçamento de textura configurado. renderizar_Geometria() Declara o formato de vértice utilizado: CustomVertex_PositionTextured_Format. O temporizador seleciona um modo de endereçamento de textura diferente a cada dois segundos. Renderiza o quadrado com o modo de texturização selecionado.
2.1 Renderizando a geometria
void renderizar_Geometria() { // Mensagens para a barra de títulos da janela char mensagem[6][80] = { "prj_texModo: 0. By Gameprog ", "prj_texModo: 1. D3DTADDRESS_WRAP ", "prj_texModo: 2. D3DTADDRESS_MIRROR ", "prj_texModo: 3. D3DTADDRESS_CLAMP ", "prj_texModo: 4. D3DTADDRESS_BORDER ", "prj_texModo: 5. D3DTADDRESS_MIRRORONCE" }; // Produz a cada dois segundos um valor de 1 a 5 com temporizador++. temporizador = ( clock() / 2000 ) % 5; temporizador++; // 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); // Configura o texto da barra de títulos config_janelaTexto( mensagem[temporizador] ); // Configura o modo de endereçamento da textura g_device->SetSamplerState(0, D3DSAMP_ADDRESSU, temporizador); g_device->SetSamplerState(0, D3DSAMP_ADDRESSV, temporizador); // Define a cor azul para o modo de endereçamento D3DSAMP_BORDERCOLOR if (temporizador == D3DSAMP_BORDERCOLOR) g_device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, dwAzul); // Renderiza o quadrado g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices, D3DFMT_INDEX16, &g_Verts, nPasso); } // renderizar_Geometria().fim
char mensagem[6][80] = { "prj_texModo: 0. By Gameprog ", "prj_texModo: 1. D3DTADDRESS_WRAP ", "prj_texModo: 2. D3DTADDRESS_MIRROR ", "prj_texModo: 3. D3DTADDRESS_CLAMP ", "prj_texModo: 4. D3DTADDRESS_BORDER ", "prj_texModo: 5. D3DTADDRESS_MIRRORONCE" };
Nesta array de strings nós colocamos todos os modos possíveis de endereçamento de textura presentes na enumeração D3DTEXTUREADDRESS com seus valores literais de um a cinco que foram aproveitados na variável temporizador. temporizador = ( clock() / 2000 ) % 5; temporizador++; Esta linha produz um valor de um a cinco a cada dois segundos. config_janelaTexto( mensagem[temporizador] ); Configura o texto da janela para mostrar o modo de texturização selecionado. g_device->SetSamplerState(0, D3DSAMP_ADDRESSU, temporizador); g_device->SetSamplerState(0, D3DSAMP_ADDRESSV, temporizador); Configuramos de fato aqui o modo de endereçamento de textura. Vamos lembrar que para essa configuração funcionar adequadamente, as coordenadas de textura tomaram esses valores em montar_Geometria(): TexCoord cimaEsq( 0.0f, 0.0f); TexCoord cimaDir( 3.0f, 0.0f); TexCoord baixoEsq ( 0.0f, 3.0f); TexCoord baixoDir ( 3.0f, 3.0f); if (temporizador == D3DSAMP_BORDERCOLOR) g_device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, dwAzul); Aqui configuramos a cor de borda utilizada no modo de texturização D3DSAMP_BORDERCOLOR. 2.2 Configuração da barra de títulos da janela
void config_janelaTexto( char *texto) { // Pega o texto atual da janela char temp_txt[80]; GetWindowText (hJanela, temp_txt, 80); // Configura apenas se o texto de entrada for diferente // do texto que está na janela // Isto é para evitar um efeito visual desagradável na barra // de título da janela. if (strcmp (temp_txt, texto)) SetWindowText (hJanela, texto); } // config_janelaTexto().fim
char temp_txt[80]; GetWindowText (hJanela, temp_txt, 80); Aqui nós pegamos o texto da janela e na sequência ele é configurado com o código abaixo. // Configura apenas se o texto de entrada for diferente // do texto que está na janela // Isto é para evitar um efeito visual desagradável na barra // de título da janela. if (strcmp (temp_txt, texto)) SetWindowText (hJanela, texto); 3. Código fonte do projeto de exemplo: prj_texModo
//----------------------------------------------------------------------------- // Projeto: prj_texModo - Arquivo: motor.h // Esta aplicação mostra os modos de endereçamento de 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); // Mostra um texto na barra da janela void config_janelaTexto( char *texto); // 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_texModo - arquivo: motor.cpp // Esta aplicação mostra os modos de endereçamento de textura // Produzido por www.gameprog.com.br // ----------------------------------------------------------------------------- #include <windows.h> #include <d3d9.h> #include <d3dx9.h> #include <time.h> #include "motor.h" // Variáveis globais // Representa o dispositivo Direct3D LPDIRECT3D9 g_Direct3d = NULL; // Representa o dispositivo Renderizador IDirect3DDevice9* g_device = NULL; // Interface para uso de textura IDirect3DTexture9* g_Textura = 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; // Handle da janela usado na função config_janelaTexto() extern HWND hJanela; // Constante para cores const DWORD dwBranco = 0xFFFFFFFF; const DWORD dwAzul = 0xFF0000FF; // Controla a mudança periódica do modo de endereçamento de textura UINT temporizador = 0; // Memória para os vértices CustomVertex_PositionTextured g_Verts[4 ]; // Buffer de índices - indica a ordem de conexão dos vértices WORD g_Indices[6] = { 0, 1, 2, 2, 3, 0 }; // 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 o quadrado texturizado montar_Geometria(); // Carrega a textura do disco e inicializa contexto de texturização inicializar_Textura(); // Faz a configuração inicial da câmera inicializar_Camera(); // Habilita iluminação default g_device->SetRenderState (D3DRS_LIGHTING, false); return S_OK; } // initGfx().fim void montar_Geometria(void) { // *** Coordenadas de textura *** // cima-esquerda TexCoord cimaEsq( 0.0f, 0.0f); // cima-direita TexCoord cimaDir( 3.0f, 0.0f); // baixo-esquerda TexCoord baixoEsq ( 0.0f, 3.0f); // baixo-direita TexCoord baixoDir ( 3.0f, 3.0f); // Posicionamento de profundidade float zpos = 0.9f; // Configuração normal dos vértices com coordenadas de textura g_Verts[0] = CustomVertex_PositionTextured( 2.20f, 1.50f, zpos, cimaEsq); g_Verts[1] = CustomVertex_PositionTextured( -2.20f, 1.50f, zpos, cimaDir); g_Verts[2] = CustomVertex_PositionTextured( -2.20f, -1.50f, zpos, baixoDir); g_Verts[3] = CustomVertex_PositionTextured( 2.20f, -1.50f, zpos, baixoEsq); } // montar_Geometria().fim void renderizar_Geometria() { // Mensagens para a barra de títulos da janela char mensagem[6][80] = { "prj_texModo: 0. By Gameprog ", "prj_texModo: 1. D3DTADDRESS_WRAP ", "prj_texModo: 2. D3DTADDRESS_MIRROR ", "prj_texModo: 3. D3DTADDRESS_CLAMP ", "prj_texModo: 4. D3DTADDRESS_BORDER ", "prj_texModo: 5. D3DTADDRESS_MIRRORONCE" }; // Produz a cada dois segundos um valor de 1 a 5 com temporizador++. temporizador = ( clock() / 2000 ) % 5; temporizador++; // 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); // Configura o texto da barra de títulos config_janelaTexto( mensagem[temporizador] ); // Configura o modo de endereçamento da textura g_device->SetSamplerState(0, D3DSAMP_ADDRESSU, temporizador); g_device->SetSamplerState(0, D3DSAMP_ADDRESSV, temporizador); // Define a cor azul para o modo de endereçamento D3DSAMP_BORDERCOLOR if (temporizador == D3DSAMP_BORDERCOLOR) g_device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, dwAzul); // Renderiza o quadrado g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices, D3DFMT_INDEX16, &g_Verts, 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(); // Reconfiguração dos ponteiros para NULL 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, dwBranco, 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 void config_janelaTexto( char *texto) { // Pega o texto atual da janela char temp_txt[80]; GetWindowText (hJanela, temp_txt, 80); // Configura apenas se o texto de entrada for diferente // do texto que está na janela // Isto é para evitar um efeito visual desagradável na barra // de título da janela. if (strcmp (temp_txt, texto)) SetWindowText (hJanela, texto); } // config_janelaTexto().fim
//----------------------------------------------------------------------------- // Projeto: prj_texModo - arquivo: entrada.cpp // Esta aplicação mostra os modos de endereçamento de 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; // 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_texModo"; 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