📄 ch13p1_simplefeedback.cpp
字号:
// get the current rendering target (we'll set it back later)
LPDIRECT3DSURFACE8 pOldRenderTarget;
m_pd3dDevice->GetRenderTarget(&pOldRenderTarget);
// get surface interfaces for our textures, so we can set them as rendering
// surfaces later.
LPDIRECT3DSURFACE8 pScratchSurf, pOrigSurf;
m_pScratchTexture->GetSurfaceLevel(0, &pScratchSurf);
m_pOrigTexture->GetSurfaceLevel(0, &pOrigSurf);
// set scratch surface active and clear it.
// SetRenderTarget will also set our viewport so that it completely fills
// pScratchSurf.
m_pd3dDevice->SetRenderTarget(pScratchSurf, NULL);
m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x000000, 1.0f, 0L );
// set up texture stage states, turn off z buffering (we don't need it!)
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
// render transformed image onto scratch surface
{
// set up orthogonal projection matrix, so that one texel = one pixel in the final
// image, with no perspective correction.
D3DXMATRIX mat;
D3DXMatrixOrthoLH(&mat, (float)m_iTextureWidth, (float)m_iTextureHeight, 0.0, 100.0);
m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mat );
// set up world matrix so that it rotates the quad slightly.
D3DXMATRIX scalemat,destmat,rotmat;
D3DXMatrixIdentity( &mat );
D3DXMatrixRotationZ(&mat, D3DXToRadian(m_fFeedbackRotation));
// scaling: dividing by 2 will make the texture completely fill the rendering surface
// (because our ortho projection made one texel=one pixel, and the quad's local origin is
// in its exact center.)
// So, dividing by 1.8 will enlarge the image slightly, creating the "tunneling" effect
// of this feedback system.
D3DXMatrixMultiply(&destmat, &mat,
D3DXMatrixScaling(&scalemat, (float)m_iTextureWidth/1.8, (float)m_iTextureHeight/1.8, 1.0));
m_pd3dDevice->SetTransform( D3DTS_WORLD, &destmat );
// set the original texture active
m_pd3dDevice->SetTexture(0, m_pOrigTexture);
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
// begin rendering the scene
if (FAILED(m_pd3dDevice->BeginScene())) return;
m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) );
m_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
// this "blits" the slightly rotated and scaled quad.
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
// randomly put original image on texture to keep feedback going
m_pd3dDevice->SetTexture(0, m_pImageTexture);
//D3DXMatrixScaling(&scalemat, (float)m_iTextureWidth/m_fFeedbackScale, (float)m_iTextureHeight/m_fFeedbackScale, 1.0);
D3DXMatrixScaling(&scalemat, (float)m_iTextureWidth/5, (float)m_iTextureHeight/5, 1.0);
D3DXMatrixMultiply(&destmat, &scalemat, D3DXMatrixRotationZ(&rotmat, D3DXToRadian(m_fImageRotation)));
m_pd3dDevice->SetTransform( D3DTS_WORLD, &destmat );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
// end scene
m_pd3dDevice->EndScene();
}
// at this point, our scratch surface contains a rotated/scaled version of our original image.
// now we need to blend the scratch surface back onto the original image.
// set original surface active (DON'T clear it)
m_pd3dDevice->SetRenderTarget(pOrigSurf, NULL);
// turn alpha blitting on
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
// blend scratch surface back onto original surface.
// This is the feedback portion of the feedback effect.
{
if (FAILED(m_pd3dDevice->BeginScene())) return;
// this world matrix, combined with orthogonal projection, causes the texture to completely
// and exactly fill the rendering surface.
D3DXMATRIX matWorld;
D3DXMatrixScaling(&matWorld, (float)m_iTextureWidth/2.0f, (float)m_iTextureHeight/2.0f, 1.0);
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
m_pd3dDevice->SetTexture(0, m_pScratchTexture);
m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) );
m_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
m_pd3dDevice->EndScene();
}
// release the surface of the scratch texture.
pOrigSurf->Release();
pScratchSurf->Release();
// set the rendering target back to the old target.
m_pd3dDevice->SetRenderTarget(pOldRenderTarget, pDepthSurf);
m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
pOldRenderTarget->Release();
// release the depth surface interface.
pDepthSurf->Release();
}
//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc: Initialize scene objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::RestoreDeviceObjects()
{
HRESULT hr;
m_pFont->RestoreDeviceObjects();
m_pFontSmall->RestoreDeviceObjects();
// Setup render states
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
// Create vertex buffer
{
CUSTOMVERTEX* pVertices;
if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 6*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_MANAGED, &m_pVB ) ) )
return hr;
if( FAILED( hr = m_pVB->Lock( 0, m_dwNumVertices*sizeof(CUSTOMVERTEX), (BYTE**)&pVertices, 0 ) ) )
return hr;
// first triangle
pVertices[0].position = D3DXVECTOR3(-1.0f, 1.0f, 0.0f);
pVertices[0].color = D3DCOLOR_ARGB(200,0,0,0);
pVertices[0].tu = 0.0f;
pVertices[0].tv = 0.0f;
pVertices[1].position = D3DXVECTOR3(1.0f, 1.0f, 0.0f);
pVertices[1].color = D3DCOLOR_ARGB(200,0,0,0);
pVertices[1].tu = 1.0f;
pVertices[1].tv = 0.0f;
pVertices[2].position = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
pVertices[2].color = D3DCOLOR_ARGB(200,0,0,0);
pVertices[2].tu = 1.0f;
pVertices[2].tv = 1.0f;
// second triangle
pVertices[3].position = D3DXVECTOR3(-1.0f, 1.0f, 0.0f);
pVertices[3].color = D3DCOLOR_ARGB(200,0,0,0);
pVertices[3].tu = 0.0f;
pVertices[3].tv = 0.0f;
pVertices[4].position = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
pVertices[4].color = D3DCOLOR_ARGB(200,0,0,0);
pVertices[4].tu = 1.0f;
pVertices[4].tv = 1.0f;
pVertices[5].position = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
pVertices[5].color = D3DCOLOR_ARGB(200,0,0,0);
pVertices[5].tu = 0.0f;
pVertices[5].tv = 1.0f;
if( FAILED( hr = m_pVB->Unlock() ) )
return hr;
}
// create original image texture. This must be created as a render target.
if (FAILED(hr = D3DXCreateTextureFromFileEx(m_pd3dDevice, "Ch13p1_trippy256.bmp",
0, 0, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
0, NULL, NULL, &m_pImageTexture))) {
return(hr);
}
D3DSURFACE_DESC desc;
m_pImageTexture->GetLevelDesc(0, &desc);
m_iTextureWidth = desc.Width;
m_iTextureHeight = desc.Height;
// create scratch texture that's the same size as the image texture.
// this also must be created as a render target.
if (FAILED(hr = D3DXCreateTexture(m_pd3dDevice, m_iTextureWidth, m_iTextureHeight, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pOrigTexture))) {
return(hr);
}
if (FAILED(hr = D3DXCreateTexture(m_pd3dDevice, m_iTextureWidth, m_iTextureHeight, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pScratchTexture))) {
return(hr);
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InvalidateDeviceObjects()
{
m_pFont->InvalidateDeviceObjects();
m_pFontSmall->InvalidateDeviceObjects();
SAFE_RELEASE( m_pVB );
SAFE_RELEASE( m_pScratchVB );
SAFE_RELEASE( m_pOrigTexture );
SAFE_RELEASE( m_pImageTexture );
SAFE_RELEASE( m_pScratchTexture );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Called when the app is exiting, or the device is being changed,
// this function deletes any device dependent objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::DeleteDeviceObjects()
{
m_pFont->DeleteDeviceObjects();
m_pFontSmall->DeleteDeviceObjects();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FinalCleanup()
// Desc: Called before the app exits, this function gives the app the chance
// to cleanup after itself.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FinalCleanup()
{
SAFE_DELETE( m_pFont );
SAFE_DELETE( m_pFontSmall );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ConfirmDevice()
// Desc: Called during device intialization, this code checks the device
// for some minimum set of capabilities
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
D3DFORMAT Format )
{
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: Message proc function to handle key and menu input
//-----------------------------------------------------------------------------
LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam )
{
// Pass remaining messages to default handler
return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -