Esta página contém diversos exemplos DirectX10. Eles foram tirados de um tutorial de iniciante em DirectX10 da Microsoft, porém os comentários foram traduzidos para o português.
Obs: Há alguns erros na tradução e em alguns lugares talvez eu tenha esquecido de traduzir
Obs2: O código funciona desde que as dependências tenham sido postas nos seus devidos lugares. Eu me certifiquei disso por iniciar um projeto vazio para o primeiro tutorial e reusar tal projeto para os tutoriais subsequentes, cuidando para que o código fosse executado corretamente. Futuramente vou colocar um link apontando para os arquivos de projeto nesta página
Obs3: Futuramente colocarei estes tutoriais em páginas separadas e explicarei alguns detalhes deles. Até lá veja a explicação nos arquivos de ajuda do DirectX.
Table of Contents
|
Tutorial 00 - DXSDK - Criando uma Janela Win32
Este tutorial básico ensino a criar uma janela Win32 o que é o básico para ser exibido na tela. Em cima de tal janela que o DirectX funcionará em tutoriais posteriores.
// Este tutorial configura uma aplicação Windows com uma janela e um // procedimento para verificar as mensagens do sistema #include <windows.h> HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; // Loop principal de mensagens MSG msg = {0}; while( GetMessage( &msg, NULL, 0, 0 ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 0: Configurando uma Janela", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; }
Tutorial 01 - DXSDK - Básicos do D3D 10
Este tutorial demonstra como anexar um dispositivo D3D10 à janela
// Esta aplicação demonstra como criar um dispositivo Direct3D10 #include <windows.h> #include <d3d10.h> #include <d3dx10.h> HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ){ CleanupDevice(); return 0; } // Loop principal de mensagens MSG msg = {0}; while( WM_QUIT != msg.message ){ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 1: Básicos do Direct3D 10", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Cria o dispositivo Direct3D e a cadeia de troca HRESULT InitDevice(){ HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Numerator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ){ g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // cria uma visão de renderização alvo (Render Target) ID3D10Texture2D* pBackBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID *) &pBackBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, & g_pRenderTargetView, NULL ); // Configure o viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); return S_OK; } // Renderiza o quadro void Render(){ // Apenas limpe o buffer de trás float ClearColor[4] = {0.0f, 0.125f, 0.3f, 1.0f}; g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); g_pSwapChain->Present(0,0); } // Limpa os objetos que nós criamos void CleanupDevice(){ if( g_pd3dDevice ) g_pd3dDevice->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); }
Tutorial 02 - DXSDK - Renderizando um triângulo
Este tutorial demonstra como renderizar um triângulo na tela.
// Esta aplicação exibe um triângulo usando Direct3D10 #include <windows.h> #include <d3d10.h> #include <d3dx10.h> struct SimpleVertex{ D3DXVECTOR3 Pos; }; HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; ID3D10Effect* g_pEffect = NULL; ID3D10EffectTechnique* g_pTechnique = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ){ CleanupDevice(); return 0; } // Loop principal de mensagens MSG msg = {0}; while( WM_QUIT != msg.message ){ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 2: Renderizando um triângulo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Cria o dispositivo Direct3D e a cadeia de troca HRESULT InitDevice(){ HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Numerator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ){ g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // cria uma visão de renderização alvo (Render Target) ID3D10Texture2D* pBackBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID *) &pBackBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, & g_pRenderTargetView, NULL ); // Configure o viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); //Crie o efeito DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configure a opção D3D10_SHADER_DEBUG para embutir informação de debug nos shaders. // Configurar esta opção melhora a debugação do shader, mas ainda permite aos // shaders serem otimizados e executarem da maneira que eles executarão na // configuração release deste programa dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"..\\Tutorial02.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ){ MessageBox( g_hWnd, L"O arquivo fx não pôde ser localizado. Por favor execute este executável do diretório que contém o arquivo FX", L"Erro", MB_OK ); return hr; } // Obtenha a técnica g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); // Defina o leiaute de entrada D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Crie o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Configure o leiaute de entrada g_pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Crie o buffer de vértice SimpleVertex vertices[] = { D3DXVECTOR3( 0.0f, 0.5f, 0.5f ), D3DXVECTOR3( 0.5f, -0.5f, 0.5f ), D3DXVECTOR3( -0.5f, -0.5f, 0.5f ) }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 3; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Configure o buffer de vértice UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0,1, &g_pVertexBuffer, &stride, &offset ); // Configure a topologia primitiva g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); return S_OK; } // Renderiza o quadro void Render(){ // Limpe o buffer de trás float ClearColor[4] = {0.0f, 0.125f, 0.3f, 1.0f}; // vermelho, verde, azul, alfa g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); // Renderize um triângulo D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechnique->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->Draw( 3, 0 ); } // Apresenta a informação renderizada no buffer de trás para o buffer da frente (a tela) g_pSwapChain->Present(0,0); } // Limpa os objetos que nós criamos void CleanupDevice(){ if( g_pd3dDevice ) g_pd3dDevice->ClearState(); if( g_pVertexBuffer ) g_pVertexBuffer->Release(); if( g_pVertexLayout ) g_pVertexLayout->Release(); if( g_pEffect ) g_pEffect->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); }
Tutorial 03 - DXSDK - Shaders e sistema de efeito
Este tutorial usa o mesmo código que o exemplo anterior. A mudança está na documentação do DXSDK que explica ao invés do código DirectX que renderiza o triângulo, o código do arquivo de efeito usado. O arquivo de efeito é uma maneira simples e compacta de usar shaders. Apesar de vital importância ele não vai ser explicado aqui. Numa outra oportunidade será colocado sua explicação, provavelmente na seção de shaders e quando isto acontecer esta seção será atualizada para apontar para ele. Neste tempo o que será colocado aqui é o arquivo de efeito apenas para vocês terem uma idéia de como ele é formado.
//-------------------------------------------------------------------------------------- // File: Tutorial02.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- float4 VS( float4 Pos : POSITION ) : SV_POSITION { return Pos; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( float4 Pos : SV_POSITION ) : SV_Target { return float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1 } //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Tutorial 04 - DXSDK - Renderizando um cubo
Neste tutorial ao invés de um triângulo são renderizados vários triângulos, formando um cubo. Este cubo fica girando através do eixo Y. O propósito do tutorial é introduzir os espaços 3D (Objeto, Mundo, Olho, Espaço de Recorte de coordenadas da tela).
// Esta aplicação exibe um cubo 3D usando Direct3D10 #include <windows.h> #include <d3d10.h> #include <d3dx10.h> struct SimpleVertex{ D3DXVECTOR3 Pos; D3DXVECTOR4 Color; }; HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; ID3D10Effect* g_pEffect = NULL; ID3D10EffectTechnique* g_pTechnique = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; ID3D10Buffer* g_pIndexBuffer = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; D3DXMATRIX g_World; D3DXMATRIX g_View; D3DXMATRIX g_Projection; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ){ CleanupDevice(); return 0; } // Loop principal de mensagens MSG msg = {0}; while( WM_QUIT != msg.message ){ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 4: Espaços 3D", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Cria o dispositivo Direct3D e a cadeia de troca HRESULT InitDevice(){ HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ){ g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // cria uma visão de renderização alvo (Render Target) ID3D10Texture2D* pBackBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID *) &pBackBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, & g_pRenderTargetView, NULL ); // Configure o viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); //Crie o efeito DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configure a opção D3D10_SHADER_DEBUG para embutir informação de debug nos shaders. // Configurar esta opção melhora a debugação do shader, mas ainda permite aos // shaders serem otimizados e executarem da maneira que eles executarão na // configuração release deste programa dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"..\\Tutorial04.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ){ MessageBox( g_hWnd, L"O arquivo fx não pôde ser localizado. Por favor execute este executável do diretório que contém o arquivo FX", L"Erro", MB_OK ); return hr; } // Obtem a técnica g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); // Obtém as variáveis g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); // Defina o leiaute de entrada D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Configure o leiaute de entrada g_pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Crie o buffer de vértice SimpleVertex vertices[] = { { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR4( 0.0f, 1.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR4( 1.0f, 1.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 1.0f ) }, }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 8; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Configure o buffer de vértice UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0,1, &g_pVertexBuffer, &stride, &offset ); // Cria o buffer de índice DWORD indices[] = { 3,1,0, 2,1,3, 0,5,4, 1,5,0, 3,4,7, 0,4,3, 1,6,5, 2,6,1, 2,7,6, 3,7,2, 6,4,5, 7,4,6, }; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * 36; // 36 vértices necessários para 12 triângulos em uma lista de triângulos bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = bd.MiscFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Configura o buffer de índice g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Configure a topologia primitiva g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Inicialize a matriz do mundo D3DXVECTOR3 Eye( 0.0f, 1.0f, -5.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Inicializa a matriz de projeção D3DXMatrixPerspectiveFovLH( &g_Projection, (float) D3DX_PI * 0.5f, width / (FLOAT) height, 0.1f, 100.0f ); return S_OK; } // Renderiza o quadro void Render(){ // Atualize nosso tempo static float t = 0.0f; if( g_driverType == D3D10_DRIVER_TYPE_REFERENCE ){ t += (float) D3DX_PI * 0.0125f; } else { static DWORD dwTimeStart = 0; DWORD dwTimeCur = GetTickCount(); if( dwTimeStart == 0 ) dwTimeStart = dwTimeCur; t = ( dwTimeCur - dwTimeStart ) / 1000.0f; } // Anime o cubo D3DXMatrixRotationY( &g_World, t ); // Limpe o buffer de trás float ClearColor[4] = {0.0f, 0.125f, 0.3f, 1.0f}; // vermelho, verde, azul, alfa g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); // Atualize as variáveis g_pWorldVariable->SetMatrix( (float* )&g_World ); g_pViewVariable->SetMatrix( (float* )&g_View ); g_pProjectionVariable->SetMatrix( (float* )&g_Projection ); // Renderize um triângulo D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechnique->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } // Apresenta a informação renderizada no buffer de trás para o buffer da frente (a tela) g_pSwapChain->Present(0,0); } // Limpa os objetos que nós criamos void CleanupDevice(){ if( g_pd3dDevice ) g_pd3dDevice->ClearState(); if( g_pVertexBuffer ) g_pVertexBuffer->Release(); if( g_pIndexBuffer ) g_pIndexBuffer->Release(); if( g_pVertexLayout ) g_pVertexLayout->Release(); if( g_pEffect ) g_pEffect->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); }
O shader que ele faz uso é o seguinte:
//-------------------------------------------------------------------------------------- // File: Tutorial04.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- matrix World; matrix View; matrix Projection; //-------------------------------------------------------------------------------------- struct VS_OUTPUT { float4 Pos : SV_POSITION; float4 Color : COLOR0; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR ) { VS_OUTPUT output = (VS_OUTPUT)0; output.Pos = mul( Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Color = Color; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( VS_OUTPUT input ) : SV_Target { return input.Color; } //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Tutorial 05 - DXSDK - Animando cubos
Neste tutorial ocorre a animação de dois cubos. O intuito principal dele é mostrar como usar o buffer de profundidade para que os cubos sejam desenhados apropriadamente na tela
// Esta aplicação demonstra animação usando transformações de matriz #include <windows.h> #include <d3d10.h> #include <d3dx10.h> struct SimpleVertex{ D3DXVECTOR3 Pos; D3DXVECTOR4 Color; }; HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; ID3D10Texture2D* g_pDepthStencil = NULL; ID3D10DepthStencilView* g_pDepthStencilView = NULL; ID3D10Effect* g_pEffect = NULL; ID3D10EffectTechnique* g_pTechnique = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; ID3D10Buffer* g_pIndexBuffer = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; D3DXMATRIX g_World1; D3DXMATRIX g_World2; D3DXMATRIX g_View; D3DXMATRIX g_Projection; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ){ CleanupDevice(); return 0; } // Loop principal de mensagens MSG msg = {0}; while( WM_QUIT != msg.message ){ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 5", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Cria o dispositivo Direct3D e a cadeia de troca HRESULT InitDevice(){ HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ){ g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // cria uma visão de renderização alvo (Render Target) ID3D10Texture2D* pBackBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID *) &pBackBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; // Cria textura stencil de profundidade D3D10_TEXTURE2D_DESC descDepth; descDepth.Width = width; descDepth.Height = height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D32_FLOAT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D10_USAGE_DEFAULT; descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil ); if( FAILED( hr ) ) return hr; // Cria a visão stencil de profundidade D3D10_DEPTH_STENCIL_VIEW_DESC descDSV; descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, & g_pRenderTargetView, g_pDepthStencilView ); // Configure o viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); //Cria o efeito DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configure a opção D3D10_SHADER_DEBUG para embutir informação de debug nos shaders. // Configurar esta opção melhora a debugação do shader, mas ainda permite aos // shaders serem otimizados e executarem da maneira que eles executarão na // configuração release deste programa dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"..\\Tutorial05.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ){ MessageBox( g_hWnd, L"O arquivo fx não pôde ser localizado. Por favor execute este executável do diretório que contém o arquivo FX", L"Erro", MB_OK ); return hr; } // Obtem a técnica g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); // Obtém as variáveis g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); // Defina o leiaute de entrada D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Configure o leiaute de entrada g_pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Crie o buffer de vértice SimpleVertex vertices[] = { { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR4( 0.0f, 0.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR4( 0.0f, 1.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR4( 0.0f, 1.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR4( 1.0f, 0.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR4( 1.0f, 1.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR4( 1.0f, 1.0f, 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR4( 0.0f, 0.0f, 0.0f, 1.0f ) }, }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 8; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Configure o buffer de vértice UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0,1, &g_pVertexBuffer, &stride, &offset ); // Cria o buffer de índice DWORD indices[] = { 3,1,0, 2,1,3, 0,5,4, 1,5,0, 3,4,7, 0,4,3, 1,6,5, 2,6,1, 2,7,6, 3,7,2, 6,4,5, 7,4,6, }; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * 36; // 36 vértices necessários para 12 triângulos em uma lista de triângulos bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = bd.MiscFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Configura o buffer de índice g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Configure a topologia primitiva g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Inicialize a matriz do mundo D3DXMatrixIdentity( &g_World1 ); D3DXMatrixIdentity( &g_World2 ); // Inicialize a matriz visão D3DXVECTOR3 Eye( 0.0f, 1.0f, -10.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Inicializa a matriz de projeção D3DXMatrixPerspectiveFovLH( &g_Projection, (float) D3DX_PI * 0.25f, width / (FLOAT) height, 0.1f, 100.0f ); return TRUE; } // Renderiza um quadro void Render(){ // Atualize nosso tempo static float t = 0.0f; if( g_driverType == D3D10_DRIVER_TYPE_REFERENCE ){ t += (float) D3DX_PI * 0.0125f; } else { static DWORD dwTimeStart = 0; DWORD dwTimeCur = GetTickCount(); if( dwTimeStart == 0 ) dwTimeStart = dwTimeCur; t = ( dwTimeCur - dwTimeStart ) / 1000.0f; } // Primeiro cubo: Rotacione ao redor da origem D3DXMatrixRotationY( &g_World1, t ); // Segundo cubo: Rotacione ao redor da origem D3DXMATRIX mTranslate; D3DXMATRIX mOrbit; D3DXMATRIX mSpin; D3DXMATRIX mScale; D3DXMatrixRotationZ( &mSpin, -t ); D3DXMatrixRotationY( &mOrbit, -t * 2.0f ); D3DXMatrixTranslation( &mTranslate, -4.0f, 0.0f, 0.0f ); D3DXMatrixScaling( &mScale, 0.3f, 0.3f, 0.3f ); D3DXMatrixMultiply( &g_World2, &mScale, &mSpin ); D3DXMatrixMultiply( &g_World2, &g_World2, &mTranslate ); D3DXMatrixMultiply( &g_World2, &g_World2, &mOrbit ); // Limpe o buffer de trás float ClearColor[4] = {0.0f, 0.125f, 0.3f, 1.0f}; // vermelho, verde, azul, alfa g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); // limpe o buffer de profundidade para 1.0 (profundidade máxima) g_pd3dDevice->ClearDepthStencilView( g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 ); // Atualize as variáveis para o primeiro cubo g_pWorldVariable->SetMatrix( (float* )&g_World1 ); g_pViewVariable->SetMatrix( (float* )&g_View ); g_pProjectionVariable->SetMatrix( (float* )&g_Projection ); // Renderize o primeiro cubo D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechnique->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } // Atualize as variáveis para o segundo cubo g_pWorldVariable->SetMatrix( (float* )&g_World2 ); g_pViewVariable->SetMatrix( (float* )&g_View ); g_pProjectionVariable->SetMatrix( (float* )&g_Projection ); // Renderize o segundo cubo for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechnique->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } // Apresenta a informação renderizada no buffer de trás para o buffer da frente (a tela) g_pSwapChain->Present(0,0); } // Limpa os objetos que nós criamos void CleanupDevice(){ if( g_pd3dDevice ) g_pd3dDevice->ClearState(); if( g_pVertexBuffer ) g_pVertexBuffer->Release(); if( g_pIndexBuffer ) g_pIndexBuffer->Release(); if( g_pVertexLayout ) g_pVertexLayout->Release(); if( g_pEffect ) g_pEffect->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); }
Este tutorial usa o mesmo arquivo de efeito que o anterior:
//-------------------------------------------------------------------------------------- // File: Tutorial05.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- matrix World; matrix View; matrix Projection; //-------------------------------------------------------------------------------------- struct VS_INPUT { float4 Pos : POSITION; float4 Color : COLOR; }; struct PS_INPUT { float4 Pos : SV_POSITION; float4 Color : COLOR; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul( input.Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Color = input.Color; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( PS_INPUT input) : SV_Target { return input.Color; } //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Tutorial 06 - DXSDK - Luzes
// Esta aplicação demonstra animação usando transformações de matriz #include <windows.h> #include <d3d10.h> #include <d3dx10.h> struct SimpleVertex{ D3DXVECTOR3 Pos; D3DXVECTOR3 Normal; }; HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; ID3D10Texture2D* g_pDepthStencil = NULL; ID3D10DepthStencilView* g_pDepthStencilView = NULL; ID3D10Effect* g_pEffect = NULL; ID3D10EffectTechnique* g_pTechniqueRender = NULL; ID3D10EffectTechnique* g_pTechniqueRenderLight = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; ID3D10Buffer* g_pIndexBuffer = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; ID3D10EffectVectorVariable* g_pLightDirVariable = NULL; ID3D10EffectVectorVariable* g_pLightColorVariable = NULL; ID3D10EffectVectorVariable* g_pOutputColorVariable = NULL; D3DXMATRIX g_World; D3DXMATRIX g_View; D3DXMATRIX g_Projection; HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ){ CleanupDevice(); return 0; } // Loop principal de mensagens MSG msg = {0}; while( WM_QUIT != msg.message ){ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 6", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Cria o dispositivo Direct3D e a cadeia de troca HRESULT InitDevice(){ HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ){ g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // cria uma visão de renderização alvo (Render Target) ID3D10Texture2D* pBackBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID *) &pBackBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; // Cria textura stencil de profundidade D3D10_TEXTURE2D_DESC descDepth; descDepth.Width = width; descDepth.Height = height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D32_FLOAT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D10_USAGE_DEFAULT; descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil ); if( FAILED( hr ) ) return hr; // Cria a visão stencil de profundidade D3D10_DEPTH_STENCIL_VIEW_DESC descDSV; descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, & g_pRenderTargetView, g_pDepthStencilView ); // Configure o viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); //Cria o efeito DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configure a opção D3D10_SHADER_DEBUG para embutir informação de debug nos shaders. // Configurar esta opção melhora a debugação do shader, mas ainda permite aos // shaders serem otimizados e executarem da maneira que eles executarão na // configuração release deste programa dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"..\\Tutorial06.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ){ MessageBox( g_hWnd, L"O arquivo fx não pôde ser localizado. Por favor execute este executável do diretório que contém o arquivo FX", L"Erro", MB_OK ); return hr; } // Obtem as técnicas g_pTechniqueRender = g_pEffect->GetTechniqueByName( "Render" ); g_pTechniqueRenderLight = g_pEffect->GetTechniqueByName( "RenderLight" ); // Obtém as variáveis g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); g_pLightDirVariable = g_pEffect->GetVariableByName( "vLightDir" )->AsVector(); g_pLightColorVariable = g_pEffect->GetVariableByName( "vLightColor" )->AsVector(); g_pOutputColorVariable = g_pEffect->GetVariableByName( "vOutputColor" )->AsVector(); // Defina o leiaute de entrada D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechniqueRender->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Configure o leiaute de entrada g_pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Crie o buffer de vértice SimpleVertex vertices[] = { { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, -1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR3( -1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 1.0f, 0.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR3( 0.0f, 0.0f, -1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR3( 0.0f, 0.0f, 1.0f ) }, }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 24; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Configure o buffer de vértice UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0,1, &g_pVertexBuffer, &stride, &offset ); // Cria o buffer de índice // Cria o buffer de vértice DWORD indices[] = { 3,1,0, 2,1,3, 6,4,5, 7,4,6, 11,9,8, 10,9,11, 14,12,13, 15,12,14, 19,17,16, 18,17,19, 22,20,21, 23,20,22 }; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * 36; bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = bd.MiscFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Configura o buffer de índice g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Configure a topologia primitiva g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Inicialize a matriz do mundo D3DXMatrixIdentity( &g_World ); // Inicialize a matriz visão D3DXVECTOR3 Eye( 0.0f, 4.0f, -10.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Inicializa a matriz de projeção D3DXMatrixPerspectiveFovLH( &g_Projection, (float) D3DX_PI * 0.25f, width / (FLOAT) height, 0.1f, 100.0f ); return TRUE; } // Renderiza um quadro void Render(){ // Atualize nosso tempo static float t = 0.0f; if( g_driverType == D3D10_DRIVER_TYPE_REFERENCE ){ t += (float) D3DX_PI * 0.0125f; } else { static DWORD dwTimeStart = 0; DWORD dwTimeCur = GetTickCount(); if( dwTimeStart == 0 ) dwTimeStart = dwTimeCur; t = ( dwTimeCur - dwTimeStart ) / 1000.0f; } // Rotacione o cubo ao redor da origem D3DXMatrixRotationY( &g_World, t ); // Configura nossos parâmetros de iluminação D3DXVECTOR4 vLightDirs[2] = { D3DXVECTOR4( -0.577f, 0.577f, -0.577f, 1.0f ), D3DXVECTOR4( 0.0f, 0.0f, -1.0f, 1.0f ), }; D3DXVECTOR4 vLightColors[2] = { D3DXVECTOR4( 0.5f, 0.5f, 0.5f, 1.0f ), D3DXVECTOR4( 0.5f, 0.0f, 0.0f, 1.0f ) }; // Rotaciona a segunda luz ao redor da origem D3DXMATRIX mRotate; D3DXVECTOR4 vOutDir; D3DXMatrixRotationY( &mRotate, -t * 2.0f ); D3DXVec3Transform( &vLightDirs[1], (D3DXVECTOR3*) &vLightDirs[1], &mRotate ); // Limpe o buffer de trás float ClearColor[4] = {0.0f, 0.125f, 0.3f, 1.0f}; // vermelho, verde, azul, alfa g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); // limpe o buffer de profundidade para 1.0 (profundidade máxima) g_pd3dDevice->ClearDepthStencilView( g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 ); // Atualiza as variáveis matriz g_pWorldVariable->SetMatrix( (float* )&g_World ); g_pViewVariable->SetMatrix( (float* )&g_View ); g_pProjectionVariable->SetMatrix( (float* )&g_Projection ); // Atualiza as variáveis de iluminação g_pLightDirVariable->SetFloatVectorArray( (float*) vLightDirs, 0, 2 ); g_pLightColorVariable->SetFloatVectorArray( (float*) vLightColors, 0, 2 ); // Renderiza o cubo D3D10_TECHNIQUE_DESC techDesc; g_pTechniqueRender->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechniqueRender->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } // Renderiza cada luz for( int m = 0; m < 2; ++m ){ D3DXMATRIX mLight; D3DXMATRIX mLightScale; D3DXVECTOR3 vLightPos = vLightDirs[m] * 5.0f; D3DXMatrixTranslation( &mLight, vLightPos.x, vLightPos.y, vLightPos.z ); D3DXMatrixScaling( &mLightScale, 0.2f, 0.2f, 0.2f ); mLight = mLightScale * mLight; // Atualiza a variável do mundo para refeltir a luz atual g_pWorldVariable->SetMatrix( (float*) &mLight ); g_pOutputColorVariable->SetFloatVector( (float*) &vLightColors[m] ); g_pTechniqueRender->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechniqueRenderLight->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } } // Apresenta nosso buffer de trás para o buffer da frente g_pSwapChain->Present(0,0); } // Limpa os objetos que nós criamos void CleanupDevice(){ if( g_pd3dDevice ) g_pd3dDevice->ClearState(); if( g_pVertexBuffer ) g_pVertexBuffer->Release(); if( g_pIndexBuffer ) g_pIndexBuffer->Release(); if( g_pVertexLayout ) g_pVertexLayout->Release(); if( g_pEffect ) g_pEffect->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pDepthStencil ) g_pDepthStencil->Release(); if( g_pDepthStencilView ) g_pDepthStencilView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); }
O shader para este exemplo é o sgeuinte:
//-------------------------------------------------------------------------------------- // File: Tutorial06.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- matrix World; matrix View; matrix Projection; float4 vLightDir[2]; float4 vLightColor[2]; float4 vOutputColor; //-------------------------------------------------------------------------------------- struct VS_INPUT { float4 Pos : POSITION; float3 Norm : NORMAL; }; struct PS_INPUT { float4 Pos : SV_POSITION; float3 Norm : TEXCOORD0; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul( input.Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Norm = mul( input.Norm, World ); return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( PS_INPUT input) : SV_Target { float4 finalColor = 0; //do NdotL lighting for 2 lights for(int i=0; i<2; i++) { finalColor += saturate( dot( (float3)vLightDir[i],input.Norm) * vLightColor[i] ); } finalColor.a = 1; return finalColor; } //-------------------------------------------------------------------------------------- // PSSolid - render a solid color //-------------------------------------------------------------------------------------- float4 PSSolid( PS_INPUT input) : SV_Target { return vOutputColor; } //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } } //-------------------------------------------------------------------------------------- technique10 RenderLight { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PSSolid() ) ); } }
Tutorial 07 - DXSDK - Mapeamento de textura
// Esta aplicação demonstra animação usando transformações de matriz #include <windows.h> #include <d3d10.h> #include <d3dx10.h> struct SimpleVertex{ D3DXVECTOR3 Pos; D3DXVECTOR2 Tex; }; HINSTANCE g_hInst = NULL; HWND g_hWnd = NULL; D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL; ID3D10Device* g_pd3dDevice = NULL; IDXGISwapChain* g_pSwapChain = NULL; ID3D10RenderTargetView* g_pRenderTargetView = NULL; ID3D10Effect* g_pEffect = NULL; ID3D10EffectTechnique* g_pTechnique = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; ID3D10Buffer* g_pIndexBuffer = NULL; ID3D10ShaderResourceView* g_pTextureRV = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; ID3D10EffectVectorVariable* g_pMeshColorVariable = NULL; ID3D10EffectShaderResourceVariable* g_pDiffuseVariable = NULL; D3DXMATRIX g_World; D3DXMATRIX g_View; D3DXMATRIX g_Projection; D3DXVECTOR4 g_vMeshColor( 0.7f, 0.7f, 0.7f, 1.0f ); HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ); HRESULT InitDevice(); void CleanupDevice(); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); void Render(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ if( FAILED( InitWindow( hInstance, nCmdShow ) ) ) return 0; if( FAILED( InitDevice() ) ){ CleanupDevice(); return 0; } // Loop principal de mensagens MSG msg = {0}; while( WM_QUIT != msg.message ){ if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); } } return (int) msg.wParam; } // Registra classe e cria janela HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow ){ // Registra a classe WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; //wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIcon = NULL; wcex.hCursor = LoadCursor( NULL, IDC_ARROW ); wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 ); wcex.lpszMenuName = NULL; wcex.lpszClassName = L"TutorialWindowClass"; //wcex.hIconSm = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 ); wcex.hIconSm = NULL; if( !RegisterClassEx( &wcex ) ) return E_FAIL; // Cria a janela g_hInst = hInstance; RECT rc = { 0, 0, 640, 480 }; AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 7", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL ); if( !g_hWnd ) return E_FAIL; ShowWindow( g_hWnd, nCmdShow ); return S_OK; } // Chamado toda vez que a aplicação recebe uma mensagem LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ){ PAINTSTRUCT ps; HDC hdc; switch( message ){ case WM_PAINT: hdc = BeginPaint( hWnd, &ps ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Cria o dispositivo Direct3D e a cadeia de troca HRESULT InitDevice(){ HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; #endif D3D10_DRIVER_TYPE driverTypes[] = { D3D10_DRIVER_TYPE_HARDWARE, D3D10_DRIVER_TYPE_REFERENCE }; UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] ); DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ){ g_driverType = driverTypes[driverTypeIndex]; hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice ); if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // cria uma visão de renderização alvo (Render Target) ID3D10Texture2D* pBackBuffer; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), (LPVOID *) &pBackBuffer ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pd3dDevice->OMSetRenderTargets( 1, & g_pRenderTargetView, NULL ); // Configure o viewport D3D10_VIEWPORT vp; vp.Width = width; vp.Height = height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = vp.TopLeftY = 0; g_pd3dDevice->RSSetViewports( 1, &vp ); //Cria o efeito DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configure a opção D3D10_SHADER_DEBUG para embutir informação de debug nos shaders. // Configurar esta opção melhora a debugação do shader, mas ainda permite aos // shaders serem otimizados e executarem da maneira que eles executarão na // configuração release deste programa dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"..\\Tutorial07.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, g_pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ){ MessageBox( g_hWnd, L"O arquivo fx não pôde ser localizado. Por favor execute este executável do diretório que contém o arquivo FX", L"Erro", MB_OK ); return hr; } // Obtem as técnicas g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); // Obtém as variáveis g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); g_pMeshColorVariable = g_pEffect->GetVariableByName( "vMeshColor" )->AsVector(); g_pDiffuseVariable = g_pEffect->GetVariableByName( "txDiffuse" )->AsShaderResource(); // Defina o leiaute de entrada D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA,0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA,0 }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Configure o leiaute de entrada g_pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Crie o buffer de vértice SimpleVertex vertices[] = { { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 24; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Configure o buffer de vértice UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pd3dDevice->IASetVertexBuffers( 0,1, &g_pVertexBuffer, &stride, &offset ); // Cria o buffer de índice // Cria o buffer de vértice DWORD indices[] = { 3,1,0, 2,1,3, 6,4,5, 7,4,6, 11,9,8, 10,9,11, 14,12,13, 15,12,14, 19,17,16, 18,17,19, 22,20,21, 23,20,22 }; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * 36; bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = bd.MiscFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Configura o buffer de índice g_pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Configura a topologia primitiva g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Carrega a textura hr = D3DX10CreateShaderResourceViewFromFile( g_pd3dDevice, L"..\\seafloor.dds", NULL, NULL, &g_pTextureRV, NULL ); if( FAILED( hr ) ) return hr; // Inicializa a matriz do mundo D3DXMatrixIdentity( &g_World ); // Inicializa a matriz visão D3DXVECTOR3 Eye( 0.0f, 3.0f, -6.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Inicializa a matriz de projeção D3DXMatrixPerspectiveFovLH( &g_Projection, (float) D3DX_PI * 0.25f, width / (FLOAT) height, 0.1f, 100.0f ); // Atualize variáveis que nunca mudarão g_pViewVariable->SetMatrix( (float*) &g_View ); g_pProjectionVariable->SetMatrix( (float*) &g_Projection ); g_pDiffuseVariable->SetResource( g_pTextureRV ); return S_OK; } // Renderiza um quadro void Render(){ // Atualize nosso tempo static float t = 0.0f; if( g_driverType == D3D10_DRIVER_TYPE_REFERENCE ){ t += (float) D3DX_PI * 0.0125f; } else { static DWORD dwTimeStart = 0; DWORD dwTimeCur = GetTickCount(); if( dwTimeStart == 0 ) dwTimeStart = dwTimeCur; t = ( dwTimeCur - dwTimeStart ) / 1000.0f; } // Rotacione o cubo ao redor da origem D3DXMatrixRotationY( &g_World, t ); // Modifica a cor g_vMeshColor.x = ( sinf( t*1.0f ) + 1.0f ) * 0.5f; g_vMeshColor.y = ( cosf( t*3.0f ) + 1.0f ) * 0.5f; g_vMeshColor.z = ( sinf( t*5.0f ) + 1.0f ) * 0.5f; // Limpa o buffer de trás float ClearColor[4] = {0.0f, 0.125f, 0.3f, 1.0f}; // vermelho, verde, azul, alfa g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor ); // Atualiza as variáveis que mudam uma vez por quadro g_pWorldVariable->SetMatrix( (float* )&g_World ); g_pMeshColorVariable->SetFloatVector( (float*) g_vMeshColor); // Renderiza o cubo D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechnique->GetPassByIndex( p )->Apply( 0 ); g_pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } // Apresenta nosso buffer de trás para o buffer da frente g_pSwapChain->Present(0,0); } // Limpa os objetos que nós criamos void CleanupDevice(){ if( g_pd3dDevice ) g_pd3dDevice->ClearState(); if( g_pVertexBuffer ) g_pVertexBuffer->Release(); if( g_pIndexBuffer ) g_pIndexBuffer->Release(); if( g_pVertexLayout ) g_pVertexLayout->Release(); if( g_pEffect ) g_pEffect->Release(); if( g_pRenderTargetView ) g_pRenderTargetView->Release(); if( g_pSwapChain ) g_pSwapChain->Release(); if( g_pd3dDevice ) g_pd3dDevice->Release(); }
E o código para o arquivo de efeito é:
//-------------------------------------------------------------------------------------- // File: Tutorial07.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- Texture2D txDiffuse; SamplerState samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; }; cbuffer cbNeverChanges { matrix View; }; cbuffer cbChangeOnResize { matrix Projection; }; cbuffer cbChangesEveryFrame { matrix World; float4 vMeshColor; }; struct VS_INPUT { float4 Pos : POSITION; float2 Tex : TEXCOORD; }; struct PS_INPUT { float4 Pos : SV_POSITION; float2 Tex : TEXCOORD0; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul( input.Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Tex = input.Tex; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( PS_INPUT input) : SV_Target { return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor; } //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Tutorial 08 - DXSDK - Introdução ao DXUT
Este tutorial aborda uma introdução ao DXUT. Nele são vistos quais as principais funções de callback que devem ser configuradas para que uma aplicação use das facilidades fornecidas por esta biblioteca utilitária. Ps: A funcionalidade é a mesma do tutorial 07.
// Introdução básica ao DXUT #include <windows.h> #include "DXUT\Core\DXUT.h" #include "DXUT\Core\DXUTmisc.h" #define DEG2RAD( a ) ( a * D3DX_PI / 180.0f ) struct SimpleVertex{ D3DXVECTOR3 Pos; D3DXVECTOR2 Tex; }; ID3D10Effect* g_pEffect = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10EffectTechnique* g_pTechnique = NULL; ID3D10Buffer* g_pVertexBuffer = NULL; ID3D10Buffer* g_pIndexBuffer = NULL; ID3D10ShaderResourceView* g_pTextureRV = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; ID3D10EffectVectorVariable* g_pMeshColorVariable = NULL; ID3D10EffectShaderResourceVariable* g_pDiffuseVariable = NULL; D3DXMATRIX g_World; D3DXMATRIX g_View; D3DXMATRIX g_Projection; D3DXVECTOR4 g_vMeshColor( 0.7f, 0.7f, 0.7f, 1.0f ); // Protótipos das funções bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ); HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); void CALLBACK OnD3D10ReleasingSwapChain( void* pUserContext ); void CALLBACK OnD3D10DestroyDevice( void* pUserContext ); LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void* pUserContext); void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ); void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUserContext ); bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void *pUserContext ); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ #if defined( DEBUG ) | defined( _DEBUG ) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // DXUT criará e usará o melhor equipamento disponível (ou D3D9 ou D3D10) // isto é dependente do sistema disponível no qual os CALLBACKS do D3D são configurados abaixo // Configure callbacks DXUT DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable ); DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice ); DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizeSwapChain ); DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain ); DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice ); DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( OnKeyboard ); DXUTSetCallbackFrameMove( OnFrameMove ); DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); DXUTInit( true, true, NULL ); // Parse da linha de comando, mostra caixas de mensagem no erro, sem parâmetros de linha de comando extra DXUTSetCursorSettings(true, true ); // Mostre o cursor e recorte ele (clip) quando em modo de tela cheia DXUTCreateWindow( L"Tutorial08" ); DXUTCreateDevice( true, 640, 480 ); DXUTMainLoop(); // Entra dentro do loop de renderização DXUT return DXUTGetExitCode(); } // Rejeita qualquer equipamento D3D10 que não é aceitável por retornar falso bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ){ return true; } // Crie quaisquer recursos que não são dependentes do buffer de trás HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void *pUserContext ){ HRESULT hr = S_OK; // Lê o arquivo de efeito D3DX DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined(DEBUG) || defined(_DEBUG) // Coloque a opção D3D10_SHADER_DEBUG para embutir informação de debug nos shaders. // Colocar estaopção melhora a experiência de debugação dos shaders, mas ainda permite // os shaders serem otimizados e executarem apropriadamente da maneira que eles // executarão na configuração release deste programa dwShaderFlags |= D3D10_SHADER_DEBUG; #endif hr = D3DX10CreateEffectFromFile( L"..\\Tutorial08.fx", NULL, NULL, "fx_4_0", dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ); if( FAILED( hr ) ){ MessageBox( NULL, L"O arquivo fx não pôde ser localizado. Por favor execute este executável do diretório que contém o arquivo FX", L"Erro", MB_OK ); V_RETURN( hr ); } // Obtem as técnicas g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); // Obtém as variáveis g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); g_pMeshColorVariable = g_pEffect->GetVariableByName( "vMeshColor" )->AsVector(); g_pDiffuseVariable = g_pEffect->GetVariableByName( "txDiffuse" )->AsShaderResource(); // Defina o leiaute de entrada D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA,0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA,0 }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); hr = pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ); if( FAILED( hr ) ) return hr; // Configure o leiaute de entrada pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Crie o buffer de vértice SimpleVertex vertices[] = { { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, -1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, -1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 0.0f ) }, { D3DXVECTOR3( 1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 1.0f, 1.0f ) }, { D3DXVECTOR3( -1.0f, 1.0f, 1.0f ), D3DXVECTOR2( 0.0f, 1.0f ) }, }; D3D10_BUFFER_DESC bd; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 24; bd.BindFlags = D3D10_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; D3D10_SUBRESOURCE_DATA InitData; InitData.pSysMem = vertices; hr = pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Configure o buffer de vértice UINT stride = sizeof( SimpleVertex ); UINT offset = 0; pd3dDevice->IASetVertexBuffers( 0,1, &g_pVertexBuffer, &stride, &offset ); // Cria o buffer de índice // Cria o buffer de vértice DWORD indices[] = { 3,1,0, 2,1,3, 6,4,5, 7,4,6, 11,9,8, 10,9,11, 14,12,13, 15,12,14, 19,17,16, 18,17,19, 22,20,21, 23,20,22 }; bd.Usage = D3D10_USAGE_DEFAULT; bd.ByteWidth = sizeof( DWORD ) * 36; bd.BindFlags = D3D10_BIND_INDEX_BUFFER; bd.CPUAccessFlags = bd.MiscFlags = 0; InitData.pSysMem = indices; V_RETURN( pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ) ); // Configura o buffer de índice pd3dDevice->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0 ); // Configura a topologia primitiva pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Carrega a textura hr = D3DX10CreateShaderResourceViewFromFile( pd3dDevice, L"..\\seafloor.dds", NULL, NULL, &g_pTextureRV, NULL ); // Inicializa a matriz do mundo D3DXMatrixIdentity( &g_World ); // Inicializa a matriz visão D3DXVECTOR3 Eye( 0.0f, 3.0f, -6.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Atualize variáveis que nunca mudarão g_pViewVariable->SetMatrix( (float*) &g_View ); g_pDiffuseVariable->SetResource( g_pTextureRV ); return S_OK; } // Crie quaisquer recursos D3D10 que dependam do buffer de trás // Crie e configure a textura stencial de profundidade se necessário HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC *pBufferSurfaceDesc, void *pUserContext){ // Configura os parâmetros de projeção de novo float fAspect = static_cast<float>( pBufferSurfaceDesc->Width) / static_cast<float>( pBufferSurfaceDesc->Height ); D3DXMatrixPerspectiveFovLH( &g_Projection, (float) D3DX_PI * 0.25f, fAspect, 0.1f, 100.0f ); g_pProjectionVariable->SetMatrix( (float*) &g_Projection ); return S_OK; } // Renderiza a cena usando o dispositivo D3D10 void CALLBACK OnD3D10FrameRender( ID3D10Device *pd3dDevice, double fTime, float fElapsedTime, void *pUserContext ) { // Limpa o buffer de trás float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // vermelho, verde, azul, alfa ID3D10RenderTargetView *pRTV = DXUTGetD3D10RenderTargetView(); pd3dDevice->ClearRenderTargetView(pRTV, ClearColor ); // limpa o stencil de profundidade ID3D10DepthStencilView *pDSV = DXUTGetD3D10DepthStencilView(); pd3dDevice->ClearDepthStencilView( pDSV, D3D10_CLEAR_DEPTH, 1.0, 0 ); // Atualiza as variáveis que mudam uma vez por quadro g_pWorldVariable->SetMatrix( (float* )&g_World ); g_pMeshColorVariable->SetFloatVector( (float*) g_vMeshColor); // Renderiza o cubo D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); for( UINT p = 0; p < techDesc.Passes; ++p ){ g_pTechnique->GetPassByIndex( p )->Apply( 0 ); pd3dDevice->DrawIndexed( 36, 0, 0 ); // 36 vértices necessários para 12 triângulos em uma lista de triângulos } } // Libera recursos D3D10 criados em OnD3D10ResizedSwapChain void CALLBACK OnD3D10ReleasingSwapChain( void *pUserContext ){ } // Libera recursos D3D10 criados em OnD3D10CreateDevice void CALLBACK OnD3D10DestroyDevice( void *pUserContext ){ SAFE_RELEASE( g_pVertexBuffer ); SAFE_RELEASE( g_pIndexBuffer ); SAFE_RELEASE( g_pVertexLayout ); SAFE_RELEASE( g_pTextureRV ); SAFE_RELEASE( g_pEffect ); } // Chamado imediatamente antes de criar um dispositivo D3D9 oy D3D10, permitindo o aplicativo modificar // as configurações do dispositivo como necessário bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *pDeviceSettings, void *pUserContext ){ return true; } // Trata das atualizações na cena. Isto é chamado indiferentemente de qual API D3D é usada void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUsetContex ){ // Rotaciona p cubo ao redor da origem D3DXMatrixRotationY( &g_World, 60.0f * DEG2RAD( (float) fTime ) ); // Modifique a cor g_vMeshColor.x = ( sinf( (float) fTime *1.0f ) + 1.0f) * 0.5f; g_vMeshColor.y = ( cosf( (float) fTime *3.0f ) + 1.0f) * 0.5f; g_vMeshColor.z = ( sinf( (float) fTime *5.0f ) + 1.0f) * 0.5f; } // Manuseia as mensagens para a aplicação LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void *pUserContext ) { return 0; } // Manuseia pressionamentos do teclado void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ){ if( bKeyDown ){ switch( nChar ){ case VK_F1: // Change as needed break; } } }
O shader relacionado (Tutorial08.fx) é igual ao apresentado no Tutorial 07.
//-------------------------------------------------------------------------------------- // File: Tutorial08.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- Texture2D txDiffuse; SamplerState samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; }; cbuffer cbNeverChanges { matrix View; }; cbuffer cbChangeOnResize { matrix Projection; }; cbuffer cbChangesEveryFrame { matrix World; float4 vMeshColor; }; struct VS_INPUT { float4 Pos : POSITION; float2 Tex : TEXCOORD; }; struct PS_INPUT { float4 Pos : SV_POSITION; float2 Tex : TEXCOORD0; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul( input.Pos, World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Tex = input.Tex; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( PS_INPUT input) : SV_Target { return txDiffuse.Sample( samLinear, input.Tex ) * vMeshColor; } //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Tutorial 09 - DXSDK - usando uma malha com DXUT
Este arquivo mostra como renderizar uma malha .x usando DXUT
// Carregamento de malha através do DXUT #include <windows.h> #include "DXUT.h" #include "DXUTmisc.h" #include "SDKmisc.h" #include "SDKmesh.h" #define DEG2RAD( a ) ( a * D3DX_PI / 180.0f ) ID3D10Effect* g_pEffect = NULL; ID3D10InputLayout* g_pVertexLayout = NULL; ID3D10EffectTechnique* g_pTechnique = NULL; CDXUTSDKMesh g_Mesh; ID3D10EffectShaderResourceVariable* g_ptxDiffuseVariable = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; D3DXMATRIX g_World; D3DXMATRIX g_View; D3DXMATRIX g_Projection; // Protótipos das funções bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ); HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); void CALLBACK OnD3D10ReleasingSwapChain( void* pUserContext ); void CALLBACK OnD3D10DestroyDevice( void* pUserContext ); LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void* pUserContext); void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ); void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUserContext ); bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void *pUserContext ); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ #if defined( DEBUG ) | defined( _DEBUG ) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // DXUT criará e usará o melhor equipamento disponível (ou D3D9 ou D3D10) // isto é dependente do sistema disponível no qual os CALLBACKS do D3D são configurados abaixo // Configure callbacks DXUT DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable ); DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice ); DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizeSwapChain ); DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain ); DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice ); DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( OnKeyboard ); DXUTSetCallbackFrameMove( OnFrameMove ); DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); DXUTInit( true, true, NULL ); // Parse da linha de comando, mostra caixas de mensagem no erro, sem parâmetros de linha de comando extra DXUTSetCursorSettings(true, true ); // Mostre o cursor e recorte ele (clip) quando em modo de tela cheia DXUTCreateWindow( L"Tutorial09" ); DXUTCreateDevice( true, 640, 480 ); DXUTMainLoop(); // Entra dentro do loop de renderização DXUT return DXUTGetExitCode(); } // Rejeita qualquer equipamento D3D10 que não é aceitável por retornar falso bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ){ return true; } // Crie quaisquer recursos que não são dependentes do buffer de trás HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; // Find the D3DX effect file WCHAR str[MAX_PATH]; V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"..\\Tutorial09.fx" ) ); DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Set the D3D10_SHADER_DEBUG flag to embed debug information in the shaders. // Setting this flag improves the shader debugging experience, but still allows // the shaders to be optimized and to run exactly the way they will run in // the release configuration of this program. dwShaderFlags |= D3D10_SHADER_DEBUG; #endif V_RETURN( D3DX10CreateEffectFromFile( str, NULL, NULL, "fx_4_0", dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ) ); // Obtain the technique g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); g_ptxDiffuseVariable = g_pEffect->GetVariableByName( "g_txDiffuse" )->AsShaderResource(); g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); // Define the input layout const D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Create the input layout D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); V_RETURN( pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ) ); // Set the input layout pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Load the mesh V_RETURN( g_Mesh.Create( pd3dDevice, L"..\\Media\\Tiny\\tiny.sdkmesh", true ) ); // Initialize the world matrices D3DXMatrixIdentity( &g_World ); // Initialize the view matrix D3DXVECTOR3 Eye( 0.0f, 3.0f, -500.0f ); D3DXVECTOR3 At( 0.0f, 1.0f, 0.0f ); D3DXVECTOR3 Up( 0.0f, 1.0f, 0.0f ); D3DXMatrixLookAtLH( &g_View, &Eye, &At, &Up ); // Update Variables that never change g_pViewVariable->SetMatrix( ( float* )&g_View ); return S_OK; } // Crie quaisquer recursos D3D10 que dependam do buffer de trás HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC *pBufferSurfaceDesc, void *pUserContext) { // Configura os parâmetros de projeção de novo float fAspect = static_cast<float>( pBufferSurfaceDesc->Width) / static_cast<float>( pBufferSurfaceDesc->Height ); D3DXMatrixPerspectiveFovLH( &g_Projection, (float) D3DX_PI * 0.25f, fAspect, 0.5f, 1000.0f ); g_pProjectionVariable->SetMatrix( (float*) &g_Projection ); return S_OK; } // Renderiza a cena usando o dispositivo D3D10 void CALLBACK OnD3D10FrameRender( ID3D10Device *pd3dDevice, double fTime, float fElapsedTime, void *pUserContext ) { // Limpa o buffer de trás float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // vermelho, verde, azul, alfa ID3D10RenderTargetView *pRTV = DXUTGetD3D10RenderTargetView(); pd3dDevice->ClearRenderTargetView(pRTV, ClearColor ); // limpa o stencil de profundidade ID3D10DepthStencilView *pDSV = DXUTGetD3D10DepthStencilView(); pd3dDevice->ClearDepthStencilView( pDSV, D3D10_CLEAR_DEPTH, 1.0, 0 ); // Atualiza as variáveis que mudam uma vez por quadro g_pWorldVariable->SetMatrix( (float* )&g_World ); // Configura o leiaute de vértices pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Renderiza a malha UINT Strides[1]; UINT Offsets[1]; ID3D10Buffer* pVB[1]; pVB[0] = g_Mesh.GetVB10( 0, 0 ); Strides[0] = ( UINT ) g_Mesh.GetVertexStride(0,0); Offsets[0] = 0; pd3dDevice->IASetVertexBuffers(0, 1, pVB, Strides, Offsets); pd3dDevice->IASetIndexBuffer( g_Mesh.GetIB10( 0 ), g_Mesh.GetIBFormat10( 0 ), 0 ); D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); SDKMESH_SUBSET* pSubset = NULL; ID3D10ShaderResourceView* pDiffuseRV = NULL; D3D10_PRIMITIVE_TOPOLOGY PrimType; for( UINT p = 0; p < techDesc.Passes; ++p ){ for( UINT subset = 0; subset < g_Mesh.GetNumSubsets( 0 ); ++subset ){ pSubset = g_Mesh.GetSubset( 0, subset ); PrimType = g_Mesh.GetPrimitiveType10( ( SDKMESH_PRIMITIVE_TYPE ) pSubset->PrimitiveType ); pd3dDevice->IASetPrimitiveTopology( PrimType ); pDiffuseRV = g_Mesh.GetMaterial( pSubset->MaterialID )->pDiffuseRV10; g_ptxDiffuseVariable->SetResource( pDiffuseRV ); g_pTechnique->GetPassByIndex( p )->Apply( 0 ); pd3dDevice->DrawIndexed( ( UINT ) pSubset->IndexCount, 0, ( UINT ) pSubset->VertexStart ); } } // a classe de malha também tinha um método render que permite renderizar a malha com as opções mais comuns // g_pMesh.Render( pd3dDevice, g_pTechnique, g_ptxDiffuseVariable ); } // Libera recursos D3D10 criados em OnD3D10ResizedSwapChain void CALLBACK OnD3D10ReleasingSwapChain( void *pUserContext ){ } // Libera recursos D3D10 criados em OnD3D10CreateDevice void CALLBACK OnD3D10DestroyDevice( void *pUserContext ){ DXUTGetGlobalResourceCache().OnDestroyDevice(); SAFE_RELEASE( g_pVertexLayout ); SAFE_RELEASE( g_pEffect ); g_Mesh.Destroy(); } // Chamado imediatamente antes de criar um dispositivo D3D9 oy D3D10, permitindo o aplicativo modificar // as configurações do dispositivo como necessário bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *pDeviceSettings, void *pUserContext ){ return true; } // Trata das atualizações na cena. Isto é chamado indiferentemente de qual API D3D é usada void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUsetContex ){ // Rotaciona p cubo ao redor da origem D3DXMatrixRotationY( &g_World, 60.0f * DEG2RAD( (float) fTime ) ); } // Manuseia as mensagens para a aplicação LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void *pUserContext ) { return 0; } // Manuseia pressionamentos do teclado void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ){ if( bKeyDown ){ switch( nChar ){ case VK_F1: // Change as needed break; } } }
O arquivo de efeito que acompanho o exemplo é mostrado logo abaixo
//-------------------------------------------------------------------------------------- // File: Tutorial08.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- Texture2D g_txDiffuse; SamplerState samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; }; cbuffer cbConstant { float3 vLightDir = float3(-0.577,0.577,-0.577); }; cbuffer cbChangesOnce { matrix View; }; cbuffer cbChangeOnResize { matrix Projection; }; cbuffer cbChangesEveryFrame { matrix World; }; struct VS_INPUT { float3 Pos : POSITION; //position float3 Norm : NORMAL; //normal float2 Tex : TEXCOORD0; //texture coordinate }; struct PS_INPUT { float4 Pos : SV_POSITION; float3 Norm : TEXCOORD0; float2 Tex : TEXCOORD1; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; output.Pos = mul( float4(input.Pos,1), World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Norm = mul( input.Norm, World ); output.Tex = input.Tex; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( PS_INPUT input) : SV_Target { //calculate lighting assuming light color is <1,1,1,1> float fLighting = saturate( dot( input.Norm, vLightDir ) ); float4 outputColor = g_txDiffuse.Sample( samLinear, input.Tex ) * fLighting; outputColor.a = 1; return outputColor; } //-------------------------------------------------------------------------------------- // Technique //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); } }
Tutorial 10 - DXSDK - DXUT Avançado
Esta amostra foca em características avanãdas do DXUT, mostrando como se pode integrar funcionalidade GUI com DX
// Carregamento de malha através do DXUT #include <windows.h> #include "DXUT.h" #include "DXUTcamera.h" #include "DXUTgui.h" #include "DXUTsettingsDlg.h" #include "DXUTmisc.h" #include "SDKmisc.h" #include "SDKmesh.h" #define DEG2RAD( a ) ( a * D3DX_PI / 180.0f ) CModelViewerCamera g_Camera; // Uma câmera de visualização do modelo CDXUTDialogResourceManager g_DialogResourceManager; // gerente para recursos compartilhados de diálogos CD3DSettingsDlg g_D3DSettingsDialog; // diálogo de configurações do dispositivo CDXUTDialog g_HUD; // gerencia a UI 3D CDXUTDialog g_SampleUI; // diálogo para controles específicos da amostra ID3DX10Font* g_pFont = NULL; // Fonte para desenho de texto ID3DX10Sprite* g_pSprite = NULL; // SPrite para desenho de texto em lote CDXUTTextHelper* g_pTxtHelper = NULL; ID3D10Effect* g_pEffect = NULL; // interface de efeito D3DX ID3D10InputLayout* g_pVertexLayout = NULL; // Leiaute de vértice ID3D10EffectTechnique* g_pTechnique = NULL; CDXUTSDKMesh g_Mesh; ID3D10EffectShaderResourceVariable* g_ptxDiffuseVariable = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; ID3D10EffectScalarVariable* g_pPuffiness = NULL; D3DXMATRIX g_World; float g_fModelPuffiness; bool g_bSpinning = true; // IDs de controle da UI #define IDC_TOGGLEFULLSCREEN 1 #define IDC_TOGGLEREF 2 #define IDC_CHANGEDEVICE 3 #define IDC_TOGGLESPIN 4 #define IDC_PUFF_SCALE 5 #define IDC_PUFF_STATIC 6 #define IDC_TOGGLEWARP 7 // Protótipos das funções bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ); HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); void CALLBACK OnD3D10ReleasingSwapChain( void* pUserContext ); void CALLBACK OnD3D10DestroyDevice( void* pUserContext ); void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void *pUserContext ); LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void* pUserContext); void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ); void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUserContext ); bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void *pUserContext ); void RenderText(); void InitApp(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ #if defined( DEBUG ) | defined( _DEBUG ) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // DXUT criará e usará o melhor equipamento disponível (ou D3D9 ou D3D10) // isto é dependente do sistema disponível no qual os CALLBACKS do D3D são configurados abaixo // Configure callbacks DXUT DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable ); DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice ); DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizeSwapChain ); DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain ); DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice ); DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( OnKeyboard ); DXUTSetCallbackFrameMove( OnFrameMove ); DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); DXUTInit( true, true, NULL ); // Parse da linha de comando, mostra caixas de mensagem no erro, sem parâmetros de linha de comando extra DXUTSetCursorSettings(true, true ); // Mostre o cursor e recorte ele (clip) quando em modo de tela cheia InitApp(); DXUTCreateWindow( L"Tutorial10" ); DXUTCreateDevice( true, 640, 480 ); DXUTMainLoop(); // Entra dentro do loop de renderização DXUT return DXUTGetExitCode(); } // Inicializa a aplicação void InitApp() { g_fModelPuffiness = 0.0f; g_bSpinning = true; g_D3DSettingsDialog.Init( &g_DialogResourceManager ); g_HUD.Init( &g_DialogResourceManager ); g_SampleUI.Init( &g_DialogResourceManager ); g_HUD.SetCallback( OnGUIEvent ); int iY = 10; g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Mudar para tela cheia", 35, iY, 125, 22 ); g_HUD.AddButton( IDC_CHANGEDEVICE, L"Mudar dispositivo (F2)", 35, iY += 24, 125, 22, VK_F2 ); g_HUD.AddButton( IDC_TOGGLEREF, L"Mudar para REF (F3)", 35, iY += 24, 125, 22, VK_F3 ); g_HUD.AddButton( IDC_TOGGLEWARP, L"Mudar para WARP( F4 )", 35, iY+= 24, 125, 22, VK_F4 ); g_SampleUI.SetCallback( OnGUIEvent); iY = 10; WCHAR sz[100]; iY += 24; swprintf_s( sz, 100, L"Inchaço: %0.2f", g_fModelPuffiness ); g_SampleUI.AddStatic( IDC_PUFF_STATIC, sz, 35, iY += 24, 125, 22 ); g_SampleUI.AddSlider( IDC_PUFF_SCALE, 50, iY += 24, 100, 22, 0, 2000, ( int ) ( g_fModelPuffiness * 100.0f ) ); iY += 24; g_SampleUI.AddCheckBox( IDC_TOGGLESPIN, L"Girar", 35, iY += 24, 125, 22, g_bSpinning ); } // Rejeita qualquer equipamento D3D10 que não é aceitável por retornar falso bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ){ return true; } // Crie quaisquer recursos que não são dependentes do buffer de trás HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; V_RETURN( g_DialogResourceManager.OnD3D10CreateDevice( pd3dDevice ) ); V_RETURN( g_D3DSettingsDialog.OnD3D10CreateDevice( pd3dDevice ) ); V_RETURN( D3DX10CreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ) ); V_RETURN( D3DX10CreateSprite( pd3dDevice, 512, &g_pSprite ) ); g_pTxtHelper = new CDXUTTextHelper( NULL, NULL, g_pFont, g_pSprite, 15 ); DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configura a opção D3D10_SHADER_DEBUG para embutir informãção de debug nos shaders. // Configurar esta opção melhora a experiência de debugação do shader, mas ainda permite // que os shaders sejam otimizados para executar à maneira que eles executarão na // configuração release deste programa. dwShaderFlags |= D3D10_SHADER_DEBUG; #endif // Leia o arquivo de efeito D3DX WCHAR str[MAX_PATH]; V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"..\\Tutorial10.fx" ) ); V_RETURN( D3DX10CreateEffectFromFile( str, NULL, NULL, "fx_4_0", dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ) ); // Obtém a técnica g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); g_ptxDiffuseVariable = g_pEffect->GetVariableByName( "g_txDiffuse" )->AsShaderResource(); g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); g_pPuffiness = g_pEffect->GetVariableByName( "Puffiness" )->AsScalar(); // Configura o inchaço g_pPuffiness->SetFloat( g_fModelPuffiness ); // Define o leiaute de entrada const D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); V_RETURN( pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ) ); // Configura o leiaute de entrada pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Carrega a malha V_RETURN( g_Mesh.Create( pd3dDevice, L"..\\Media\\Tiny\\tiny.sdkmesh", true ) ); // Initializa as matrizes do mundo D3DXMatrixIdentity( &g_World ); // Initializa a câmera D3DXVECTOR3 Eye( 0.0f, 0.0f, -800.0f ); D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f ); g_Camera.SetViewParams( &Eye, &At ); return S_OK; } // Crie quaisquer recursos D3D10 que dependam do buffer de trás HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC *pBufferSurfaceDesc, void *pUserContext) { HRESULT hr; V_RETURN( g_DialogResourceManager.OnD3D10ResizedSwapChain( pd3dDevice, pBufferSurfaceDesc ) ); V_RETURN( g_D3DSettingsDialog.OnD3D10ResizedSwapChain( pd3dDevice, pBufferSurfaceDesc ) ); // Configura os parâmetros de projeção da câmera float fAspect = static_cast<float>( pBufferSurfaceDesc->Width) / static_cast<float>( pBufferSurfaceDesc->Height ); g_Camera.SetProjParams( D3DX_PI / 4, fAspect, 0.1f, 5000.0f ); g_Camera.SetWindow( pBufferSurfaceDesc->Width, pBufferSurfaceDesc->Height ); g_Camera.SetButtonMasks( MOUSE_MIDDLE_BUTTON, MOUSE_WHEEL, MOUSE_LEFT_BUTTON ); g_HUD.SetLocation( pBufferSurfaceDesc->Width -170, 0 ); g_HUD.SetSize( 170, 170 ); g_SampleUI.SetLocation( pBufferSurfaceDesc->Width - 170, pBufferSurfaceDesc->Height - 300 ); g_SampleUI.SetSize( 170, 300 ); return S_OK; } // Renderiza a cena usando o dispositivo D3D10 void CALLBACK OnD3D10FrameRender( ID3D10Device *pd3dDevice, double fTime, float fElapsedTime, void *pUserContext ) { // Limpa o buffer de trás float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // vermelho, verde, azul, alfa ID3D10RenderTargetView *pRTV = DXUTGetD3D10RenderTargetView(); pd3dDevice->ClearRenderTargetView(pRTV, ClearColor ); // Se o diálogo de configurações está sendo mostrado, então // renderiza ele ao invés de renderizar a cena da aplicação if( g_D3DSettingsDialog.IsActive() ) { g_D3DSettingsDialog.OnRender( fElapsedTime ); return; } // limpa o stencil de profundidade ID3D10DepthStencilView *pDSV = DXUTGetD3D10DepthStencilView(); pd3dDevice->ClearDepthStencilView( pDSV, D3D10_CLEAR_DEPTH, 1.0, 0 ); // Atualiza as variáveis que mudam uma vez por quadro g_pWorldVariable->SetMatrix( (float* )&g_World ); g_pViewVariable->SetMatrix( (float*) g_Camera.GetViewMatrix() ); g_pProjectionVariable->SetMatrix( (float*) g_Camera.GetProjMatrix() ); // Configura o leiaute de vértices pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Renderiza a malha UINT Strides[1]; UINT Offsets[1]; ID3D10Buffer* pVB[1]; pVB[0] = g_Mesh.GetVB10( 0, 0 ); Strides[0] = ( UINT ) g_Mesh.GetVertexStride(0,0); Offsets[0] = 0; pd3dDevice->IASetVertexBuffers(0, 1, pVB, Strides, Offsets); pd3dDevice->IASetIndexBuffer( g_Mesh.GetIB10( 0 ), g_Mesh.GetIBFormat10( 0 ), 0 ); D3D10_TECHNIQUE_DESC techDesc; g_pTechnique->GetDesc( &techDesc ); SDKMESH_SUBSET* pSubset = NULL; ID3D10ShaderResourceView* pDiffuseRV = NULL; D3D10_PRIMITIVE_TOPOLOGY PrimType; for( UINT p = 0; p < techDesc.Passes; ++p ){ for( UINT subset = 0; subset < g_Mesh.GetNumSubsets( 0 ); ++subset ){ pSubset = g_Mesh.GetSubset( 0, subset ); PrimType = g_Mesh.GetPrimitiveType10( ( SDKMESH_PRIMITIVE_TYPE ) pSubset->PrimitiveType ); pd3dDevice->IASetPrimitiveTopology( PrimType ); pDiffuseRV = g_Mesh.GetMaterial( pSubset->MaterialID )->pDiffuseRV10; g_ptxDiffuseVariable->SetResource( pDiffuseRV ); g_pTechnique->GetPassByIndex( p )->Apply( 0 ); pd3dDevice->DrawIndexed( ( UINT ) pSubset->IndexCount, 0, ( UINT ) pSubset->VertexStart ); } } // a classe de malha também tinha um método render que permite renderizar a malha com as opções mais comuns // g_pMesh.Render( pd3dDevice, g_pTechnique, g_ptxDiffuseVariable ); // Renderiza a UI g_HUD.OnRender( fElapsedTime ); g_SampleUI.OnRender( fElapsedTime ); RenderText(); } // Renderiza a ajuda e o texto das estatísticas void RenderText() { g_pTxtHelper->Begin(); g_pTxtHelper->SetInsertionPos( 2, 0 ); g_pTxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) ); g_pTxtHelper->DrawTextLine( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) ); g_pTxtHelper->DrawTextLine( DXUTGetDeviceStats() ); g_pTxtHelper->End(); } // Libera recursos D3D10 criados em OnD3D10ResizedSwapChain void CALLBACK OnD3D10ReleasingSwapChain( void *pUserContext ){ g_DialogResourceManager.OnD3D10ReleasingSwapChain(); } // Libera recursos D3D10 criados em OnD3D10CreateDevice void CALLBACK OnD3D10DestroyDevice( void *pUserContext ){ g_DialogResourceManager.OnD3D10DestroyDevice(); g_D3DSettingsDialog.OnD3D10DestroyDevice(); DXUTGetGlobalResourceCache().OnDestroyDevice(); SAFE_RELEASE( g_pFont ); SAFE_RELEASE( g_pSprite ); SAFE_DELETE( g_pTxtHelper ); SAFE_RELEASE( g_pVertexLayout ); SAFE_RELEASE( g_pEffect ); g_Mesh.Destroy(); } // Chamado imediatamente antes de criar um dispositivo D3D9 oy D3D10, permitindo o aplicativo modificar // as configurações do dispositivo como necessário bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings *pDeviceSettings, void *pUserContext ){ return true; } // Esta função de callback será chamada uma vez no início de todo quadro. Isto é o melhor // local para sua aplicação manusear atualizações para a cena, mas sua intenção não é // conter chamadas de renderização verdadeiras, que deveriam ser colocadas por sua vez // no callback OnFrameRender void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUsetContex ){ // Atualiza a posição da câmera baseada na entrada do usuário g_Camera.FrameMove( fElapsedTime ); if( g_bSpinning ){ D3DXMatrixRotationY( &g_World, 60.0f * DEG2RAD( (float) fTime ) ); } else { D3DXMatrixRotationY( &g_World, DEG2RAD( 180.0f ) ); } D3DXMATRIX mRot; D3DXMatrixRotationX( &mRot, DEG2RAD( -90.0f ) ); g_World = mRot *= g_World; } // Manuseia as mensagens para a aplicação LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void *pUserContext ) { // Passa as mensagens para as chamadas do gerenciador de recurso de diálogo para que // o estado da GUI seja atualizado corretamente *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; // Passe as mensagens para a configuração de diálogo se ela ainda estiver ativa if( g_D3DSettingsDialog.IsActive() ){ g_D3DSettingsDialog.MsgProc( hWnd, uMsg, wParam, lParam ); return 0; } // Dê aos diálogos uma chance de manusear a mensagem primeiro *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; // Passe todas as mensagens de janela restantes para a cãmera para que ela possa respodner à entrada do usuário g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); return 0; } // Manuseia pressionamentos do teclado void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ){ if( bKeyDown ){ switch( nChar ){ case VK_F1: // Change as needed break; } } } // Manuseia os eventos da GUI void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl *pControl, void *pUserContext ) { switch( nControlID ){ case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break; case IDC_TOGGLEREF: DXUTToggleREF(); break; case IDC_CHANGEDEVICE: g_D3DSettingsDialog.SetActive( !g_D3DSettingsDialog.IsActive() ); break; case IDC_TOGGLEWARP: DXUTToggleWARP(); break; case IDC_TOGGLESPIN:{ g_bSpinning = g_SampleUI.GetCheckBox( IDC_TOGGLESPIN )->GetChecked(); break; } case IDC_PUFF_SCALE: { WCHAR sz[100]; g_fModelPuffiness = (float) (g_SampleUI.GetSlider( IDC_PUFF_SCALE )->GetValue() * 0.01f ); swprintf_s( sz, 100, L"Inchaço: %0.2f", g_fModelPuffiness ); g_SampleUI.GetStatic( IDC_PUFF_STATIC )->SetText( sz ); g_pPuffiness->SetFloat( g_fModelPuffiness ); break; } } }
E o shader acompanhante que é responsável pelo efeito de inchaço da malha:
//-------------------------------------------------------------------------------------- // File: Tutorial10.fx // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------- // Constant Buffer Variables //-------------------------------------------------------------------------------------- Texture2D g_txDiffuse; SamplerState samLinear { Filter = MIN_MAG_MIP_LINEAR; AddressU = Wrap; AddressV = Wrap; }; cbuffer cbConstant { float3 vLightDir = float3(-0.577,0.577,-0.577); }; cbuffer cbChangesEveryFrame { matrix World; matrix View; matrix Projection; }; cbuffer cbUserChanges { float Puffiness; }; struct VS_INPUT { float3 Pos : POSITION; //position float3 Norm : NORMAL; //normal float2 Tex : TEXCOORD0; //texture coordinate }; struct PS_INPUT { float4 Pos : SV_POSITION; float3 Norm : TEXCOORD0; float2 Tex : TEXCOORD1; }; //-------------------------------------------------------------------------------------- // DepthStates //-------------------------------------------------------------------------------------- DepthStencilState EnableDepth { DepthEnable = TRUE; DepthWriteMask = ALL; DepthFunc = LESS_EQUAL; }; BlendState NoBlending { AlphaToCoverageEnable = FALSE; BlendEnable[0] = FALSE; }; //-------------------------------------------------------------------------------------- // Vertex Shader //-------------------------------------------------------------------------------------- PS_INPUT VS( VS_INPUT input ) { PS_INPUT output = (PS_INPUT)0; input.Pos += input.Norm*Puffiness; output.Pos = mul( float4(input.Pos,1), World ); output.Pos = mul( output.Pos, View ); output.Pos = mul( output.Pos, Projection ); output.Norm = mul( input.Norm, World ); output.Tex = input.Tex; return output; } //-------------------------------------------------------------------------------------- // Pixel Shader //-------------------------------------------------------------------------------------- float4 PS( PS_INPUT input) : SV_Target { // Calculate lighting assuming light color is <1,1,1,1> float fLighting = saturate( dot( input.Norm, vLightDir ) ); float4 outputColor = g_txDiffuse.Sample( samLinear, input.Tex ) * fLighting; outputColor.a = 1; return outputColor; } //-------------------------------------------------------------------------------------- // Technique //-------------------------------------------------------------------------------------- technique10 Render { pass P0 { SetVertexShader( CompileShader( vs_4_0, VS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, PS() ) ); SetDepthStencilState( EnableDepth, 0 ); SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
Tutorial 11 - DXSDK - Vertex Shader
Mesma aplicação que o Tutorial 10. A única mudança é o Vertex shader, usado para fazer um efeito de ondulação no espaço da tela.
// Carregamento de malha através do DXUT #include "DXUT.h" #include "DXUTcamera.h" #include "DXUTgui.h" #include "DXUTsettingsDlg.h" #include "DXUTmisc.h" #include "SDKmisc.h" #include "SDKmesh.h" #define DEG2RAD( a ) ( a * D3DX_PI / 180.0f ) // Variáveis globais específicas do DXUT CModelViewerCamera g_Camera; // Uma câmera de visualização do modelo CDXUTDialogResourceManager g_DialogResourceManager; // gerente para recursos compartilhados de diálogos CD3DSettingsDlg g_D3DSettingsDialog; // diálogo de configurações do dispositivo CDXUTDialog g_HUD; // gerencia a UI 3D CDXUTDialog g_SampleUI; // diálogo para controles específicos da amostra // Variáveis globais específicas da aplicação ID3DX10Font* g_pFont = NULL; // Fonte para desenho de texto ID3DX10Sprite* g_pSprite = NULL; // SPrite para desenho de texto em lote CDXUTTextHelper* g_pTxtHelper = NULL; ID3D10Effect* g_pEffect = NULL; // interface de efeito D3DX ID3D10InputLayout* g_pVertexLayout = NULL; // Leiaute de vértice ID3D10EffectTechnique* g_pTechnique = NULL; CDXUTSDKMesh g_Mesh; ID3D10EffectShaderResourceVariable* g_ptxDiffuseVariable = NULL; ID3D10EffectMatrixVariable* g_pWorldVariable = NULL; ID3D10EffectMatrixVariable* g_pViewVariable = NULL; ID3D10EffectMatrixVariable* g_pProjectionVariable = NULL; ID3D10EffectScalarVariable* g_pWavinessVariable = NULL; ID3D10EffectScalarVariable* g_pTimeVariable = NULL; D3DXMATRIX g_World; float g_fModelWaviness; bool g_bSpinning = true; // IDs de controle da UI #define IDC_TOGGLEFULLSCREEN 1 #define IDC_TOGGLEREF 2 #define IDC_CHANGEDEVICE 3 #define IDC_TOGGLESPIN 4 #define IDC_PUFF_SCALE 5 #define IDC_PUFF_STATIC 6 #define IDC_TOGGLEWARP 7 // Protótipos das funções bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ); HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext); void CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext ); void CALLBACK OnD3D10ReleasingSwapChain( void* pUserContext ); void CALLBACK OnD3D10DestroyDevice( void* pUserContext ); void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void *pUserContext ); LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool *pbNoFurtherProcessing, void* pUserContext); void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void *pUserContext ); void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void *pUserContext ); bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void *pUserContext ); void RenderText(); void InitApp(); // Ponto de entrada para o programa. Inicializa tudo e entra em um loop de processamento de // mensagem. Tempo ocioso é usado para renderizar a cena int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ){ // Habilita checagem de memória em tempo de execução para construções debug. #if defined( DEBUG ) | defined( _DEBUG ) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // DXUT criará e usará o melhor equipamento disponível (ou D3D9 ou D3D10) // isto é dependente do sistema disponível no qual os CALLBACKS do D3D são configurados abaixo // Configure callbacks DXUT DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable ); DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice ); DXUTSetCallbackD3D10SwapChainResized( OnD3D10ResizeSwapChain ); DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10ReleasingSwapChain ); DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice ); DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender ); DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( OnKeyboard ); DXUTSetCallbackFrameMove( OnFrameMove ); DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); InitApp(); DXUTInit( true, true, NULL ); // Parse da linha de comando, mostra caixas de mensagem no erro, sem parâmetros de linha de comando extra DXUTSetCursorSettings(true, true ); // Mostre o cursor e recorte ele (clip) quando em modo de tela cheia DXUTCreateWindow( L"Tutorial11" ); DXUTCreateDevice( true, 640, 480 ); DXUTMainLoop(); // Entra dentro do loop de renderização DXUT return DXUTGetExitCode(); } // Inicializa a aplicação void InitApp() { g_fModelWaviness = 0.0f; g_bSpinning = true; g_D3DSettingsDialog.Init( &g_DialogResourceManager ); g_HUD.Init( &g_DialogResourceManager ); g_SampleUI.Init( &g_DialogResourceManager ); g_HUD.SetCallback( OnGUIEvent ); int iY = 10; g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Mudar para tela cheia", 35, iY, 125, 22 ); g_HUD.AddButton( IDC_CHANGEDEVICE, L"Mudar dispositivo (F2)", 35, iY += 24, 125, 22, VK_F2 ); g_HUD.AddButton( IDC_TOGGLEREF, L"Mudar para REF (F3)", 35, iY += 24, 125, 22, VK_F3 ); g_HUD.AddButton( IDC_TOGGLEWARP, L"Mudar para WARP( F4 )", 35, iY+= 24, 125, 22, VK_F4 ); g_SampleUI.SetCallback( OnGUIEvent); iY = 10; WCHAR sz[100]; iY += 24; swprintf_s( sz, 100, L"Ondulação: %0.2f", g_fModelWaviness ); g_SampleUI.AddStatic( IDC_PUFF_STATIC, sz, 35, iY += 24, 125, 22 ); g_SampleUI.AddSlider( IDC_PUFF_SCALE, 50, iY += 24, 100, 22, 0, 2000, ( int ) ( g_fModelWaviness * 100.0f ) ); iY += 24; g_SampleUI.AddCheckBox( IDC_TOGGLESPIN, L"Girar", 35, iY += 24, 125, 22, g_bSpinning ); } // Rejeita qualquer equipamento D3D10 que não é aceitável por retornar falso bool CALLBACK IsD3D10DeviceAcceptable( UINT adapter, UINT output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BufferFormat, bool bWindowed, void *pUserContext ){ return true; } // Crie quaisquer recursos que não são dependentes do buffer de trás HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; V_RETURN( g_DialogResourceManager.OnD3D10CreateDevice( pd3dDevice ) ); V_RETURN( g_D3DSettingsDialog.OnD3D10CreateDevice( pd3dDevice ) ); V_RETURN( D3DX10CreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial", &g_pFont ) ); V_RETURN( D3DX10CreateSprite( pd3dDevice, 512, &g_pSprite ) ); g_pTxtHelper = new CDXUTTextHelper( NULL, NULL, g_pFont, g_pSprite, 15 ); DWORD dwShaderFlags = D3D10_SHADER_ENABLE_STRICTNESS; #if defined( DEBUG ) || defined( _DEBUG ) // Configura a opção D3D10_SHADER_DEBUG para embutir informãção de debug nos shaders. // Configurar esta opção melhora a experiência de debugação do shader, mas ainda permite // que os shaders sejam otimizados para executar à maneira que eles executarão na // configuração release deste programa. dwShaderFlags |= D3D10_SHADER_DEBUG; #endif // Ache o arquivo de efeito D3DX WCHAR str[MAX_PATH]; V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"..\\Tutorial11.fx" ) ); V_RETURN( D3DX10CreateEffectFromFile( str, NULL, NULL, "fx_4_0", dwShaderFlags, 0, pd3dDevice, NULL, NULL, &g_pEffect, NULL, NULL ) ); // Obtém a técnica g_pTechnique = g_pEffect->GetTechniqueByName( "Render" ); // Obtém as variáveis g_ptxDiffuseVariable = g_pEffect->GetVariableByName( "g_txDiffuse" )->AsShaderResource(); g_pWorldVariable = g_pEffect->GetVariableByName( "World" )->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName( "View" )->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName( "Projection" )->AsMatrix(); g_pWavinessVariable = g_pEffect->GetVariableByName( "Waviness" )->AsScalar(); g_pTimeVariable = g_pEffect->GetVariableByName( "Time" )->AsScalar(); // Configura a ondulação g_pWavinessVariable->SetFloat( g_fModelWaviness ); // Define o leiaute de entrada const D3D10_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D10_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = sizeof( layout ) / sizeof( layout[0] ); // Cria o leiaute de entrada D3D10_PASS_DESC PassDesc; g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc ); V_RETURN( pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize, &g_pVertexLayout ) ); // Configura o leiaute de entrada pd3dDevice->IASetInputLayout( g_pVertexLayout ); // Carrega a malha V_RETURN( g_Mesh.Create( pd3dDevice, L"..\\Media\\Tiny\\tiny.sdkmesh", true ) ); // Initializa as matrizes do mundo D3DXMatrixIdentity( &g_World ); // Initializa a câmera D3DXVECTOR3 Eye( 0.0f, 0.0f, -800.0f ); D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f ); g_Camera.SetViewParams( &Eye, &At ); return S_OK; } // Crie quaisquer recursos D3D10 que dependam do buffer de trás HRESULT CALLBACK OnD3D10ResizeSwapChain( ID3D10Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC *pBufferSurfaceDesc, void *pUserContext) { HRESULT hr; V_RETURN( g_DialogResourceManager.OnD3D10ResizedSwapChain( pd3dDevice, pBufferSurfaceDesc ) ); V_RETURN( g_D3DSettingsDialog.OnD3D10ResizedSwapChain( pd3dDevice, pBufferSurfaceDesc ) ); // Configura os parâmetros de projeção da câmera float fAspect = static_cast<float>( pBufferSurfaceDesc->Width) / static_cast<float>( pBufferSurfaceDesc->Height ); g_Camera.SetProjParams( D3DX_PI / 4, fAspect, 0.1f, 5000.0f ); g_Camera.SetWindow( pBufferSurfaceDesc->Width, pBufferSurfaceDesc->Height ); g_Camera.SetButtonMasks( MOUSE_MIDDLE_BUTTON, MOUSE_WHEEL, MOUSE_LEFT_BUTTON ); g_HUD.SetLocation( pBufferSurfaceDesc->Width -170, 0 ); g_HUD.SetSize( 170, 170 ); g_SampleUI.SetLocation( pBufferSurfaceDesc->Width - 170, pBufferSurfaceDesc->Height