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

📄 ca_fire.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*********************************************************************NVMH2****
Path:  C:\Dev\devrel\Nv_sdk_4\Dx8\NVEffectsBrowser\Effects\CA_Fire
File:  CA_Fire.cpp

Copyright (C) 1999, 2000 NVIDIA Corporation
This file is provided without support, instruction, or implied warranty of any
kind.  NVIDIA makes no guarantee of its fitness for a particular purpose and is
not liable under any circumstances for any damages or loss whatsoever arising
from the use or inability to use this file or items derived from it.

Comments:

A class for generating a procedural texture animation fire effect.

The only thing tying it to the Effects Browser code is the GetFilePath()
  function for loading media and other files.
This is very easy to pull out of the code if you want to use the class
  elsewhere.  If all files are in directory of the executable,
  then the GetFilePath() call can be removed.


******************************************************************************/


#include <crtdbg.h>


#include "eb_effect.h"		// need for mouse button ID only
#include "eb_file.h"		// for GetFilePath and Load..Shader(..)
#include "CA_Fire.h"
#include "..\..\..\CommonSrc\NV_Error.h"			// for FDebug

#include "Constants.h"
#include "PixelConstants.h"

#include "ShaderManager.h"

#include "SimpleObject8.h"
#include "SimpleVBObject8.h"

using namespace std;


#define RULE_TABLE_NAME		"RuleTable.bmp"
#define INITIAL_FILENAME	"start.bmp"
#define OUTPUT_MAP_FILENAME	"OutputColors.bmp"


////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////


CA_Fire::CA_Fire()
{
	m_bWireframe			= false;
	m_pInitialStateTexture	= NULL;
	m_pOutputMapTexture		= NULL;

	m_dwVertexShader		= 0;
	m_SHI_SimpleObjVShader	= 0;
	m_dwTwoWeight_PostMultShader = 0;
	m_dwDependentAR			= 0;

	m_pVertexBuffer			= NULL;
	m_pObj					= NULL;

	mpBackbufferColor		= 0 ;
	mpBackbufferDepth		= 0 ;

	m_pInputTexture			= NULL;

	m_pD3DDev				= NULL;

	m_pUI = NULL;

	for ( int i = 0; i < kMaxNumTargets; ++i )
	{
        mpTextureFiltered[i] = 0;
		mpFilterTarget   [i] = 0;
	}

}

CA_Fire::~CA_Fire()
{
	Free();	
}

/////////////////////////////////////////////////////////


HRESULT CA_Fire::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
    // check vertex shading support
    if(D3DSHADER_VERSION_MAJOR(pCaps->VertexShaderVersion) < 1)
	{
		m_strLastError = "Device does not support vertex shaders!";
		return E_FAIL;
	}
    if(D3DSHADER_VERSION_MINOR(pCaps->VertexShaderVersion) < 1)
	{
		m_strLastError = "Device does not support 1.1 vertex shaders!";
		return E_FAIL;
	}

    // check simultaneous texture support
    if(pCaps->MaxSimultaneousTextures < 4)
	{
		m_strLastError = "Device does not support 4 simultaneous textures!";
		return E_FAIL;
	}

    // check pixel shader support
    if(D3DSHADER_VERSION_MAJOR(pCaps->PixelShaderVersion) < 1)
	{
		m_strLastError = "Device does not support pixel shaders!";
		return E_FAIL;
	}
	if(D3DSHADER_VERSION_MINOR(pCaps->PixelShaderVersion) < 1)
	{
		m_strLastError = "Device does not support 1.1 pixel shaders!";
		return E_FAIL;
	}
	if(pCaps->MaxTextureBlendStages < 8)
	{
		m_strLastError = "Device does not support 8 register combiners!";
		return E_FAIL;
	}


	return S_OK;
}




void CA_Fire::LoadRulesAndOtherMaps( IDirect3DTexture8 * pInitialTexture )
{
	// Load "rules" texture which determines how the neighbor accumulation 
	//  maps to new pixels
	// Also reload output color map 
	// Also reload initial conditions map

	EBString filename;
	HRESULT hr;

	
	if( pInitialTexture != NULL )
	{
		// Inc. ref count
		pInitialTexture->AddRef();

		m_pInitialStateTexture = pInitialTexture;

	}
	else
	{
		// load a default initial texture

		filename = INITIAL_FILENAME;

		hr = D3DXCreateTextureFromFile( m_pD3DDev, GetFilePath(filename.c_str()).c_str(),
										&m_pInitialStateTexture );

		ASSERT_IF_FAILED(hr);
		if (FAILED(hr))
		{
			m_strLastError = "Couldn't load texture: ";
			m_strLastError += filename;
			assert( false );
			return;
		}
	}


	filename = OUTPUT_MAP_FILENAME;

	hr = D3DXCreateTextureFromFile( m_pD3DDev, GetFilePath(filename.c_str()).c_str(),
									&m_pOutputMapTexture );

	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
	{
		m_strLastError = "Couldn't load texture: ";
		m_strLastError += filename;
		assert( false );
		return;
	}



	//  Not re-creating render targets.  This could be problem if 
	//   you reload an initial texture with different resolution while
	//   the simulation is running.  The new resolution will not be 
	//   reflected in the render targets

}



HRESULT CA_Fire::Initialize( LPDIRECT3DDEVICE8 pDev, ShaderManager * pManager, 
							 IDirect3DTexture8 * pInitialTexture )
{
	// Called when effect is selected from list in browser
	// Free() is called when effect is de-selected

	// pInitialTexture == texture which determines initial state AND
	//   resolution of the render targets on which this is run.  
	//   If NULL then a default start texture is loaded.

	assert( pDev != NULL );
	assert( pManager != NULL );

    int     i;
	HRESULT hr;


	m_pShaderManager = pManager;


	// get the device
	m_pD3DDev = pDev;
	pDev->AddRef();			// released on Free()



	//initialize mouse UI
	RECT rect;
	rect.left = rect.top = 0;
	D3DVIEWPORT8 viewport;
	m_pD3DDev->GetViewport(&viewport);
	rect.bottom = viewport.Height;
	rect.right  = viewport.Width;

	m_pUI = new MouseUI((const RECT)rect);
	assert( m_pUI != NULL );

	m_pUI->SetTranslationalSensitivityFactor(0.0001f);

    m_pUI->Reset();

	///////////////////////////////////////////////


	m_bReset = true;
	m_bAnimate = true;
	m_bSingleStep = false;

	m_bSlow = false;

	m_bFarther = false;
	m_bWrap = true;

	m_bMulticolor = false;

	m_nSlowDelay = 7;

	m_eRenderMode = FULLSCREEN_FINALOUT;

	m_nSkipInterval = 0;
	m_nFlipState = 0;


	// scales colors during each blurred sampling
	m_fColorAtten = 0.4959f;
	m_fColorAtten = 0.487f;

	// texel scrolling offset per frame
	m_fTranslateAmount = 2.5f;



	m_pOutputMapTexture = NULL;

	/////////////////////////////////

	// create the vertex and pixel shaders
	vector<DWORD> Declaration;
	Declaration.push_back(D3DVSD_STREAM(0));
	Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT2));
	Declaration.push_back(D3DVSD_END());


	hr = m_pShaderManager->LoadAndCreateShader( GetFilePath("TexCoord_4_Offset.vso"),
							GetFilePath("TexCoord_4_Offset.nvv"), &Declaration[0], 0,
							SM_SHADERTYPE_VERTEX, &m_dwVertexShader);
	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
		return hr;
	
    hr = m_pShaderManager->LoadAndCreateShader(GetFilePath("TwoWeightCombine_PostMult.pso"),
							GetFilePath("TwoWeightCombine_PostMult.nvp"), NULL, 0,
							SM_SHADERTYPE_PIXEL, &(m_dwTwoWeight_PostMultShader));
	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
		return hr;


	// Dependent 2D lookup pixel shader.
	// This one is used to re-map the color of the smoke

    hr = m_pShaderManager->LoadAndCreateShader(GetFilePath("DependentAR.pso"),
							GetFilePath("DependentAR.nvp"), NULL, 0,
							SM_SHADERTYPE_PIXEL, &(m_dwDependentAR ) );
	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
		return hr;

	//////////////////////////////////////////////////////////////////////////
	// Another simple transform vertex shader for rendering the Simple..Object
	//  geometry that will be "on fire"
	
	// Fill in the format to correspond to that of a SimpleObjectVertex

	vector< DWORD > Decl2;
	Decl2.push_back( D3DVSD_STREAM(0) );
	Decl2.push_back( D3DVSD_REG(0, D3DVSDT_FLOAT3) );		// pos
	Decl2.push_back( D3DVSD_REG(1, D3DVSDT_FLOAT3) );		// normal
	Decl2.push_back( D3DVSD_REG(2, D3DVSDT_D3DCOLOR) );		// color
	Decl2.push_back( D3DVSD_REG(3, D3DVSDT_FLOAT2) );		// tex coord 2D
	Decl2.push_back( D3DVSD_END()		);


	hr = m_pShaderManager->LoadAndCreateShader( GetFilePath("SimpleObject_TexCoord_4_Offset.vso"),
							GetFilePath("SimpleObject_TexCoord_4_Offset.nvv"), &Decl2[0], 0,
							SM_SHADERTYPE_VERTEX, & m_SHI_SimpleObjVShader );
	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
		return hr;


	/////////////////////////////////////////////////////////////////////////
    // get a pointer to the current back-buffer (so we can restore it later)
	m_pD3DDev->GetRenderTarget(        &mpBackbufferColor );
	m_pD3DDev->GetDepthStencilSurface( &mpBackbufferDepth );



	D3DXVECTOR4  commonconst( 0.0f, 0.5f, 1.0f, 2.0f );
	m_pD3DDev->SetVertexShaderConstant( CV_CONSTS_1, &commonconst,    1);


	/////////////////////////////////


	// load the initial conditions texture map, and 
	//  optional final color re-mapping map

	LoadRulesAndOtherMaps( pInitialTexture );


	// Create additional texture surfaces to use as targets & 
	//  sources in the procedural animation

	hr = CreateTextureRenderTargets();
	ASSERT_IF_FAILED(hr);


	////////////////////////////////////////////////////////////////////////////

	D3DSURFACE_DESC ddsd;
    m_pInitialStateTexture->GetLevelDesc(0, &ddsd);

    CreateAndWriteUVOffsets(ddsd.Width, ddsd.Height);

	/////////////////////////////////////////////////////
	// Create an object for rendering the source embers 
	//  onto.  This could be a game character or anything
	//  "on fire"
	//* Ultimately, this fire effect class should not know
	//  or care about the nature of this object.  It could
	//  be any game object, but the work involved in
	//	abstracting this away is not warranted for this 
	//  first version of the technique.
	//* We should also use a zbuffer when rendering this
	//  object to the texture, but that is not done here.

	SimpleObject8 * pObj = new SimpleObject8;
	assert( pObj != NULL );

	pObj->InitTorus( 0.45f, 0.8f, 10, 15, 1.0f, 4.0f );

	m_pObj = new SimpleVBObject8( );
	assert( m_pObj != NULL );

	hr = m_pObj->CreateFromSimpleObject( pObj, m_pD3DDev );

	delete pObj;
	pObj = NULL;

	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
		return hr;

	

	/////////////////////////////////////////////////////
	// Create a single quad object to use for render-to-texture
	//  operations.  The world-view-proj matrices scale this
	//  quad to exactly cover the render target.

	// create vertex buffer 

	hr = m_pD3DDev->CreateVertexBuffer( 4 * sizeof(QuadVertex), D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &m_pVertexBuffer);
	ASSERT_IF_FAILED(hr);
	if (FAILED(hr))
		return hr;

	QuadVertex      *pBuff;

	if (m_pVertexBuffer)
	{
		hr = m_pVertexBuffer->Lock(0, 4 * sizeof(QuadVertex),(BYTE**)&pBuff, 0);
		ASSERT_IF_FAILED(hr);
		if (FAILED(hr))
		{
			m_strLastError = "Couldn't lock buffer!";
			return hr;
		}


		float uv_base;
		float uv_max;

		uv_base = 0.0f;
		uv_max  = 1.0f; 

        for (i = 0; i < 4; ++i)
        {
            pBuff->Position = D3DXVECTOR3((i==0 || i==3) ? -1.0f : 1.0f,
                                          (i<2)          ? -1.0f : 1.0f,
                                          0.0f);
		    pBuff->Tex      = D3DXVECTOR2((i==0 || i==3) ? uv_base : uv_max , 
                                          (i<2)          ? uv_max : uv_base );

⌨️ 快捷键说明

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