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

📄 shader_particlesystem.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************

  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.
        
        
******************************************************************************/

#include "eb_effect.h"
#include "nvinc.h"
#include "shader_ParticleSystem.h"
#include "ParticleSystem.h"

using namespace std;

DECLARE_EFFECT_MAIN()

extern "C"
{

__declspec(dllexport) unsigned int GetNumEffects() { return 1; }

__declspec(dllexport) EBEffect* CreateEffect(unsigned int EffectNum)
{
	return new CShaderPSystem();
}

}

CShaderPSystem::CShaderPSystem()
	: m_pParticleVB(NULL)
	, m_pFloorVB(NULL)
    , m_pFloorTexture(NULL)
    , m_pParticleTexture(NULL)
    , mNumParticles(kStartParticles)
    , mbFreezeFrame(false)
    , mbWireFrame(false)
    , mpMouseUI(NULL)

{
	m_strEffectName = "Particle System";
	m_strEffectLocation = "Vertex Shaders\\Physics";
	m_strEffectPixelShader = "";
	m_strEffectVertexShader = GetFilePath("particleSystem.nvv");
}

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

void CShaderPSystem::UpdateProperties()
{
	EBEffect::UpdateProperties();
    AddProperty(new EBProperty("Wireframe", OBJECT_MEMBER(mbWireFrame), EBTYPE_BOOL_PROP));
    AddProperty(new EBProperty("Pause", OBJECT_MEMBER(mbFreezeFrame), EBTYPE_BOOL_PROP));

	m_pVertexShaderEnum->AddEnumerant(new EBEnumValue(m_pVertexShaderEnum, "Physics in Vertex Shader", GetFilePath("particleSystem.nvv"), EBTYPE_STRING_PROP));
}

HRESULT CShaderPSystem::Initialize(IDirect3DDevice8* pDev)
{
    ZeroMemory(&m_bKey[0], sizeof(bool) * kMaxVKey);

	HRESULT hr;

	m_pD3DDev = pDev;
	pDev->AddRef();

    //initialize mouse UI
	D3DVIEWPORT8    viewport;
	RECT            rect;

    m_pD3DDev->GetViewport(&viewport);
	rect.left   = rect.top = 0;
	rect.bottom = viewport.Height;
	rect.right  = viewport.Width;
	mpMouseUI   = new MouseUI(rect, true);
    mpMouseUI->SetRotationalSensitivityFactor(1.0f);

    // create the floor quadrangle
    hr = m_pD3DDev->CreateVertexBuffer( 4 * sizeof(FloorVertex), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_pFloorVB);
	if (FAILED(hr))
		return hr;

	vector<DWORD> floorDecl;
	floorDecl.push_back(D3DVSD_STREAM(0));
	floorDecl.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT4));
	floorDecl.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT2));
	floorDecl.push_back(D3DVSD_END());
	hr = LoadAndCreateShader(GetFilePath("particleFloor.vso"), &floorDecl[0], 0, SHADERTYPE_VERTEX, &mFloorShader);
	if (FAILED(hr))
		return hr;
    
    FloorVertex* pFloor;

    assert(m_pFloorVB != NULL);
	hr = m_pFloorVB->Lock(0, 4 * sizeof(FloorVertex),(BYTE**)&pFloor, 0);
	if (FAILED(hr))
	{
		m_strLastError = "Couldn't lock Floor buffer!";
		return hr;
	}
    float const  kFloorDimension = 101.0f;

    pFloor->position = D3DXVECTOR4(-kFloorDimension, 0.0f, -kFloorDimension, 1.0f);
    pFloor->texture  = D3DXVECTOR2(0.0f, 0.0f);
    ++pFloor;
    pFloor->position = D3DXVECTOR4( kFloorDimension, 0.0f, -kFloorDimension, 1.0f);
    pFloor->texture  = D3DXVECTOR2(0.0f, kFloorDimension);
    ++pFloor;
    pFloor->position = D3DXVECTOR4(-kFloorDimension, 0.0f, kFloorDimension, 1.0f);
    pFloor->texture  = D3DXVECTOR2(kFloorDimension, 0.0f);
    ++pFloor;
    pFloor->position = D3DXVECTOR4( kFloorDimension, 0.0f, kFloorDimension, 1.0f);
    pFloor->texture  = D3DXVECTOR2(kFloorDimension, kFloorDimension);
    ++pFloor;

    m_pFloorVB->Unlock();

	hr = D3DXCreateTextureFromFileEx(m_pD3DDev, 
		GetFilePath("wall.dds").c_str(),
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		0,
		0,
		D3DFMT_UNKNOWN,
		D3DPOOL_MANAGED,
		D3DX_FILTER_LINEAR,
		D3DX_FILTER_LINEAR,
		0,
		NULL,
		NULL,
		&m_pFloorTexture);
	if (FAILED(hr))
	{
		m_strLastError = "Could not load texture wall.dds";
		return hr;
	}


    // create the particles
    hr = m_pD3DDev->CreateVertexBuffer( kNumParticles * sizeof(PSystemVertex), D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_pParticleVB);
	if (FAILED(hr))
		return hr;

	vector<DWORD> Declaration;
	Declaration.push_back(D3DVSD_STREAM(0));
	Declaration.push_back(D3DVSD_REG(0, D3DVSDT_FLOAT4));
	Declaration.push_back(D3DVSD_REG(1, D3DVSDT_FLOAT4));
	Declaration.push_back(D3DVSD_REG(2, D3DVSDT_FLOAT3));
	Declaration.push_back(D3DVSD_END());
	hr = LoadAndCreateShader(GetFilePath("particleSystem.vso"), &Declaration[0], 0, SHADERTYPE_VERTEX, &mParticleShader);
	if (FAILED(hr))
		return hr;

	PSystemVertex* pBuff;

    assert(m_pParticleVB != NULL);
	hr = m_pParticleVB->Lock(0, kNumParticles * sizeof(PSystemVertex),(BYTE**)&pBuff, 0);
	if (FAILED(hr))
	{
		m_strLastError = "Couldn't lock buffer!";
		return hr;
	}

    D3DXVECTOR4 timeSeeds;
    D3DXVECTOR4 physics;
    D3DXVECTOR3 color;

    _ftime(&mStartTime);
    srand( (unsigned)mStartTime.time );

    float const     kRandMax  = static_cast<float>(RAND_MAX);
    float const     kIAOver2  = 16807.0f/2.0f;

    // all following times are in seconds
    float   creationTime      =  0.0f;    // used to figure out how far along a particle is in its lifetime
    float   lifeTime          =  4.0f;    // life time of a particle.  A particle becomes invisible at the end of its life time
    float   periodicityOffset =  0.3f;    // a particle is reborn (reused) every (lifeTime+periodicityOffset)
    float   decay             = -1.0f;    // 2^decay = Eps, w/ Eps < 1, but close to 1, ie, -1 < decay < 0;
    float   velocity          =  3.0f;    // initial velocity of particle (direction vector multiplier)
    float   random;

    // generate and copy particle values
    for (int i = kNumParticles; --i >= 0; )
    {
        timeSeeds.x   = creationTime;
        creationTime += 2.0f*lifeTime/static_cast<float>(kNumParticles);

        random = lifeTime + 4.0f * static_cast<float>(rand())/kRandMax;
        timeSeeds.y = 1.0f/random;                
        timeSeeds.z = random + periodicityOffset * static_cast<float>(rand())/kRandMax;
        timeSeeds.w = 1.0f/(timeSeeds.z);
    
        physics.x   = decay;              // could be a random variation 
        physics.y   = 1.0f/(physics.x*logf(2.0f));
        random      = velocity + 2.0f * static_cast<float>(rand())/kRandMax;
        physics.z   = random;           
        physics.w   = kIAOver2 * static_cast<float>(rand())/kRandMax;   // per vertex random-seed (to be added to constant seed)

        random = static_cast<float>(rand())/kRandMax;
        color.x = 0.9f + 0.1f * random;
        random = static_cast<float>(rand())/kRandMax;
        color.y = 0.6f + 0.4f * random;
        random = static_cast<float>(rand())/kRandMax;
        color.z = 0.0f + 0.25f * random;

        pBuff->timeSeeds = timeSeeds;
	    pBuff->physics   = physics;
	    pBuff->color     = color;
	    ++pBuff;
    }
	m_pParticleVB->Unlock();

    // read a texture for the particle
	hr = D3DXCreateTextureFromFileEx(m_pD3DDev, 
		GetFilePath("flare1.dds").c_str(),
		D3DX_DEFAULT,
		D3DX_DEFAULT,
		0,
		0,
		D3DFMT_UNKNOWN,
		D3DPOOL_MANAGED,
		D3DX_FILTER_LINEAR,
		D3DX_FILTER_LINEAR,
		0,
		NULL,
		NULL,
		&m_pParticleTexture);
	if (FAILED(hr))
	{
		m_strLastError = "Could not load texture flare1.dds";
		return hr;
	}

    m_pD3DDev->SetTexture(0, NULL);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
    m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
    m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );


    m_pD3DDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
	m_pD3DDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);

	m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

    // going to set real fog color in Tick()
    m_pD3DDev->SetRenderState( D3DRS_FOGCOLOR,  D3DCOLOR_RGBA(0, 0, 0, 0));
	m_pD3DDev->SetRenderState( D3DRS_FOGENABLE,      TRUE );
    m_pD3DDev->SetRenderState( D3DRS_FOGTABLEMODE,   D3DFOG_NONE );
    m_pD3DDev->SetRenderState( D3DRS_FOGVERTEXMODE,  D3DFOG_NONE );
    m_pD3DDev->SetRenderState( D3DRS_RANGEFOGENABLE, FALSE );
    
    m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, true);

    // add alpha's straight to achieve a "burn-out" effect
    m_pD3DDev->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
    m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); 

    m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, true);

    // we actually override point-size in the vertex shader
    float const kMinPointSize =  0.1f;
    float const kMaxPointSize = 25.0f;
    float const kPointSize    =  4.0f;

    m_pD3DDev->SetRenderState(D3DRS_POINTSIZE_MIN, *reinterpret_cast<DWORD const *>(&kMinPointSize) ); 
    m_pD3DDev->SetRenderState(D3DRS_POINTSIZE_MAX, *reinterpret_cast<DWORD const *>(&kMaxPointSize) );
    m_pD3DDev->SetRenderState(D3DRS_POINTSIZE,     *reinterpret_cast<DWORD const *>(&kPointSize) );

    m_pD3DDev->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
	m_pD3DDev->SetRenderState(D3DRS_POINTSCALEENABLE,  false); 

    // write the non-changing vertex shader constants
    WriteVertexShaderConstants();

    // initialize the camera controls
    mpMouseUI->Reset();

	return S_OK;
}

void CShaderPSystem::WriteVertexShaderConstants() const
{
    // All of the following are write-once!

    D3DXVECTOR4     constants(0.0f, 2.0f, D3DX_PI, 1.0f/3.0f);
	m_pD3DDev->SetVertexShaderConstant(VSC_CONSTANTS,      &constants, 1);

    D3DXVECTOR4     constants2(1.0f/2.0f, 0.25f, 80.0f, 1.0f / (2.0f * D3DX_PI));
	m_pD3DDev->SetVertexShaderConstant(VSC_CONSTANTS2,     &constants2, 1);

    D3DXVECTOR4     cosine(1.0f, -1.0f / 2.0f, 1.0f / 24.0f, -1.0f / 720.0f);
    m_pD3DDev->SetVertexShaderConstant(VSC_COSINE,         &cosine, 1);

    D3DXVECTOR4     sine(1.0f, -1.0f / 6.0f, 1.0f / 120.0f, -1.0f / 5040.0f);
    m_pD3DDev->SetVertexShaderConstant(VSC_SINE,           &sine, 1);


    D3DXVECTOR4     rndVariance(1.0f, 1.0f, 2.0f, 0.3f);
    m_pD3DDev->SetVertexShaderConstant(VSC_RND_VARIANCE, &rndVariance, 1);

    float const     kNumRnds = static_cast<float>(kNumRndVectors);
    D3DXVECTOR4     rndNumVectors(kNumRnds, 1.0f/kNumRnds, 0.0f, 0.0f);

⌨️ 快捷键说明

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