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

📄 shader_particlesystem.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    m_pD3DDev->SetVertexShaderConstant(VSC_RND_NUM_VECTORS, &rndNumVectors, 1);

    float       x, y, z, w;
    float const kRandMax = static_cast<float>(RAND_MAX);
    float const kIAOver2 = 16807.0f/2.0f;

    struct _timeb   currentTime;
    _ftime(&currentTime);
    srand( (unsigned)currentTime.time );
    
    for (int i = 0; i < kNumRndVectors; ++i)
    {
        x = kIAOver2 * static_cast<float>(rand())/kRandMax;
        y = kIAOver2 * static_cast<float>(rand())/kRandMax;
        z = kIAOver2 * static_cast<float>(rand())/kRandMax;
        w = kIAOver2 * static_cast<float>(rand())/kRandMax;
        D3DXVECTOR4 rndVector(x, y, z, w);
        m_pD3DDev->SetVertexShaderConstant(VSC_RND_START + i, &rndVector, 1);
    }

    // particle start, direction, and perpendicular direction
	D3DXVECTOR4 startPosition(-0.0f, 0.0f, 0.0f, 1.0f);
    m_pD3DDev->SetVertexShaderConstant(VSC_START_POSITION, &startPosition, 1);

    D3DXVECTOR3        direction(-0.2f, 1.0f, 0.0f);
    D3DXVec3Normalize(&direction, &direction);
	m_pD3DDev->SetVertexShaderConstant(VSC_DIRECTION,      &direction, 1);

    D3DXVECTOR3        dirPerp1(0.0f, 0.0f, 1.0f);
    D3DXVec3Cross(    &dirPerp1, &dirPerp1, &direction);
    D3DXVec3Normalize(&dirPerp1, &dirPerp1);
    m_pD3DDev->SetVertexShaderConstant(VSC_DIR_PERPENDICULAR1, &dirPerp1, 1);

    D3DXVECTOR3        dirPerp2(0.0f, 0.0f, 0.0f);
    D3DXVec3Cross(    &dirPerp2, &dirPerp1, &direction);
    D3DXVec3Normalize(&dirPerp2, &dirPerp2);
    m_pD3DDev->SetVertexShaderConstant(VSC_DIR_PERPENDICULAR2, &dirPerp2, 1);

    D3DXVECTOR4 halfGravity(0.0f, -0.9f, 0.0f, 0.0f);
	m_pD3DDev->SetVertexShaderConstant(VSC_HALF_GRAVITY,   &halfGravity, 1);
}

HRESULT CShaderPSystem::Free()
{
	SAFE_RELEASE(m_pParticleVB);
	SAFE_RELEASE(m_pFloorVB);

	SAFE_RELEASE(m_pFloorTexture);
	SAFE_RELEASE(m_pParticleTexture);

	if (m_pD3DDev)
	{
		m_pD3DDev->DeleteVertexShader(mFloorShader);
		m_pD3DDev->DeleteVertexShader(mParticleShader);
		SAFE_RELEASE(m_pD3DDev);
	}
    SAFE_DELETE(mpMouseUI);

	return S_OK;
}

HRESULT CShaderPSystem::Start()
{
	return S_OK;
}

HRESULT CShaderPSystem::Tick(EBTimer* pTimer)
{
    HRESULT hr = S_OK;
   
	D3DXMATRIX matWorld;
	D3DXMATRIX matView;
	D3DXMATRIX matProj;
	D3DXMATRIX matWorldViewProj;

    DWORD   const kSmokeColor = D3DCOLOR_RGBA(125, 105, 95, 0);
    DWORD   const kSkyColor   = D3DCOLOR_RGBA( 70,  80, 65, 0);

    // clear the backbuffer
    hr = m_pD3DDev->SetRenderState(D3DRS_FILLMODE, (mbWireFrame) ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
	hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, kSkyColor, 1.0, 0);

    // set up the camera/projection

	// Setup the world and projection matrices
	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixPerspectiveFovLH(&matProj, D3DXToRadian(60.0f), 1.0f, 0.01f, 200.0f);

    // update the view matrix from the keyboard
    SetViewFromKeyboardInput(pTimer, matView);
    
	// Setup the composite matrix to get vertices to projection space
	D3DXMatrixMultiply( &matWorldViewProj, &matWorld, &matView);
	D3DXMatrixMultiply( &matWorldViewProj, &matWorldViewProj, &matProj);	
	D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);

	// write the matrix to the vertex shader constants
    m_pD3DDev->SetVertexShaderConstant(VSC_WORLDVIEW_PROJ_0, &matWorldViewProj(0, 0), 4);

         
    // update current time
    struct _timeb   now;
    _ftime(&now);

    float kDifference(static_cast<float>(now.time - mStartTime.time));
    kDifference += static_cast<float>(0.001f * (now.millitm - mStartTime.millitm));
    kDifference += 10000.0f;    // fudge it to randoomize particles more

    D3DXVECTOR4 currentTime(kDifference, kDifference, kDifference, kDifference);

    // but only if we are not freezing the current frame
    if (! mbFreezeFrame)
        m_pD3DDev->SetVertexShaderConstant(VSC_CURRENT_TIME,   &currentTime, 1);

    // done writing constants, just draw the VBs now
    // draw the floor first!    
    
    // all color comes from texture, no alpha at all
    m_pD3DDev->SetRenderState(D3DRS_FOGENABLE, false );
    m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
    m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1);
    m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, true);   

    hr = m_pD3DDev->SetStreamSource(0, m_pFloorVB, sizeof(FloorVertex));
	hr = m_pD3DDev->SetVertexShader( mFloorShader );
    hr = m_pD3DDev->SetTexture(0, m_pFloorTexture);
	
    hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
	if (FAILED(hr))
		return hr;

    // now the particles 
    // all color comes from diffuse of vertex
    m_pD3DDev->SetRenderState(D3DRS_FOGENABLE, true );
    m_pD3DDev->SetRenderState(D3DRS_FOGCOLOR,  kSmokeColor);
    m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_SELECTARG2);
    // particles have alpha, but are not (cannot be) depth-sorted.  Thus, disable z-writing 
    // to avoid funny alpha-occlusion
    m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, false);   
    
    hr = m_pD3DDev->SetStreamSource(0, m_pParticleVB, sizeof(PSystemVertex));
	hr = m_pD3DDev->SetVertexShader(mParticleShader);
    hr = m_pD3DDev->SetTexture(0, m_pParticleTexture);
    
    assert(10 < kNumParticles);
    hr = m_pD3DDev->DrawPrimitive(D3DPT_POINTLIST, 0, mNumParticles);

	return hr;
}

void CShaderPSystem::Keyboard(DWORD vKey, UINT nFlags, bool bDown)
{
	eEBKeyAction Action = TranslateEffectKey(vKey, nFlags, bDown);
	
    switch ( Action )
    {
		case EB_HELP:
		{
			::MessageBoxEx( NULL, " Help : F1 - Help \n\n Home - Reset To Defaults \n\n W - Wireframe Toggle \n\n Space/Pause Toggle Pausing Animation\n\n +/- - Increase/Reduce Number of Particles\n\n Left Button & Mouse - Rotate Camera\n\n Shift Left Button & Mouse - Pan Camera \n\n Ctrl Left Button & Mouse - Move Camera In & Out\n\n",
				   "Help", MB_ICONINFORMATION | MB_TASKMODAL, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) );
		}
		break;

		case EB_WIREFRAME:
        {
            mbWireFrame = !mbWireFrame;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
        }
		break;

        case EB_PAUSE:
        {
            mbFreezeFrame = !mbFreezeFrame;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
        }
        break;

		case EB_RESET:
        {
            mbFreezeFrame = false;
            mNumParticles = kStartParticles;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
            mpMouseUI->Reset();
        }
		break;

        case EB_ADD:
            mNumParticles += max(5, mNumParticles/10);
            if (mNumParticles > kNumParticles)
                mNumParticles = kNumParticles;
            break;

        case EB_SUBTRACT:
            mNumParticles -= max(5, mNumParticles/10);
            if (mNumParticles < 10)
                mNumParticles = 10;
            break;

        default:
            m_bKey[vKey] = bDown;
    }
}

void CShaderPSystem::SetViewFromKeyboardInput(EBTimer* pTimer, D3DXMATRIX &matView)
{
    float   const   kSpeed              = pTimer->GetSecsPerFrame() * 10.0f;
    float   const   moveSpeed           = kSpeed * 2.0f;

    D3DXVECTOR3 const   yVector(0.0f, 1.0f, 0.0f);
    D3DXVECTOR3         lookDir(0.0f, 0.0f, 1.0f);    
    D3DXVECTOR4         position;
    D3DXMATRIX          matLookRotations;

    D3DXMatrixTranspose(&matLookRotations, &(mpMouseUI->GetRotationMatrix()));
    D3DXVec3TransformNormal(&lookDir, &lookDir, &matLookRotations);

    float       const   h = D3DXVec3Dot(&yVector, &lookDir);
    D3DXVECTOR3         xzProjectedLookDirection(lookDir - h*yVector);

    D3DXVec3Normalize(&xzProjectedLookDirection, &xzProjectedLookDirection);
    
    D3DXVECTOR3         rightVector;         
    D3DXVec3Cross(&rightVector, &yVector, &xzProjectedLookDirection);

    if(m_bKey[VK_UP]    || m_bKey[VK_NUMPAD8])
        mpMouseUI->Translate(  moveSpeed*xzProjectedLookDirection);
	if(m_bKey[VK_DOWN]  || m_bKey[VK_NUMPAD2])
        mpMouseUI->Translate(- moveSpeed*xzProjectedLookDirection);
	if(m_bKey[VK_LEFT]  || m_bKey[VK_NUMPAD4])
        mpMouseUI->Translate(- 0.5f*moveSpeed*rightVector);
	if(m_bKey[VK_RIGHT] || m_bKey[VK_NUMPAD6])              
        mpMouseUI->Translate(  0.5f*moveSpeed*rightVector);
	if(m_bKey[VK_PRIOR])
        mpMouseUI->Translate(  0.25f*moveSpeed*yVector);
	if(m_bKey[VK_NEXT])
        mpMouseUI->Translate(- 0.25f*moveSpeed*yVector);
    

    D3DXVec3Transform(&position, &D3DXVECTOR3(0.0f, 1.0f, -5.0f), &mpMouseUI->GetTranslationMatrix());

    D3DXVECTOR3 const   camPosition = D3DXVECTOR3(position.x, max(0.1f, position.y), position.z);
    D3DXVECTOR3 const   vLookatPt   = camPosition + lookDir;         

    D3DXMatrixLookAtLH(&matView, &camPosition, &vLookatPt, &yVector);
}

HRESULT CShaderPSystem::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 (only need 1...)
    if(pCaps->MaxSimultaneousTextures < 1)
	{
		m_strLastError = "Device does not support 1 simultaneous textures!";
		return E_FAIL;
	}

    // only need very few, simple register combiners...
	if(pCaps->MaxTextureBlendStages < 2)
	{
		m_strLastError = "Device does not support 2 register combiners!";
		return E_FAIL;
	}

    // need mipmapping 
	if ((pCaps->TextureCaps & D3DPTEXTURECAPS_MIPMAP) == 0)
	{
		m_strLastError = "Device does not support mip-mapping!";
		return E_FAIL;
	}
    // and trilinear filtering between mipmaps
	if ((pCaps->TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR) == 0)
	{
		m_strLastError = "Device does not support trilinear mip-mapping!";
		return E_FAIL;
	}

    // point primitives?!
	if (pCaps->MaxPointSize == 1.0f)
	{
		m_strLastError = "Device does not support point-sprites!";
		return E_FAIL;
	}

	return S_OK;
}

void CShaderPSystem::MouseMove(HWND hWnd, int x, int y)
{
    mpMouseUI->OnMouseMove(x, y);
}

void CShaderPSystem::MouseButton(HWND hWnd, eButtonID button, bool bDown, int x, int y)
{
	if(button == MOUSE_LEFTBUTTON)
	{
		if(bDown)
			mpMouseUI->OnLButtonDown(x, y);
		else
			mpMouseUI->OnLButtonUp(x, y);
	}
}

⌨️ 快捷键说明

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