softparticles.cpp

来自「声音和图片的加载功能,不过运行起来有点卡」· C++ 代码 · 共 990 行 · 第 1/3 页

CPP
990
字号
//--------------------------------------------------------------------------------------
// File: SoftParticles.cpp
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "DXUT.h"
#include "DXUTgui.h"
#include "DXUTsettingsdlg.h"
#include "DXUTcamera.h"
#include "SDKmisc.h"
#include "SDKmesh.h"
#include "resource.h"

#define MAX_PARTICLES 500
struct PARTICLE_VERTEX
{
    D3DXVECTOR3	 Pos;
    D3DXVECTOR3  Vel;
    float		 Life;
    float		 Size;
};

//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
CModelViewerCamera      g_Camera;               // A model viewing camera
CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs
CD3DSettingsDlg         g_D3DSettingsDlg;       // Device settings dialog
CDXUTDialog             g_HUD;                  // manages the 3D UI
CDXUTDialog             g_SampleUI;             // dialog for sample specific controls

PARTICLE_VERTEX*		g_pCPUParticles = NULL;
DWORD*					g_pCPUParticleIndices = NULL;
float*					g_pParticleDepthArray = NULL;
CDXUTSDKMesh			g_ObjectMesh;
CDXUTSDKMesh			g_SkyMesh;

ID3DX10Font*            g_pFont10 = NULL;       
ID3DX10Sprite*          g_pSprite10 = NULL;
CDXUTTextHelper*        g_pTxtHelper = NULL;
ID3D10Effect*           g_pEffect10 = NULL;
ID3D10InputLayout*      g_pSceneVertexLayout = NULL;
ID3D10InputLayout*      g_pParticleVertexLayout = NULL;

ID3D10Texture2D*		  g_pDepthStencilTexture = NULL;
ID3D10DepthStencilView*	  g_pDepthStencilDSV = NULL;
ID3D10ShaderResourceView* g_pDepthStencilSRV = NULL;

ID3D10Buffer*           g_pParticleVB = NULL;
ID3D10Buffer*           g_pParticleIB = NULL;
ID3D10ShaderResourceView* g_pParticleTexRV = NULL;
ID3D10Texture3D*        g_pNoiseVolume = NULL;
ID3D10ShaderResourceView* g_pNoiseVolumeRV = NULL;
ID3D10Texture2D*        g_pColorGradTexture = NULL;
ID3D10ShaderResourceView* g_pColorGradTexRV = NULL;

ID3D10EffectTechnique*  g_pRenderScene = NULL;
ID3D10EffectTechnique*  g_pRenderSky = NULL;
ID3D10EffectTechnique*  g_pRenderBillboardParticlesHard = NULL;
ID3D10EffectTechnique*  g_pRenderBillboardParticlesODepth = NULL;
ID3D10EffectTechnique*  g_pRenderBillboardParticlesSoft = NULL;
ID3D10EffectTechnique*  g_pRenderBillboardParticlesODepthSoft = NULL;
ID3D10EffectTechnique*  g_pRenderVolumeParticlesHard = NULL;
ID3D10EffectTechnique*  g_pRenderVolumeParticlesSoft = NULL;
ID3D10EffectMatrixVariable* g_pmWorldViewProj = NULL;
ID3D10EffectMatrixVariable* g_pmWorldView = NULL;
ID3D10EffectMatrixVariable* g_pmWorld = NULL;
ID3D10EffectMatrixVariable* g_pmInvView = NULL;
ID3D10EffectMatrixVariable* g_pmInvProj = NULL;
ID3D10EffectScalarVariable* g_pfFadeDistance = NULL;
ID3D10EffectScalarVariable* g_pfSizeZScale = NULL;
ID3D10EffectVectorVariable* g_pvViewLightDir1 = NULL;
ID3D10EffectVectorVariable* g_pvViewLightDir2 = NULL;
ID3D10EffectVectorVariable* g_pvWorldLightDir1 = NULL;
ID3D10EffectVectorVariable* g_pvWorldLightDir2 = NULL;
ID3D10EffectVectorVariable* g_pvEyePt = NULL;
ID3D10EffectVectorVariable* g_pvViewDir = NULL;
ID3D10EffectVectorVariable* g_pvOctaveOffsets = NULL;
ID3D10EffectShaderResourceVariable* g_pDiffuseTex = NULL;
ID3D10EffectShaderResourceVariable* g_pNormalTex = NULL;
ID3D10EffectShaderResourceVariable* g_pColorGradient = NULL;
ID3D10EffectShaderResourceVariable* g_pVolumeDiffTex = NULL;
ID3D10EffectShaderResourceVariable* g_pVolumeNormTex = NULL;
ID3D10EffectShaderResourceVariable* g_pDepthTex = NULL;

enum PARTICLE_TECHNIQUE
{
    PT_VOLUME_SOFT = 0x0,
    PT_VOLUME_HARD,
    PT_BILLBOARD_ODEPTHSOFT,
    PT_BILLBOARD_ODEPTH,
    PT_BILLBOARD_SOFT,
    PT_BILLBOARD_HARD
};

float g_fFadeDistance = 1.0f;
float g_fParticleLifeSpan = 5.0f;
float g_fEmitRate = 0.015f;

float g_ParticleVel = 3.0f;
float g_fParticleMaxSize = 1.25f;
float g_fParticleMinSize = 1.0f;
bool  g_bAnimateParticles = true;


PARTICLE_TECHNIQUE g_ParticleTechnique = PT_VOLUME_SOFT;
D3DXVECTOR3 g_vLightDir1 = D3DXVECTOR3(1.705f,5.557f,-9.380f);
D3DXVECTOR3 g_vLightDir2 = D3DXVECTOR3(-5.947f,-5.342f,-5.733f);

//--------------------------------------------------------------------------------------
// UI control IDs
//--------------------------------------------------------------------------------------
#define IDC_STATIC             -1
#define IDC_TOGGLEFULLSCREEN    1
#define IDC_TOGGLEREF           3
#define IDC_CHANGEDEVICE        4
#define IDC_TECHNIQUE           5

//--------------------------------------------------------------------------------------
// Forward declarations 
//--------------------------------------------------------------------------------------
bool    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );
void    CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext );
void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );

bool    CALLBACK IsD3D10DeviceAcceptable( UINT Adapter, UINT Output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
HRESULT CALLBACK OnD3D10CreateDevice( ID3D10Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
HRESULT CALLBACK OnD3D10SwapChainResized( ID3D10Device* pd3dDevice, IDXGISwapChain *pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
void    CALLBACK OnD3D10SwapChainReleasing( void* pUserContext );
void    CALLBACK OnD3D10DestroyDevice( void* pUserContext );
void    CALLBACK OnD3D10FrameRender( ID3D10Device* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext );

void    InitApp();
void    RenderText();

HRESULT CreateParticleBuffers(ID3D10Device* pd3dDevice);
HRESULT CreateNoiseVolume( ID3D10Device* pd3dDevice, UINT VolumeSize );
void SortParticleBuffer( D3DXVECTOR3 vEye, D3DXVECTOR3 vDir );
void AdvanceParticles( ID3D10Device* pd3dDevice, double fTime, float fTimeDelta );
void UpdateParticleBuffers( ID3D10Device* pd3dDevice );

//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing 
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // DXUT will create and use the best device (either D3D9 or D3D10) 
    // that is available on the system depending on which D3D callbacks are set below

    // Set DXUT callbacks
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackKeyboard( KeyboardProc );
    DXUTSetCallbackFrameMove( OnFrameMove );
    DXUTSetCallbackD3D10DeviceAcceptable( IsD3D10DeviceAcceptable );
    DXUTSetCallbackD3D10DeviceCreated( OnD3D10CreateDevice );
    DXUTSetCallbackD3D10SwapChainResized( OnD3D10SwapChainResized );
    DXUTSetCallbackD3D10SwapChainReleasing( OnD3D10SwapChainReleasing );
    DXUTSetCallbackD3D10DeviceDestroyed( OnD3D10DestroyDevice );
    DXUTSetCallbackD3D10FrameRender( OnD3D10FrameRender );

    InitApp();
    DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"SoftParticles" );
    DXUTCreateDevice( true, 640, 480 );
    DXUTMainLoop(); // Enter into the DXUT render loop
}


//--------------------------------------------------------------------------------------
// Initialize the app 
//--------------------------------------------------------------------------------------
void InitApp()
{
    g_D3DSettingsDlg.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"Toggle full screen", 35, iY, 125, 22 );
    g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22, VK_F3 );
    g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22, VK_F2 );
    g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; 

    CDXUTComboBox* pComboBox = NULL;

    g_SampleUI.AddStatic( IDC_STATIC, L"(T)echnique", 0, 0, 105, 25 );
    g_SampleUI.AddComboBox( IDC_TECHNIQUE, 0, 25, 140, 24, 'T', false, &pComboBox );
    if( pComboBox )
        pComboBox->SetDropHeight( 80 );

    pComboBox->AddItem( L"Volume Soft", (void*)PT_VOLUME_SOFT );
    pComboBox->AddItem( L"Volume Hard", (void*)PT_VOLUME_HARD );
    pComboBox->AddItem( L"Depth Sprites Soft", (void*)PT_BILLBOARD_ODEPTHSOFT );
    pComboBox->AddItem( L"Depth Sprites Hard", (void*)PT_BILLBOARD_ODEPTH );
    pComboBox->AddItem( L"Billboard Soft", (void*)PT_BILLBOARD_SOFT );
    pComboBox->AddItem( L"Billboard Hard", (void*)PT_BILLBOARD_HARD );
}


//--------------------------------------------------------------------------------------
// Called right before creating a D3D9 or D3D10 device, allowing the app to modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
    // For the first device created if its a REF device, optionally display a warning dialog box
    static bool s_bFirstTime = true;
    if( s_bFirstTime )
    {
        s_bFirstTime = false;
        if( (DXUT_D3D9_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF) ||
            (DXUT_D3D10_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d10.DriverType == D3D10_DRIVER_TYPE_REFERENCE) )
            DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
    }

    // Disable MSAA settings from the settings dialog
    g_D3DSettingsDlg.GetDialogControl()->GetComboBox( DXUTSETTINGSDLG_D3D10_MULTISAMPLE_COUNT )->SetEnabled(false);
    g_D3DSettingsDlg.GetDialogControl()->GetComboBox( DXUTSETTINGSDLG_D3D10_MULTISAMPLE_QUALITY )->SetEnabled(false);
    g_D3DSettingsDlg.GetDialogControl()->GetStatic( DXUTSETTINGSDLG_D3D10_MULTISAMPLE_COUNT_LABEL )->SetEnabled(false);
    g_D3DSettingsDlg.GetDialogControl()->GetStatic( DXUTSETTINGSDLG_D3D10_MULTISAMPLE_QUALITY_LABEL )->SetEnabled(false);

    return true;
}

static int iFrame = 0;
//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
    // Update the camera's position based on user input 
    g_Camera.FrameMove( fElapsedTime );

    D3DXVECTOR3 vEye = *g_Camera.GetEyePt();
    D3DXVECTOR3 vDir = *g_Camera.GetLookAtPt() - vEye;
    D3DXVec3Normalize( &vDir, &vDir );

    ID3D10Device* pd3dDevice = DXUTGetD3D10Device();
    AdvanceParticles( pd3dDevice, fTime, fElapsedTime );
    SortParticleBuffer( vEye, vDir );
    UpdateParticleBuffers( pd3dDevice );

    // Update the movement of the noise octaves
    D3DXVECTOR4 OctaveOffsets[4];
    for( int i=0; i<4; i++ )
    {
        OctaveOffsets[i].x = -(float)(fTime*0.05);
        OctaveOffsets[i].y = 0;
        OctaveOffsets[i].z = 0;
        OctaveOffsets[i].w = 0;
    }
    g_pvOctaveOffsets->SetFloatVectorArray( (float*)OctaveOffsets, 0, 4 );
}


//--------------------------------------------------------------------------------------
// Handle messages to the application
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext )
{
    // Pass messages to dialog resource manager calls so GUI state is updated correctly
    *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass messages to settings dialog if its active
    if( g_D3DSettingsDlg.IsActive() )
    {
        g_D3DSettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
        return 0;
    }

    // Give the dialogs a chance to handle the message first
    *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;
    *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
    if( *pbNoFurtherProcessing )
        return 0;

    // Pass all remaining windows messages to camera so it can respond to user input
    g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );

    return 0;
}


//--------------------------------------------------------------------------------------
// Handle key presses
//--------------------------------------------------------------------------------------
void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
{
}


//--------------------------------------------------------------------------------------
// Handles the GUI events
//--------------------------------------------------------------------------------------
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_D3DSettingsDlg.SetActive( !g_D3DSettingsDlg.IsActive() ); break;

        case IDC_TECHNIQUE:
        {
            CDXUTComboBox* pComboBox = (CDXUTComboBox*)pControl;
            g_ParticleTechnique = (PARTICLE_TECHNIQUE)(int)PtrToInt(pComboBox->GetSelectedData());
        }
        break;
    }    
}


//--------------------------------------------------------------------------------------
// Reject any D3D10 devices that aren't acceptable by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D10DeviceAcceptable( UINT Adapter, UINT Output, D3D10_DRIVER_TYPE DeviceType, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
{

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?