Tutorial09 Dx10

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() ) );
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.