⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blois.cpp

📁 著名的GPU Gems中的自然效果模拟-水效果的演示程序及全部实现源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//-----------------------------------------------------------------------------
// File: bLois.cpp
//
// Desc: DirectX window application created by the DirectX AppWizard
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <basetsd.h>
#include <direct.h>
#include <math.h>
#include <stdio.h>
#include <d3dx9.h>
#include <dxerr9.h>
#include <tchar.h>
#include "DXUtil.h"
#include "D3DEnumeration.h"
#include "D3DSettings.h"
#include "D3DApp.h"
#include "D3DFont.h"
#include "D3DFile.h"
#include "D3DUtil.h"
#include "resource.h"
#include "bLois.h"
#include <algorithm>
#include <functional>

static float RandMinusOneToOne()
{
	return float( double(rand()) / double(RAND_MAX) * 2.0 - 1.0 );
}

static float RandZeroToOne()
{
	return float( double(rand()) / double(RAND_MAX) );
}

static const float kGravConst = 30.f;

class ClearVert
{
public:
	D3DXVECTOR3		m_Pos;
	D3DXVECTOR2		m_Uv;
};
static const int kVSize = sizeof(ClearVert);
static const DWORD kClearVertFVF = D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0);


//-----------------------------------------------------------------------------
// Global access to the app (needed for the global WndProc())
//-----------------------------------------------------------------------------
CMyD3DApplication* g_pApp  = NULL;
HINSTANCE          g_hInst = NULL;




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
//       message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    CMyD3DApplication d3dApp;

    g_pApp  = &d3dApp;
    g_hInst = hInst;

    InitCommonControls();
    if( FAILED( d3dApp.Create( hInst ) ) )
        return 0;

    return d3dApp.Run();
}




//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor.   Paired with ~CMyD3DApplication()
//       Member variables should be initialized to a known state here.  
//       The application window has not yet been created and no Direct3D device 
//       has been created, so any initialization that depends on a window or 
//       Direct3D should be deferred to a later stage. 
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
    m_dwCreationWidth           = 500;
    m_dwCreationHeight          = 375;
    m_strWindowTitle            = TEXT( "bLois" );
    m_d3dEnumeration.AppUsesDepthBuffer   = TRUE;
	m_bStartFullscreen			= false;
	m_bShowCursorWhenFullscreen	= false;

	m_bShowHelp = false;
	m_bSortWater = true;
	m_bDrawBump = false;
	m_LastToggle = 0.f;

    // Create a D3D font using d3dfont.cpp
    m_pFont                     = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
    m_bLoadingApp               = TRUE;

    memset(m_bKey, 0x00, sizeof(m_bKey));

    D3DXMatrixIdentity(&m_matView);
    D3DXMatrixIdentity(&m_matPosition);
    D3DXMatrixIdentity(&m_matProjection);

	m_CompCosinesEff = NULL;
	m_WaterEff = NULL;
	m_WaterMesh = NULL;
	m_LandMesh = NULL;
	m_PillarsMesh = NULL;

	m_EnvMap = NULL;
	m_LandTex = NULL;

	m_CosineLUT = NULL;
	m_BiasNoiseMap = NULL;
	
	m_BumpTex = NULL;
	m_BumpSurf = NULL;
	m_BumpRender = NULL;
	m_BumpVBuffer = NULL;

	m_WaterIndices = NULL;
	m_WaterFacePos = NULL;
	m_WaterSortData = NULL;


	ResetWater();
}




//-----------------------------------------------------------------------------
// Name: ~CMyD3DApplication()
// Desc: Application destructor.  Paired with CMyD3DApplication()
//-----------------------------------------------------------------------------
CMyD3DApplication::~CMyD3DApplication()
{
	delete [] m_WaterIndices;
	delete [] m_WaterFacePos;
	delete [] m_WaterSortData;
}




//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Paired with FinalCleanup().
//       The window has been created and the IDirect3D9 interface has been
//       created, but the device has not been created yet.  Here you can
//       perform application-related initialization and cleanup that does
//       not depend on a device.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
    // TODO: perform one time initialization

    // Drawing loading status message until app finishes loading
    SendMessage( m_hWnd, WM_PAINT, 0, 0 );

    m_bLoadingApp = FALSE;

    // Misc stuff

	D3DXMatrixLookAtLH(&m_matView, 
		&D3DXVECTOR3(0.f, -150.f, 50.f),
		&D3DXVECTOR3(0.f, 0.f, 0.f),
		&D3DXVECTOR3(0.f, 0.f, 1.f));

    D3DXMatrixInverse(&m_matPosition, NULL, &m_matView);

    return S_OK;
}









//-----------------------------------------------------------------------------
// Name: ConfirmDevice()
// Desc: Called during device initialization, this code checks the display device
//       for some minimum set of capabilities
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
                                          D3DFORMAT Format )
{
    UNREFERENCED_PARAMETER( Format );
    UNREFERENCED_PARAMETER( dwBehavior );
    UNREFERENCED_PARAMETER( pCaps );
    
    BOOL bCapsAcceptable;

    // TODO: Perform checks to see if these display caps are acceptable.
    bCapsAcceptable = TRUE;

    if( bCapsAcceptable )         
        return S_OK;
    else
        return E_FAIL;
}




//-----------------------------------------------------------------------------
// Name: InitDeviceObjects()
// Desc: Paired with DeleteDeviceObjects()
//       The device has been created.  Resources that are not lost on
//       Reset() can be created here -- resources in D3DPOOL_MANAGED,
//       D3DPOOL_SCRATCH, or D3DPOOL_SYSTEMMEM.  Image surfaces created via
//       CreateImageSurface are never lost and can be created here.  Vertex
//       shaders and pixel shaders can also be created here as they are not
//       lost on Reset().
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InitDeviceObjects()
{
    // TODO: create device objects

    HRESULT hr;

    // Init the font
    m_pFont->InitDeviceObjects( m_pd3dDevice );

	if( FAILED(hr = CreateCosineLUT()) )
		return hr;

	if( FAILED(hr = CreateBiasNoiseMap()) )
		return hr;

	if( FAILED(hr = D3DXCreateCubeTextureFromFile( m_pd3dDevice, TEXT("nvlobby_new_cube_mipmap.dds"), &m_EnvMap)) )
        return DXTRACE_ERR( "EnvMap load", hr );

	if( FAILED(hr = D3DXCreateTextureFromFile( m_pd3dDevice, "Sandy.dds", &m_LandTex)) )
		return hr;

    if( FAILED(hr = D3DXLoadMeshFromX(TEXT("LandMesh.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &m_LandMesh)) )
		return hr;

    if( FAILED(hr = D3DXLoadMeshFromX(TEXT("pillars.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &m_PillarsMesh)) )
		return hr;

	ID3DXMesh* waterMesh = NULL;
    if( FAILED(hr = D3DXLoadMeshFromX(TEXT("WaterMesh.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &waterMesh)) )
		return hr;

	if( FAILED( hr = CreateWaterMesh(waterMesh)) )
		return hr;

	if( FAILED(hr = CreateClearBuffer()) )
		return hr;

    LPD3DXBUFFER pBufferErrors = NULL;
    if( FAILED( hr = D3DXCreateEffectFromFile( m_pd3dDevice, "CompCosines.fx", NULL, NULL,
                                            0, NULL, &m_CompCosinesEff, &pBufferErrors) ) )
    {
		char* errStr = (char*)pBufferErrors->GetBufferPointer();
		OutputDebugString(errStr);
        return hr;
    }
	GetCompCosineEffParams();

	if( FAILED(hr =  D3DXCreateEffectFromFile( m_pd3dDevice, "WaterRip.fx", NULL, NULL,
                                            0, NULL, &m_WaterEff, &pBufferErrors) ) )
    {
		char* errStr = (char*)pBufferErrors->GetBufferPointer();
		OutputDebugString(errStr);
        return hr;
    }
	GetWaterParams();

    return S_OK;
}

HRESULT CMyD3DApplication::CreateWaterMesh(ID3DXMesh* waterMesh)
{
	// All this should happen off line. In particular, note the assumption of even
	// spacing in calculating the edge lengths, which defeats the whole purpose.
	// Still, it's a demo, not a game.
	struct OutVert
	{
		D3DXVECTOR3		m_Pos;
		DWORD			m_Color;
	};

	const DWORD kWaterFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
	HRESULT hr = waterMesh->CloneMeshFVF(D3DXMESH_MANAGED,
							kWaterFVF,
							m_pd3dDevice,
							&m_WaterMesh);

	SAFE_RELEASE(waterMesh);

	if( FAILED(hr) )
		return hr;

	const int nVerts = m_WaterMesh->GetNumVertices();

	OutVert* oVert;
	if( FAILED(hr = m_WaterMesh->LockVertexBuffer(0, (void**)&oVert)) )
		return hr;
	OutVert* origVert = oVert;

	D3DXVECTOR3 del = oVert[0].m_Pos - oVert[1].m_Pos;
	float dist = D3DXVec3Length(&del);
	if( dist < 1.f )
		dist = 1.f;
	UINT alpha = UINT(255.9f / dist);
	int i;
	for( i = 0; i < nVerts; i++ )
	{
		oVert->m_Color = alpha << 24 | 0x00ffffff;
		oVert++;
	}

	oVert = origVert;

	const int nFaces = m_WaterMesh->GetNumFaces();

	m_WaterIndices = new FaceIndices[nFaces];
	m_WaterFacePos = new D3DXVECTOR3[nFaces];
	m_WaterSortData = new FaceSortData[nFaces];

	DWORD* oIdx;
	if( FAILED(hr = m_WaterMesh->LockIndexBuffer(0, (void**)&oIdx)) )
	{
		m_WaterMesh->UnlockVertexBuffer();
		return hr;
	}
	memcpy(m_WaterIndices, oIdx, nFaces * sizeof(*m_WaterIndices));

	for( i = 0; i < nFaces; i++ )
	{
		D3DXVECTOR3 pos = oVert[m_WaterIndices[i].m_Idx[0]].m_Pos;

		pos += oVert[m_WaterIndices[i].m_Idx[1]].m_Pos;
		pos += oVert[m_WaterIndices[i].m_Idx[2]].m_Pos;
		pos.z = 0;

		pos /= 3.f;

		m_WaterFacePos[i] = pos;
	}


	m_WaterMesh->UnlockIndexBuffer();

	m_WaterMesh->UnlockVertexBuffer();

	return hr;
}

struct CompSortFace : public std::binary_function<FaceSortData, FaceSortData, bool>
{
	bool operator()( const FaceSortData& lhs, const FaceSortData& rhs) const
	{
		return lhs.m_Dist < rhs.m_Dist;
	}
};


void CMyD3DApplication::SortWaterMesh()
{
	const D3DXVECTOR3 eyePos(m_matPosition._41, m_matPosition._42, 0.f);
	const int nFaces = m_WaterMesh->GetNumFaces();
	int i;
	for( i = 0; i < nFaces; i++ )
	{
		D3DXVECTOR3 del(eyePos - m_WaterFacePos[i]);
		m_WaterSortData[i].m_Dist = D3DXVec3LengthSq(&del);
		m_WaterSortData[i].m_Idx = i;
	}

	FaceSortData* begin = m_WaterSortData;
	FaceSortData* end = begin + nFaces;

	std::sort(begin, end, CompSortFace());

	FaceIndices* oIdx;
	if( FAILED(m_WaterMesh->LockIndexBuffer(0, (void**)&oIdx)) )
	{
		m_WaterMesh->UnlockVertexBuffer();
		return;
	}

⌨️ 快捷键说明

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