Tutorial11 Dx10

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 - 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 )
{
    // 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 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_pViewVariable->SetMatrix( (float*) g_Camera.GetViewMatrix() );
    g_pProjectionVariable->SetMatrix( (float*) g_Camera.GetProjMatrix() );
    g_pTimeVariable->SetFloat( ( float ) fTime );
 
    // 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  ){
}
 
// 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_fModelWaviness = (float) (g_SampleUI.GetSlider( IDC_PUFF_SCALE )->GetValue() * 0.01f );
            swprintf_s( sz, 100, L"Ondulação: %0.2f", g_fModelWaviness );
            g_SampleUI.GetStatic( IDC_PUFF_STATIC )->SetText( sz );
            g_pWavinessVariable->SetFloat( g_fModelWaviness );
            break;
        }
    }
}

E o arquivo de efeito responsável pela ondulação:

//--------------------------------------------------------------------------------------
// File: Tutorial11.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;
    float Time;
};
 
cbuffer cbUserChanges
{
    float Waviness;
};
 
struct VS_INPUT
{
    float3 Pos          : POSITION;        
    float3 Norm         : NORMAL;          
    float2 Tex          : TEXCOORD0;       
};
 
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;
 
    output.Pos = mul( float4(input.Pos,1), World );
 
    output.Pos.x += sin( output.Pos.y*0.1f + Time )*Waviness;
 
    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 );
    }
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.