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

index << >>


03.4 Mistura de cor (Blending) - Parte 1/2

1.1 Visão geral
Geralmente cada pixel da forma entrante vai encontrar um backbuffer já preenchido por uma cor do estado anterior do backbuffer ou de formas previamente lá desenhadas. Em resumo, a cor do pixel final vai surgir da relação da cor do pixel entrante com a cor do pixel do backbuffer que já está lá e nesta relação a configuração de blending determina quem prevalesce tal como o pixel entrante ou o pixel que já estava no frame buffer ou ainda uma mistura de ambos. Naturalmente fazem parte desse jogo todos os participantes que influenciam na cor dos pixels como a textura, a luz, o material e o aspecto alpha da cor. Uma simples equação de mistura de cor é dada dessa forma: corPixelFinal = corPixelEntrante + corPixelCorrente corPixelFinal é a cor final do pixel. corPixelEntrante é a cor do pixel entrante que já sofreu colorimento da textura com sua filtragem e impacto da luz. corPixelCorrente é a cor que já está no backbuffer ou frame buffer. Na equação simples a cor final foi produzida pela operação de adição mas é comum também a utilização de outras operações como divisão ou multiplicação. A equação simples é só para dar uma idéia básica do processo. Na equação final há dois fatores matemáticos que controlam o equilíbrio da mistura de cor que pode tender para o pixel entrante ou para o pixel corrente conforme a configuração de seus valores: corFinal = (corEntrante * fatorFonte) + ( corCorrente * fatorDestino) O controle dos integrantes dessa equação reside na sua aplicação. Quando você limpa inicialmente o backbuffer com uma cor, você já instala nesse momento uma corCorrente. Quando você pensa em renderizar um teapot amarelo você está premeditando a corEntrante; quando você finalizou a renderização do teapot você produziu a corFinal que tornou-se a corCorrente do momento. Este jogo de mistura de cor pode ficar um pouco mais complicado de se controlar na medida em que sua aplicação vai envolvendo mais luzes, texturas e objetos para produzir a imagem final do frame. Para a configuração dos fatores de mistura fonte e destino o directx oferece essas opções que foram organizadas numa array de strings na aplicação de exemplo desse tópico: char *mensagem[] = { "prj_Alpha01: 0. *** Não usado! *** ", "prj_Alpha01: 1. D3DBLEND_ZERO ", "prj_Alpha01: 2. D3DBLEND_ONE ", "prj_Alpha01: 3. D3DBLEND_SRCCOLOR ", "prj_Alpha01: 4. D3DBLEND_INVSRCCOLOR ", "prj_Alpha01: 5. D3DBLEND_SRCALPHA ", "prj_Alpha01: 6. D3DBLEND_INVSRCALPHA ", "prj_Alpha01: 7. D3DBLEND_DESTALPHA ", "prj_Alpha01: 8. D3DBLEND_INVDESTALPHA ", "prj_Alpha01: 9. D3DBLEND_DESTCOLOR ", "prj_Alpha01: 10. D3DBLEND_INVDESTCOLOR ", "prj_Alpha01: 11. D3DBLEND_SRCALPHASAT ", "prj_Alpha01: 12. D3DBLEND_BOTHSRCALPHA ", "prj_Alpha01: 13. D3DBLEND_BOTHINVSRCALPHA", "prj_Alpha01: 14. D3DBLEND_BLENDFACTOR ", "prj_Alpha01: 15. D3DBLEND_INVBLENDFACTOR ", }; Os valores alistados acima estão na enumeração D3DBLEND do directx e são configurados dessa forma conforme esse código de exemplo: g_device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); Configura o fator de mistura da cor entrante ( fatorFonte ) g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); Configura o fator de mistura da cor corrente ( fatorDestino ) Nossa aplicação de exemplo testa todas as opções da lista acima através da variável temporizador que assume um valor diferente dessa lista a cada 4 segundos. Esse teste permite uma melhor assimilação do impacto visual causado pelas diferentes configurações de blending. Observando a aplicação em execução podemos visualizar várias aplicações úteis para este recurso de blending: produção de sombras, iluminação especial, efeitos de fantasmas e outros efeitos visuais. Adiantamos que na produção de sombras ou espelhamentos é comum renderizar o mesmo objeto duas vezes, com a segunda renderização representando a sombra ou a imagem espelhada configurada adequadamente para ter o aspecto visual de sombra ou de reflexo. 1.2 Estrutura principal da aplicação
Arquivo: motor.cpp
inicializar_Textura() carrega a textura via D3DXCreateTextureFromFile() 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. Configura iluminação montar_Geometria() Define coordenadas de texturas nomeadas. Faz a montagem do quadrado texturizado. desenhar_Quad() Prepara matrizes de rotação e posicionamento. Combina posicionamento e rotação na matriz de mundo local. joga matriz mundo no dispositivo renderizador. configura material, textura e endereçamento, formato de vértice. renderiza o quad com DrawIndexedPrimitiveUP() desenharObjeto() prepara matrizes de rotação e posicionamento. atualiza ângulo de rotação combina posicionamento e rotação na matriz de mundo local. joga matriz mundo no dispositivo renderizador. configura material renderiza o teapot com DrawSubset(0) renderizar_Geometria() Declara o formato de vértice utilizado: CustomVertex_PositionTextured_Format. O temporizador seleciona um modo de mistura de cor diferente a cada quatro segundos. desliga blending chama desenhar_Quad() para renderizar o quad (quadrilátero) liga blending chama desenharObjeto() para renderizar o teapot na configuração de blending selecionada
2.1 Aspectos globais - Arquivo: motor.h
//----------------------------------------------------------------------------- // Projeto: prj_Alpha01 - Arquivo: motor.h // Esta aplicação mostra os efeitos de mistura de cor (blending) // Produzido por www.gameprog.com.br //----------------------------------------------------------------------------- #ifndef motor_h #define motor_h // Estrutura para guardar a coordenada de textura struct TexCoord { // Coordenada de textura float tu, tv; // Construtor default TexCoord() {} TexCoord( float _tu, float _tv) { // Configura coordenada textura tu = _tu; tv =_tv; } }; // fim da estrutura TexCoord // Estrutura para guardar cor, posição e rotação do objeto 3d struct Propriedades3d { D3DXVECTOR3 pos; D3DXVECTOR3 rot; D3DCOLORVALUE cor; }; // Definição do formato de vértice utilizado por esta aplicação #define CustomVertex_PositionTextured_Format(D3DFVF_XYZ | D3DFVF_TEX1) // Estrutura de vértice customizado struct CustomVertex_PositionTextured { // Posição do vértice float x, y, z; // Coordenada da 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 textura tu = texcoord.tu; tv = texcoord.tv; } // fim do construtor }; // fim da estrutura CustomVertex_PositionTextured // 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); // Configura o texto da janela void config_janelaTexto( char *texto); // Desenha um objeto 3d void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props); // Cria um material com a cor especificada void criarMaterial(D3DMATERIAL9 *mtl, D3DCOLORVALUE cvCor ); // Desenha um quadrilátero (quad) void desenhar_Quad( Propriedades3d *props ); // 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 guardar cor, posição e rotação do objeto 3d struct Propriedades3d { D3DXVECTOR3 pos; D3DXVECTOR3 rot; D3DCOLORVALUE cor; };
Esta estrutura vai auxiliar no posicionamento, rotação e na produção da cor do material dos objetos 3d da cena. void renderizar_Geometria (void); Essa função vai coordenar a renderização dos objetos com configuração adequada de blending para o quadrilátero (quad) e o teapot. void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props); void desenhar_Quad( Propriedades3d *props ); Estas funções têm o mesmo objetivo e são muito semelhantes no código fonte com pequenas variações no código para acomodar as diferenças particulares de renderização do quad e do teapot. Por exemplo, o método DrawSubset(0) do teapot se encarrega de renderizá-lo fazendo internamente toda a configuração necessária para isso que inclui ajuste de formato de vértice, ajuste de vertexbuffer etc. 2.2 Aspectos globais - Arquivo: motor.cpp
IDirect3DTexture9* g_Textura = NULL; // Material para o objeto 3d D3DMATERIAL9 g_material; // 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; // Variáveis para cores com rgba expressado em float's D3DCOLORVALUE cvBranco = { 1.0f, 1.0f, 1.0f, 1.0f }; D3DCOLORVALUE cvAmarelo = { 1.0f, 1.0f, 0.0f, 1.0f }; // Constante para cores const DWORD dwBranco = 0xFFFFFFFF; // Velocidade de giro do teapot float velocidade = 0.02f; // Controla mudanças periódicas na configuração de blending UINT temporizador = 0;
IDirect3DTexture9* g_Textura = NULL; Esta é a interface para manipulação da única textura dessa aplicação. D3DMATERIAL9 g_material; Esta estrutura servirá para configurar o material dos objetos. ID3DXMesh *g_objeto3d = NULL; Este objeto é utilizado para conter o objeto 3d teapot que será criado. Propriedades3d g_props; Esta estrutura vai auxiliar no posicionamento, rotação e produção do material do quad e do teapot. float g_angulo = 0.0f; float velocidade = 0.02f; Estas variáveis controlam a rotação dinâmica dada ao teapot. D3DCOLORVALUE cvBranco = { 1.0f, 1.0f, 1.0f, 1.0f }; D3DCOLORVALUE cvAmarelo = { 1.0f, 1.0f, 0.0f, 1.0f }; Estas variáveis trazem as cores dos materiais que serão aplicados nos objetos: amarelo para o teapot e branco para o quad. O canal alpha da cor causa grande impacto visual na produção de efeitos de transpararência quando aproveitado na configuração de blending. const DWORD dwBranco = 0xFFFFFFFF; Este é o branco que limpa inicialmente o backbuffer a cada frame. UINT temporizador = 0; Esta variável para o temporizador, já conhecido de aplicações anteriores, participa do processo de trocar a configuração de blending a cada 4 segundos. 2.3 Inicialização da texturização
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 } // inicializar_Textura(void).fim
2.4 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; // Habilita o buffer de profundidade pps.EnableAutoDepthStencil = true; pps.AutoDepthStencilFormat = D3DFMT_D16; // 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 quad montar_Geometria(); // Inicializa a textura inicializar_Textura(); // Inicializa a câmera inicializar_Camera(); // Configura luz ambiente g_device->SetRenderState (D3DRS_LIGHTING, true); g_device->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(255,250,250) ); return S_OK; } // initGfx().fim
Para a obtenção do resultado visual adequado a luz foi configurada dessa forma: g_device->SetRenderState (D3DRS_LIGHTING, true); A luz foi ativada porque o teapot traz informação de normais no seu conjunto de vértices que combinada com a configuração do material e da luz ambiente produz uma imagem final melhor. g_device->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(255,250,250) ); Aqui a luz ambiente foi configurada para melhorar o visual do quad e do teapot. 2.5 Renderização da geometria
void renderizar_Geometria() { // Mensagens para a barra de títulos da janela char *mensagem[] = { "prj_Alpha01: By Gameprog ", "prj_Alpha01: 1. D3DBLEND_ZERO ", "prj_Alpha01: 2. D3DBLEND_ONE ", "prj_Alpha01: 3. D3DBLEND_SRCCOLOR ", "prj_Alpha01: 4. D3DBLEND_INVSRCCOLOR ", "prj_Alpha01: 5. D3DBLEND_SRCALPHA ", "prj_Alpha01: 6. D3DBLEND_INVSRCALPHA ", "prj_Alpha01: 7. D3DBLEND_DESTALPHA ", "prj_Alpha01: 8. D3DBLEND_INVDESTALPHA ", "prj_Alpha01: 9. D3DBLEND_DESTCOLOR ", "prj_Alpha01: 10. D3DBLEND_INVDESTCOLOR ", "prj_Alpha01: 11. D3DBLEND_SRCALPHASAT ", "prj_Alpha01: 12. D3DBLEND_BOTHSRCALPHA ", "prj_Alpha01: 13. D3DBLEND_BOTHINVSRCALPHA", "prj_Alpha01: 14. D3DBLEND_BLENDFACTOR ", "prj_Alpha01: 15. D3DBLEND_INVBLENDFACTOR ", }; // Produz a cada quadro segundos um valor de 0 a 14. temporizador = ( clock() / 4000 ) % 15; // Soma mais um para evitar o zero e produzir o 15 temporizador = temporizador + 1; // Configura o texto da janela config_janelaTexto (mensagem[temporizador]); // Fator de mistura para os modos 14 e 15 (cor vermelha) if (temporizador > 13) g_device->SetRenderState(D3DRS_BLENDFACTOR, 0xFFFF0000); // Desliga o uso de alpha blending para o quad g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); // Configuração de material do quad cvBranco.a = 0.9f; g_props.cor = cvBranco; // Posição e rotação do teapot g_props.pos = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); desenhar_Quad(&g_props); // ********* O próximo passo consiste em desenhar o teapot ********* // Limpa a textura do dispositivo g_device->SetTexture (0, 0); // Cria o teapot se ele não existir if(g_objeto3d == NULL) D3DXCreateTeapot (g_device, &g_objeto3d, NULL); // Faz a configuração de alpha blending fonte e destino // D3DBLEND_SRCALPHA na fonte é um boa opção para transparência g_device->SetRenderState(D3DRS_SRCBLEND, temporizador); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // Habilita o uso de alpha blending para o teapot g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); // Configura a cor do material para amarelo cvAmarelo.a = 0.2f; g_props.cor = cvAmarelo; // Posição e rotação do teapot g_props.pos = D3DXVECTOR3 (0.0f, 0.0f, 1.0f); g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); // Desenha o teapot desenharObjeto( g_objeto3d, &g_props); } // renderizar_Geometria().fim
char *mensagem[] = { "prj_Alpha01: By Gameprog ", "prj_Alpha01: 1. D3DBLEND_ZERO ", "prj_Alpha01: 2. D3DBLEND_ONE ", "prj_Alpha01: 3. D3DBLEND_SRCCOLOR ", "prj_Alpha01: 4. D3DBLEND_INVSRCCOLOR ", "prj_Alpha01: 5. D3DBLEND_SRCALPHA ", "prj_Alpha01: 6. D3DBLEND_INVSRCALPHA ", "prj_Alpha01: 7. D3DBLEND_DESTALPHA ", "prj_Alpha01: 8. D3DBLEND_INVDESTALPHA ", "prj_Alpha01: 9. D3DBLEND_DESTCOLOR ", "prj_Alpha01: 10. D3DBLEND_INVDESTCOLOR ", "prj_Alpha01: 11. D3DBLEND_SRCALPHASAT ", "prj_Alpha01: 12. D3DBLEND_BOTHSRCALPHA ", "prj_Alpha01: 13. D3DBLEND_BOTHINVSRCALPHA", "prj_Alpha01: 14. D3DBLEND_BLENDFACTOR ", "prj_Alpha01: 15. D3DBLEND_INVBLENDFACTOR "};
Essa aqui é uma lista de strings das configurações possíveis de blending que vão aparecer na barra de títulos da janela conforme estejam configuradas pela variável temporizador. temporizador = ( clock() / 4000 ) % 15; temporizador = temporizador + 1; Essa linha produz um valor de 1 a 15 com intervalo de 4 segundos entre cada mudança. if (temporizador > 13) g_device->SetRenderState(D3DRS_BLENDFACTOR, 0xFFFF0000); Esta linha especifica uma cor, a cor vermelha neste caso, como fator de blending que é utilizada nos modos D3DBLEND_BLENDFACTOR e D3DBLEND_INVBLENDFACTOR para definir a cor fonte. g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); Esta linha desliga o uso de alpha blending para o quad. Isso simplifica a percepção inicial do funcionamento do processo de mistura de cor pois a aplicação fica focada na mistura do teapot que está entrando com o quad que já está no backbuffer. cvBranco.a = 0.9f; g_props.cor = cvBranco; Aqui é a configuração do material do quad. O impacto dessa configuração é melhor percebido apenas se o uso de alpha blending for habilitado com teste de alterações no aspecto alpha desse material. g_props.pos = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); desenhar_Quad(&g_props); Aqui o quad é renderizado sem rotação na posição de origem do mundo 3d. // ********* O próximo passo consiste em desenhar o teapot ********* Muitos efeitos especiais como sombra ou espelhamento para citar apenas esses dois mais conhecidos são produzidos em vários passos de renderização nos bastidores da aplicação. O complicado disso é ficar atento ao jogo das configurações necessárias dos estados em cada passo e visualizar parcialmente como está o backbuffer em cada passo para dar o passo seguinte com conhecimento de causa. Pois bem, até esse momento o quad está renderizado no backbuffer e o próximo passo agora é habilitar o uso de alpha blending, configurar o modo de mistura e finalmente renderizar o teapot. g_device->SetTexture (0, 0); O teapot não vai usar textura por isso ela é desligada. if(g_objeto3d == NULL) D3DXCreateTeapot (g_device, &g_objeto3d, NULL); Aqui criamos o teapot e esse código é executado apenas uma vez. g_device->SetRenderState(D3DRS_SRCBLEND, temporizador); Aqui nessa linha o fator de mistura do pixel entrante ou fonte referido pelo estado D3DRS_SRCBLEND é configurado com o valor que está na variável temporizador que assume a cada quatro segundos uma outra configuração possível. g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); Aqui nessa linha o fator de mistura do pixel corrente que já está no backbuffer referido pelo estado D3DRS_DESTBLEND é configurado com o valor D3DBLEND_INVSRCALPHA que vai aproveitar o inverso da configuração alpha do material do teapot. Por exemplo, se o canal alpha estiver a 20%, essa configuração vai ser então 80% ou 0.8f; o inverso é dado pela subtração (1.0f - cvAmarelo.a). g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); Aqui habilitamos o uso de alpha blending para a renderização do teapot. cvAmarelo.a = 0.2f; g_props.cor = cvAmarelo; Configuramos o material do teapot com uma atenção especial no canal alpha. g_props.pos = D3DXVECTOR3 (0.0f, 0.0f, 1.0f); g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); desenharObjeto( g_objeto3d, &g_props); Aqui renderizamos o teapot na frente do quad que vai ser afetado pela configuração de blending. 2.6 Renderização do teapot
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 += velocidade; if (g_angulo > 6.28f) velocidade = -velocidade; if (g_angulo < -6.28f) velocidade = -velocidade; // Configura rotação do objeto 3d D3DXMatrixRotationYawPitchRoll(&obj_rot, props->rot.y + g_angulo, 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 ); // Prepara e aplica uma material no objeto 3d criarMaterial( &g_material, props->cor); g_device->SetMaterial (&g_material); // Renderiza o mesh obj3d->DrawSubset(0); } // desenharObjeto().fim
D3DXMATRIX obj_rot; D3DXMATRIX obj_pos; Estas matrizes parciais vão receber a rotação e posição do objeto 3d. D3DXMATRIX mtxCombinada; Esta matriz é a matriz mundo do objeto 3d; nela vão ser combinados rotação e posicionamento do objeto 3d. D3DXMatrixIdentity( &obj_rot ); D3DXMatrixIdentity( &obj_pos ); D3DXMatrixIdentity( &mtxCombinada ); Aqui todas as matrizes são configuradas com um fator de neutralidade das matrizes que é a matriz identidade. g_angulo += velocidade; Aqui o ângulo de rotação é atualizado. if (g_angulo > 6.28f) velocidade = -velocidade; if (g_angulo < -6.28f) velocidade = -velocidade; Aqui a rotação ganha um inversão para a direção oposta caso o objeto 3d tenha dado uma volta completa ( 360º ou 6.28f em radianos ). D3DXMatrixRotationYawPitchRoll(&obj_rot, props->rot.y + g_angulo, props->rot.x + g_angulo, props->rot.z); Aqui a matriz de rotação do objeto é preparada. D3DXMatrixTranslation(&obj_pos, props->pos.x, props->pos.y, props->pos.z); Aqui a matriz de posicionamento do objeto é preparada. D3DXMatrixMultiply (&mtxCombinada, &obj_rot, &obj_pos); Aqui a matriz final do objeto com rotação e posicionamento é preparada. g_device->SetTransform( D3DTS_WORLD, &mtxCombinada ); Na sequência a matriz mundo do renderizador é configurada com a matriz final do objeto 3d. criarMaterial( &g_material, props->cor); g_device->SetMaterial (&g_material); Aqui ocorre a preparação e configuração do material do objeto 3d. obj3d->DrawSubset(0); E finalmente o método DrawSubset(0) renderiza o objeto 3d. 2.7 Renderização do quad Segue abaixo a listagem da função desenhar_Quad() na qual o código de uso das matrizes foi explicado na função desenharObjeto().
void desenhar_Quad( 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 ); // Configura rotação do objeto 3d D3DXMatrixRotationYawPitchRoll(&obj_rot, props->rot.y, props->rot.x, 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 ); // Prepara e aplica uma material no objeto 3d criarMaterial( &g_material, cvBranco); g_device->SetMaterial (&g_material); g_device->SetTexture (0, g_Textura); // 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 modo de textura g_device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); g_device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); // Renderiza o quad g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices, D3DFMT_INDEX16, &g_Verts, nPasso); } // desenhar_Quad()
3. Código fonte do projeto de exemplo: prj_Alpha01
//----------------------------------------------------------------------------- // Projeto: prj_Alpha01 - Arquivo: motor.h // Esta aplicação mostra os efeitos de mistura de cor (blending) // Produzido por www.gameprog.com.br //----------------------------------------------------------------------------- #ifndef motor_h #define motor_h // Estrutura para guardar a coordenada de textura struct TexCoord { // Coordenada de textura float tu, tv; // Construtor default TexCoord() {} TexCoord( float _tu, float _tv) { // Configura coordenada textura tu = _tu; tv =_tv; } }; // fim da estrutura TexCoord // Estrutura para guardar cor, posição e rotação do objeto 3d struct Propriedades3d { D3DXVECTOR3 pos; D3DXVECTOR3 rot; D3DCOLORVALUE cor; }; // Definição do formato de vértice utilizado por esta aplicação #define CustomVertex_PositionTextured_Format(D3DFVF_XYZ | D3DFVF_TEX1) // Estrutura de vértice customizado struct CustomVertex_PositionTextured { // Posição do vértice float x, y, z; // Coordenada da 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 textura tu = texcoord.tu; tv = texcoord.tv; } // fim do construtor }; // fim da estrutura CustomVertex_PositionTextured // 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); // Configura o texto da janela void config_janelaTexto( char *texto); // Desenha um objeto 3d void desenharObjeto ( ID3DXMesh *obj3d, Propriedades3d *props); // Cria um material com a cor especificada void criarMaterial(D3DMATERIAL9 *mtl, D3DCOLORVALUE cvCor ); // Desenha um quadrilátero (quad) void desenhar_Quad( Propriedades3d *props ); // 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_Alpha01 - arquivo: motor.cpp // Esta aplicação mostra os efeitos de mistura de cor (blending) // Produzido por www.gameprog.com.br // ----------------------------------------------------------------------------- #include <windows.h> #include <d3d9.h> #include <d3dx9.h> #include <time.h> #include "motor.h" // Inclui as bibliotecas do Direct3D #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") // 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; IDirect3DTexture9* g_Textura = NULL; // Material para o objeto 3d D3DMATERIAL9 g_material; // 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; // Variáveis para cores com rgba expressado em float's D3DCOLORVALUE cvBranco = { 1.0f, 1.0f, 1.0f, 1.0f }; D3DCOLORVALUE cvAmarelo = { 1.0f, 1.0f, 0.0f, 1.0f }; // Constante para cores const DWORD dwBranco = 0xFFFFFFFF; // Velocidade de giro do teapot float velocidade = 0.02f; // Controla mudanças periódicas na configuração de blending UINT temporizador = 0; // 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; // 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 }; 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 } // inicializar_Textura(void).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) ); // Configura os parâmetros de apresentação // A aplicação vai ter janela pps.Windowed = TRUE; // Habilita o buffer de profundidade pps.EnableAutoDepthStencil = true; pps.AutoDepthStencilFormat = D3DFMT_D16; // 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 quad montar_Geometria(); // Inicializa a textura inicializar_Textura(); // Inicializa a câmera inicializar_Camera(); // Configura luz ambiente g_device->SetRenderState (D3DRS_LIGHTING, true); g_device->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(255,250,250) ); return S_OK; } // initGfx().fim void montar_Geometria(void) { // 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[] = { "prj_Alpha01: By Gameprog ", "prj_Alpha01: 1. D3DBLEND_ZERO ", "prj_Alpha01: 2. D3DBLEND_ONE ", "prj_Alpha01: 3. D3DBLEND_SRCCOLOR ", "prj_Alpha01: 4. D3DBLEND_INVSRCCOLOR ", "prj_Alpha01: 5. D3DBLEND_SRCALPHA ", "prj_Alpha01: 6. D3DBLEND_INVSRCALPHA ", "prj_Alpha01: 7. D3DBLEND_DESTALPHA ", "prj_Alpha01: 8. D3DBLEND_INVDESTALPHA ", "prj_Alpha01: 9. D3DBLEND_DESTCOLOR ", "prj_Alpha01: 10. D3DBLEND_INVDESTCOLOR ", "prj_Alpha01: 11. D3DBLEND_SRCALPHASAT ", "prj_Alpha01: 12. D3DBLEND_BOTHSRCALPHA ", "prj_Alpha01: 13. D3DBLEND_BOTHINVSRCALPHA", "prj_Alpha01: 14. D3DBLEND_BLENDFACTOR ", "prj_Alpha01: 15. D3DBLEND_INVBLENDFACTOR ", }; // Produz a cada quadro segundos um valor de 0 a 14. temporizador = ( clock() / 4000 ) % 15; // Soma mais um para evitar o zero e produzir o 15 temporizador = temporizador + 1; // Configura o texto da janela config_janelaTexto (mensagem[temporizador]); // Fator de mistura para os modos 14 e 15 (cor vermelha) if (temporizador > 13) g_device->SetRenderState(D3DRS_BLENDFACTOR, 0xFFFF0000); // Desliga o uso de alpha blending para o quad g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); // Configuração de material do quad cvBranco.a = 0.9f; g_props.cor = cvBranco; // Posição e rotação do teapot g_props.pos = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); desenhar_Quad(&g_props); // ********* O próximo passo consiste em desenhar o teapot ********* // Limpa a textura do dispositivo g_device->SetTexture (0, 0); // Cria o teapot se ele não existir if(g_objeto3d == NULL) D3DXCreateTeapot (g_device, &g_objeto3d, NULL); // Faz a configuração de alpha blending fonte e destino // D3DBLEND_SRCALPHA na fonte é um boa opção para transparência g_device->SetRenderState(D3DRS_SRCBLEND, temporizador); g_device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // Habilita o uso de alpha blending para o teapot g_device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); // Configura a cor do material para amarelo cvAmarelo.a = 0.2f; g_props.cor = cvAmarelo; // Posição e rotação do teapot g_props.pos = D3DXVECTOR3 (0.0f, 0.0f, 1.0f); g_props.rot = D3DXVECTOR3 (0.0f, 0.0f, 0.0f); // Desenha o teapot desenharObjeto( g_objeto3d, &g_props); } // 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 o objeto 3d if( g_objeto3d != NULL) g_objeto3d->Release(); // 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(); // Limpa os ponteiros g_Direct3d = NULL; g_device = NULL; g_Textura = NULL; g_objeto3d = 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 | D3DCLEAR_ZBUFFER, 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_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 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 += velocidade; if (g_angulo > 6.28f) velocidade = -velocidade; if (g_angulo < -6.28f) velocidade = -velocidade; // Configura rotação do objeto 3d D3DXMatrixRotationYawPitchRoll(&obj_rot, props->rot.y + g_angulo, 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 ); // Prepara e aplica uma material no objeto 3d criarMaterial( &g_material, props->cor); g_device->SetMaterial (&g_material); // Renderiza o mesh obj3d->DrawSubset(0); } // desenharObjeto().fim void criarMaterial(D3DMATERIAL9 *mtl, D3DCOLORVALUE cvCor ) { // Limpa a estrutura ZeroMemory( mtl, sizeof(D3DMATERIAL9) ); // Configura cor ambiente e difusa mtl->Ambient = cvCor; mtl->Diffuse = cvCor; } // criarMaterial().fim void desenhar_Quad( 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 ); // Configura rotação do objeto 3d D3DXMatrixRotationYawPitchRoll(&obj_rot, props->rot.y, props->rot.x, 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 ); // Prepara e aplica uma material no objeto 3d criarMaterial( &g_material, cvBranco); g_device->SetMaterial (&g_material); g_device->SetTexture (0, g_Textura); // 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 modo de textura g_device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); g_device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); // Renderiza o quad g_device->DrawIndexedPrimitiveUP( D3DPT_TRIANGLELIST, nVerticeInicial, nVerticeQtd, nContagemPrim, &g_Indices, D3DFMT_INDEX16, &g_Verts, nPasso); } // desenhar_Quad()
//----------------------------------------------------------------------------- // Projeto: prj_Alpha01 - arquivo: entrada.cpp // Esta aplicação mostra os efeitos de mistura de cor (blending) // 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_Alpha01"; 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