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

📄 shader_motionblur.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    // Setup render states
    m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
    m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
	m_pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2);
	m_pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

	m_pD3DDev->SetVertexShaderConstant(CV_CONSTANTS, D3DXVECTOR4(0.0f,1.0f,0.0f,0.0f), 1);
	
    // Projection set up
    D3DXMATRIX        matProj;
	D3DXMatrixPerspectiveFovLH(&matProj, D3DXToRadian(60.0f), 1.0f, 1.0f, 1000.0f);
	m_pNVDevice->SetProjectionTransform(&matProj);
	return S_OK;
}
#pragma optimize ("", on)

HRESULT CShaderMotionBlur::Free()
{
    for (int i = 6; --i >= 0; )
	{
	    SAFE_RELEASE( m_pBlurredObjectIB[i] );
	}
	SAFE_RELEASE(m_pBlurredObjectVB);

	SAFE_DELETE(m_pFloorMesh);
	SAFE_DELETE(m_pBlurredObjectMesh);
    SAFE_RELEASE(m_pBlurredObjectMap);
	SAFE_DELETE(m_pNVDevice);

	if (m_pD3DDev)
	{
		m_pD3DDev->DeleteVertexShader(m_dwMotionBlurShader);
		SAFE_RELEASE(m_pD3DDev);
	}

	return S_OK;
}

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

HRESULT CShaderMotionBlur::SetTransform(bool  bWithBlur)
{
	D3DXMATRIX matWorld, matView, matProj;
	D3DXMATRIX matWorldView, matWorldViewIT;
	float      unused;

	matWorld = m_pNVDevice->GetWorldTransform();
	matView  = m_pNVDevice->GetViewTransform();
	matProj  = m_pNVDevice->GetProjectionTransform();

	D3DXMatrixMultiply(&matWorldView,   &matWorld, &matView);
    D3DXMatrixInverse( &matWorldViewIT, &unused, &matWorldView);
	
	// Projection to clip space
	D3DXMatrixTranspose(&matProj, &matProj);
	m_pD3DDev->SetVertexShaderConstant(CV_PROJ_TXF_0, &matProj(0, 0), 4);

    // Projection to view-space
	D3DXMatrixTranspose(&matWorldView, &matWorldView);
    m_pD3DDev->SetVertexShaderConstant(CV_CURR_WORLDVIEW_TXF_0, &matWorldView(0, 0), 3);
    if (bWithBlur)
    {
        m_pD3DDev->SetVertexShaderConstant(CV_PREV_WORLDVIEW_TXF_0, &m_LastWorldTxf(0, 0), 3);
    	m_LastWorldTxf = matWorldView;
    }
    else
    {
    	m_pD3DDev->SetVertexShaderConstant(CV_PREV_WORLDVIEW_TXF_0, &matWorldView(0, 0), 3);
    }

    // projection of normals to view-space
    m_pD3DDev->SetVertexShaderConstant(CV_CURR_WORLDVIEW_IT_0, &matWorldViewIT(0, 0), 3);

    return S_OK;
}


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

    m_pD3DDev->SetRenderState(D3DRS_FILLMODE, (mbWireFrame) ? D3DFILL_WIREFRAME : D3DFILL_SOLID);

    if (m_bPause)
        return hr;

    // Camera setup
	D3DXVECTOR3 const vEyePt    = D3DXVECTOR3( 0.0f,  2.0f, -30.0f);
	D3DXVECTOR3 const vLookatPt = D3DXVECTOR3( 0.0f, -5.0f, 0.0f);
	D3DXVECTOR3 const vUp       = D3DXVECTOR3( 0.0f,  1.0f, 0.0f );

	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
	m_pNVDevice->SetViewTransform(&matView);

	hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, BACKGROUND_COLOR, 1.0, 0);

    // Sea floor
	D3DXMatrixScaling( &matWorld, 1.0f, 1.0f, 1.0f);
	m_pNVDevice->SetWorldTransform(&matWorld);
	SetTransform( false );
	m_pFloorMesh->Render(m_pNVDevice);

    // now lets draw the blurred object
    float const kSpeed = (m_bEnableSpeed2x) ? 15.0f : 7.5f;
	float const fKickFreq = kSpeed * pTimer->GetDuration(); 
	float const fPhase    = kSpeed * pTimer->GetDuration() / 3.0f;


    m_pD3DDev->SetStreamSource(0, m_pBlurredObjectVB, sizeof(MotionBlurVertex));
	m_pD3DDev->SetVertexShader(m_dwMotionBlurShader);

    m_pD3DDev->SetTexture(0, m_pBlurredObjectMap);

    // Move the blurred object in a circle
    D3DXMATRIX      matScale, matTrans1, matRotate1, matRotate2;
    D3DXMATRIX      matBank,  matLocalRotate;

    D3DXMatrixRotationY(   &matLocalRotate, D3DX_PI/2.0f);
    D3DXMatrixRotationX(   &matBank,        D3DX_PI/8.0f);
    D3DXMatrixRotationZ(   &matRotate1, 2*D3DX_PI); 
    D3DXMatrixRotationY(   &matRotate2, fPhase );
    D3DXMatrixScaling(     &matScale, 2.0f, 2.0f, 2.0f );
    D3DXMatrixTranslation( &matTrans1, -12*sinf(fPhase), sinf(fKickFreq), 10-30*cosf(fPhase) );

	D3DXMatrixIdentity(&matWorld);
    D3DXMatrixMultiply( &matWorld, &matTrans1,      &matWorld);
	D3DXMatrixMultiply( &matWorld, &matScale,       &matWorld);
	D3DXMatrixMultiply( &matWorld, &matRotate2,     &matWorld);
	D3DXMatrixMultiply( &matWorld, &matRotate1,     &matWorld);	
    D3DXMatrixMultiply( &matWorld, &matBank,        &matWorld);
    D3DXMatrixMultiply( &matWorld, &matLocalRotate, &matWorld);

    m_pNVDevice->SetWorldTransform(&matWorld);

    // set the proper alpha colors
    // do not really have to write these all the time...
    FLOAT const kBlurAlpha = 0.1f;

    // This is not correct for vertices with actual alpha!
    // we should make sure we have the right alpha-constants in the registers...
    // Would have to modify the Render() routine...
    D3DXVECTOR4 vColorPrevious(1.0f, 1.0f, 1.0f, kBlurAlpha );
	D3DXVECTOR4 vColorCurrent (1.0f, 1.0f, 1.0f, 1.0f );

    m_pD3DDev->SetVertexShaderConstant( CV_PREV_COLOR, &vColorCurrent,  1 );
    m_pD3DDev->SetVertexShaderConstant( CV_CURR_COLOR, &vColorCurrent,  1 );

    float blurFraction(1.0f);

    switch (meBlurLengthOption)
    {
        case HALFxBLURLENGTH:
            blurFraction = 0.5f;
            break;
        case ONEHALFxBLURLENGTH:
            blurFraction = 1.5f;
            break;
        default:
            break;
    }

    D3DXVECTOR4 vOneOverExtent(m_OneOverExtent, 1.0f, blurFraction, 1.0f);
    m_pD3DDev->SetVertexShaderConstant( CV_OBJECT_EXTEND, &vOneOverExtent, 1 );

    // draw object once w/o blur
    SetTransform( false );     

    // no need to write z the first time: we will write when drawing the second time!
    m_pD3DDev->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );

    float   fBias = (m_bEnableMotionBlur ) ? kSpeed/10.0f : 0.0f;
    m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));

    m_pBlurredObjectMesh->Render(m_pNVDevice);

    // now draw it again with blur and alpha sorted
    m_pD3DDev->SetVertexShaderConstant( CV_PREV_COLOR, &vColorPrevious,   1 );
	SetTransform( m_bEnableMotionBlur );


    // invert model-matrix and transform cam to model-space
    D3DXMATRIX  MatWorldInverse;    
    FLOAT       det;
    D3DXMatrixInverse(&MatWorldInverse, &det, &matWorld); 

    D3DXVECTOR4     vLookAtModel, vEyeModel;

    D3DXVec3Transform(&vLookAtModel, &vLookatPt, &MatWorldInverse);
    D3DXVec3Transform(&vEyeModel,    &vEyePt,    &MatWorldInverse);

    D3DXVECTOR3 const vFromCam = vLookAtModel - vEyeModel;
    
    // find the biggest component 
    if (   (abs(vFromCam.x) > abs(vFromCam.y))
        && (abs(vFromCam.x) > abs(vFromCam.z)) ) 
    {
        // x is largest
        m_pD3DDev->SetIndices(m_pBlurredObjectIB[(vFromCam.x < 0) ? 0 : 1], 0);
    }
    else if (   (abs(vFromCam.y) > abs(vFromCam.x)) 
             && (abs(vFromCam.y) > abs(vFromCam.z)) )
    {
        // y is largest 
        m_pD3DDev->SetIndices(m_pBlurredObjectIB[(vFromCam.y < 0) ? 2 : 3], 0);
    }
    else
    {
        // z is largest
        m_pD3DDev->SetIndices(m_pBlurredObjectIB[(vFromCam.z < 0) ? 4 : 5], 0);
    }

    // now lets write z 
    m_pD3DDev->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );

    // render the blurred object!
    hr = m_pD3DDev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, m_numVertices, 0, m_numIndices/3);

    // reset MIPMAP bias
    fBias = 0.0f;
    m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPMAPLODBIAS, *((LPDWORD) (&fBias)));

    Sleep(50);      // artificially kill frame rate to make blur apparent!

	return hr;
}

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

    // only need very few, simple register combiners...
	if(pCaps->MaxTextureBlendStages < 2)
	{
		m_strLastError = "Device does not support 8 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;
	}
     
	return S_OK;
}

void CShaderMotionBlur::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
    unsigned int option = static_cast<unsigned int>(meBlurLengthOption); 
	eEBKeyAction Action = TranslateEffectKey(dwKey, 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 Pause/Space - Toggle pausing the animation \n\n +/- - Lengthen/Shorten Blur Length",
				   "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:
        {
            m_bPause = !m_bPause;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
        }
        break;

		case EB_RESET:
        {
            meBlurLengthOption = ONExBLURLENGTH;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
        }
		break;

        case EB_ADD:
            if (option < NUM_BLURLENGTHS-1)
                ++option;
            meBlurLengthOption = static_cast<eBlurLengths>(option);
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
            break;

        case EB_SUBTRACT:
            if (option > FIRST_BLURLENGTH)
                --option;
            meBlurLengthOption = static_cast<eBlurLengths>(option);
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
            break;

        default:
            break;
    }
}

⌨️ 快捷键说明

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