📄 ca_fire.cpp
字号:
case 1:
m_pTexSrc = mpTextureFiltered[1];
m_pIntermediateTarg = mpFilterTarget[0];
m_pIntermediateSrc = mpTextureFiltered[0];
m_pTexFinalTarg = mpFilterTarget[1];
m_pTexFinalSrc = mpTextureFiltered[1];
tmp = m_nTarget4;
m_nTarget4 = m_nTarget3;
m_nTarget3 = tmp;
break;
case 2:
m_pTexSrc = mpTextureFiltered[1];
m_pIntermediateTarg = mpFilterTarget[0];
m_pIntermediateSrc = mpTextureFiltered[0];
m_pTexFinalTarg = mpFilterTarget[1];
m_pTexFinalSrc = mpTextureFiltered[1];
tmp = m_nTarget4;
m_nTarget4 = m_nTarget3;
m_nTarget3 = tmp;
break;
}
}
if( m_bAnimate == true )
{
// Update the textures for one step of the
// game or cellular automata
DoSingleTimeStep_3Pass();
}
else if( m_bSingleStep == true )
{
DoSingleTimeStep_3Pass();
m_bSingleStep = false;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
else
{
// slow down the rendering and give any other apps a chance
Sleep(70);
}
if( m_bSlow && (m_nSlowDelay > 0) )
{
Sleep(m_nSlowDelay);
}
IDirect3DTexture8 * pSrcTex;
static int nSkip = 0;
if( nSkip >= m_nSkipInterval )
{
nSkip = 0;
// Switch back to normal rendering to display the results of
// the rendering to texture
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );
hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
ASSERT_IF_FAILED( hr );
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0,0,0 ), 1.0, 0);
ASSERT_IF_FAILED(hr);
// turn off pixel shading
SetPixelShader(0);
if( m_bWireframe )
{
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME );
// chances are the texture will be all dark, so render in solid color
m_pD3DDev->SetRenderState( D3DRS_TEXTUREFACTOR, 0xFFFFFFFF );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TFACTOR );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
m_pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
}
else
{
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
m_pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
}
switch( m_eRenderMode )
{
case FULLSCREEN_FINALOUT :
// Draw quad over full display
D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// reset offsets to 0 (ie no offsets)
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, m_pOutputSrc );
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
break;
case FULLSCREEN_RESULT :
// Draw quad over full display
D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// reset offsets to 0 (ie no offsets)
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, m_pTexSrc );
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
break;
case FULLSCREEN_NEIGHBOR_CALC:
// Draw quad over full display
D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// reset offsets to 0 (ie no offsets)
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, m_pIntermediateSrc );
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
break;
case ALL_TOGETHER :
// draw quad in upper left corner: original texture
D3DXMatrixTranslation(&matWorld, -1.0f, 1.0f, 0.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// reset offsets to 0 (ie no offsets)
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, m_pInitialStateTexture->GetTexture());
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
// draw quads in the other corners, use generated textures
for (int j = 0; j < 3; ++j)
{
D3DXMatrixTranslation(&matWorld, (j == 2) ? -1.0f : 1.0f,
(j == 0) ? 1.0f : -1.0,
0.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
pSrcTex = mpTextureFiltered[j];
if( m_bFarther )
{
if( j==1 )
pSrcTex = mpTextureFiltered[m_nTarget3];
else if( j==2 )
pSrcTex = mpTextureFiltered[m_nTarget4];
}
else
{
if( j==1 )
pSrcTex = mpTextureFiltered[2];
else if( j==2 )
pSrcTex = mpTextureFiltered[3];
}
if( pSrcTex != 0 )
{
m_pD3DDev->SetTexture(0, pSrcTex );
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
}
}
break;
}; // switch for display config
}
else
{
// skip rendering this frame
// Set normal render target in case the app is doing more rendering
// to the window
hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
nSkip++;
}
return( hr );
}
HRESULT CA_Fire::SetStep_Average_4_Nearest( IDirect3DSurface8 * pTarget,
IDirect3DTexture8 * pSrcTex )
{
HRESULT hr;
assert( pTarget != NULL );
assert( pSrcTex != NULL );
hr = m_pD3DDev->SetRenderTarget( pTarget, NULL );
ASSERT_IF_FAILED(hr);
// Render 1st using offset set 1 - for nearest neighbor pixels
const D3DXVECTOR4 offset( 1.0f, 0.0f, 0.0f, 0.0f );
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, pSrcTex );
m_pD3DDev->SetTexture(1, pSrcTex );
m_pD3DDev->SetTexture(2, pSrcTex );
m_pD3DDev->SetTexture(3, pSrcTex );
return hr;
}
HRESULT CA_Fire::SetStep_Average_4_Diagonal( IDirect3DSurface8 * pTarget,
IDirect3DTexture8 * pSrcTex )
{
HRESULT hr;
assert( pTarget != NULL );
assert( pSrcTex != NULL );
hr = m_pD3DDev->SetRenderTarget( pTarget, NULL );
ASSERT_IF_FAILED(hr);
// Render 1st using offset set 1 - for nearest neighbor pixels
const D3DXVECTOR4 offset( 2.0f, 0.0f, 0.0f, 0.0f );
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, pSrcTex );
m_pD3DDev->SetTexture(1, pSrcTex );
m_pD3DDev->SetTexture(2, pSrcTex );
m_pD3DDev->SetTexture(3, pSrcTex );
return hr;
}
HRESULT CA_Fire::DoSingleTimeStep_3Pass()
{
HRESULT hr;
int i;
// variable for writing to constant memory which uv-offsets to use
D3DXVECTOR4 offset(0.0f, 1.0f, 0.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant( CV_ONOFF_1, &offset, 1);
// Clear intermediate target
hr = m_pD3DDev->SetRenderTarget( m_pIntermediateTarg, NULL);
ASSERT_IF_FAILED( hr );
// Clear 1st target to small fraction of green and blue to offset the
// dependent lookup to the proper values
// 0xff / 16 = 0x10
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0x0, 0x06, 0x06 ), 1.0, 0);
// even if wireframe mode, render to texture as solid
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID );
/////////////////////////////////////////////////////////
// First, write the source texture into the blue channel
// I do this in preparation for a 2D dependent green-blue lookup
// into a "rules" texture which governs how old pixels spawn
// or die into new pixels.
// The logic for the game of life depends on 9 pixels: the source
// pixel and it's 8 neightbors. These are accumulated in three
// passes.
hr = m_pD3DDev->SetRenderTarget( m_pIntermediateTarg, NULL);
SetPixelShader( 0 ); // no pixel shader
// Add into dest texture - texture cleared to small fraction of
// green and blue to offset the dependent lookup to the proper values
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
m_pD3DDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
m_pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
// Setup traditional pipeline to copy the white source pixels
// into just the blue of the dest:
m_pD3DDev->SetTexture(0, m_pTexSrc );
m_pD3DDev->SetRenderState( D3DRS_TEXTUREFACTOR, 0x000000FF ); // ARGB
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR ); // blue only
m_pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
m_pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
// Render using offsets of zero
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
// draw the fan with normal texture coords
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
//excitation
static int count = 0;
count++;
if( count > 400 )
{
// Render using offsets of zero
offset.x = 4.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
// draw the fan with normal texture coords
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
count = 0;
}
/////////////////////////////////////////////////////////////////
// Setup neighbor blending modes:
hr = SetPixelShader( m_dwEqualWeightCombineShader );
ASSERT_IF_FAILED( hr );
DWORD wrapval = m_bWrap ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
for( i=0; i < 4 ; i++ )
{
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU, wrapval);
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
}
/////////////////////////////////////////////////////////////////
// Render 1st set of neighbors
// Add in nearest neighbors
hr = m_pD3DDev->SetRenderTarget( m_pIntermediateTarg, NULL);
ASSERT_IF_FAILED(hr);
// Add result of pixel operations into the dest texture:
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
m_pD3DDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
m_pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
// Render set of neighbors using bilinear filtering to sample
// equal weight of all 8 neighbors in just 4 texture samples
offset.x = 3.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
float pix_mult[4];
pix_mult[0] = 0.0f; // red
pix_mult[1] = 0.25f; // green
pix_mult[2] = 0.0f; // blue
pix_mult[3] = 0.0f; // alpha
hr = m_pD3DDev->SetPixelShaderConstant( PCN_MULTFACTOR_1, &pix_mult, 1 );
ASSERT_IF_FAILED(hr);
hr = m_pD3DDev->SetPixelShaderConstant( PCN_MULTFACTOR_2, &pix_mult, 1 );
ASSERT_IF_FAILED(hr);
m_pD3DDev->SetTexture(0, m_pTexSrc );
m_pD3DDev->SetTexture(1, m_pTexSrc );
m_pD3DDev->SetTexture(2, m_pTexSrc );
m_pD3DDev->SetTexture(3, m_pTexSrc );
for( i=0; i < 4; i++ )
{
m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
}
// draw the fan with displaced texture coordinates
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
for( i=0; i < 4; i++ )
{
m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_POINT );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_POINT );
}
// If wrapping was on, reset to clamp now for later steps
/*
//@@@ if( m_bWrap )
{
for( i=0; i < 4 ; i++ )
{
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
}
}
*/
/////////////////////////////////////////////////////////////////
// Now do dependent 2D lookup into rules texture to set new
// source pixels;
// Write white colors to final target
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );
hr = SetPixelShader( m_dwDependentGB );
ASSERT_IF_FAILED( hr );
hr = m_pD3DDev->SetRenderTarget( m_pTexFinalTarg, NULL);
ASSERT_IF_FAILED(hr);
// Render using offsets of zero
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
m_pD3DDev->SetTexture(0, m_pIntermediateSrc );
m_pD3DDev->SetTexture(1, m_pRulesTexture->GetTexture() );
ASSERT_IF_FAILED( hr );
// draw the fan with displaced texture coordinates
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
ASSERT_IF_FAILED(hr);
/////////////////////////////////////////////////////////////////
// accumulate final output texture here
// blur final white/black state into texture
// blur & add previous output texture
// alpha blend off - render straight blur
/*
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -