📄 ca_fire.cpp
字号:
SAFE_DELETE( m_pInitialStateTexture);
SAFE_DELETE( m_pRulesTexture );
SAFE_DELETE( m_pOutputMapTexture );
SAFE_DELETE(m_pUI);
if (m_pD3DDev)
{
m_pD3DDev->DeleteVertexShader(m_dwVertexShader);
m_pD3DDev->DeletePixelShader(m_dwEqualWeightCombineShader);
m_pD3DDev->DeletePixelShader(m_dwEqualWeight_PostMultShader);
m_pD3DDev->DeletePixelShader(m_dwDependentGB );
m_pD3DDev->DeletePixelShader(m_dwDependentAR );
m_dwVertexShader = 0;
m_dwEqualWeight_PostMultShader = 0;
m_dwEqualWeightCombineShader = 0;
m_dwDependentGB = 0;
m_dwDependentAR = 0;
for (int i = 0; i < kMaxNumTargets; ++i)
{
SAFE_RELEASE(mpFilterTarget[i]);
SAFE_RELEASE(mpTextureFiltered[i]);
}
SAFE_RELEASE(mpBackbufferColor);
SAFE_RELEASE(mpBackbufferDepth);
SAFE_RELEASE(m_pD3DDev); // we AddRef()'d in Initialize
}
return S_OK;
}
HRESULT CA_Fire::Start()
{
return S_OK;
}
HRESULT CA_Fire::CreateTextureRenderTarget()
{
HRESULT hr;
_ASSERT( mpBackbufferColor != NULL );
_ASSERT( mpBackbufferDepth != NULL );
// get the description for the texture we want to filter
D3DSURFACE_DESC ddsd;
m_pInitialStateTexture->GetTexture()->GetLevelDesc(0, &ddsd);
int i;
for( i=0; i < kMaxNumTargets; i++ )
{
if( mpFilterTarget[i] != NULL )
{
SAFE_RELEASE(mpFilterTarget[i]);
mpFilterTarget[i] = NULL;
}
if( mpTextureFiltered[i] != NULL )
{
SAFE_RELEASE(mpTextureFiltered[i]);
mpTextureFiltered[i] = NULL;
}
}
// create new textures just like the current texture
for( i = 0; i < kMaxNumTargets; i++ )
{
hr = m_pD3DDev->CreateTexture(ddsd.Width, ddsd.Height, 1,
D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT, &mpTextureFiltered[i]);
if (FAILED(hr))
{
m_strLastError = "Can't CreateTexture!\n";
assert(false);
return E_FAIL;
}
hr = mpTextureFiltered[i]->GetSurfaceLevel(0, &mpFilterTarget[i]);
if (FAILED(hr))
{
m_strLastError = "Can't Get to top-level texture!\n";
assert(false);
return E_FAIL;
}
// set our render target to the new and shiny textures without depth
hr = m_pD3DDev->SetRenderTarget(mpFilterTarget[i], NULL);
if (FAILED(hr))
{
m_strLastError = "Can't SetRenderTarget to new surface!\n";
assert(false);
return E_FAIL;
}
}
// switch back to conventional back-buffer
hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
if (FAILED(hr))
{
m_strLastError = "Can't SetRenderTarget to original back-buffer surfaces!\n";
assert(false);
return E_FAIL;
}
return S_OK;
}
HRESULT CA_Fire::SetPixelShader( DWORD dwHandle )
{
HRESULT hr = S_OK;
assert( m_pD3DDev != NULL );
if( m_dwCurrentPixelShader != dwHandle )
{
hr = m_pD3DDev->SetPixelShader( dwHandle );
ASSERT_IF_FAILED(hr);
m_dwCurrentPixelShader = dwHandle;
}
return hr;
}
HRESULT CA_Fire::SetVertexShader( DWORD dwHandle )
{
HRESULT hr = S_OK;
assert( m_pD3DDev != NULL );
if( m_dwCurrentVertexShader != dwHandle )
{
hr = m_pD3DDev->SetVertexShader( dwHandle );
ASSERT_IF_FAILED(hr);
m_dwCurrentVertexShader = dwHandle;
}
return hr;
}
void CA_Fire::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
// Note - pressing tidle key will not cause this to be called
// until the window is resized - Something happens then to
// trigger the Keyboard function.
unsigned int option = static_cast<unsigned int>(meDisplayOption);
char charcode;
if( bDown )
{
// Use only capital letters here - these are VK_ codes!
switch( dwKey )
{
case VK_LEFT:
if( m_nSlowDelay > 0 )
m_nSlowDelay--;
m_bSlow = true;
FDebug("frame rate slow delay: %d\n", m_nSlowDelay );
return;
break;
case VK_RIGHT:
if( m_nSlowDelay < 500 )
m_nSlowDelay++;
m_bSlow = true;
FDebug("frame rate slow delay: %d\n", m_nSlowDelay );
return;
break;
case 'C':
m_bMulticolor = !m_bMulticolor;
return;
break;
case 'B':
m_bWrap = !m_bWrap;
FDebug("Wrap mode: %d\n", m_bWrap );
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case 'M':
m_nSkipInterval++;
FDebug("Skip Interval: %d\n", m_nSkipInterval );
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case 'N':
m_nSkipInterval--;
if( m_nSkipInterval < 0 )
m_nSkipInterval = 0;
FDebug("Skip Interval: %d\n", m_nSkipInterval );
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case '1' :
m_eRenderMode = FULLSCREEN_NEIGHBOR_CALC;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case '2':
m_eRenderMode = FULLSCREEN_RESULT;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case '3' :
m_eRenderMode = ALL_TOGETHER;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case '4':
m_eRenderMode = FULLSCREEN_FINALOUT;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case 'F':
m_bFarther = !m_bFarther;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case 'R':
case '`':
case '~':
FDebug("Loading new rules texture map\n");
LoadRulesAndOtherMaps();
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case 'G':
// start or stop the animation
m_bAnimate = !m_bAnimate;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case VK_SPACE:
m_bSingleStep = !m_bSingleStep;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
case 'S':
m_bSlow = !m_bSlow;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
return;
break;
default:
charcode = MapVirtualKey( dwKey, 2 ); // VK to char code
switch( charcode )
{
case '[':
case '{':
m_fColorAtten *= 0.999f;
FDebug("blend: %f\n", m_fColorAtten );
return;
break;
case ']':
case '}':
m_fColorAtten *= 1.001f;
FDebug("blend: %f\n", m_fColorAtten );
return;
break;
case '-':
m_fTranslateAmount *= 0.99f;
FDebug("m_fTranslateAmount: %f\n", m_fTranslateAmount );
return;
break;
case '=':
m_fTranslateAmount *= 1.01f;
FDebug("m_fTranslateAmount: %f\n", m_fTranslateAmount );
return;
break;
};
};
}
eEBKeyAction Action = TranslateEffectKey(dwKey, nFlags, bDown);
switch ( Action )
{
case EB_HELP:
{
EBString str;
str = " Help : F1 - Help\n\n";
str += " W - Wireframe toggle\n\n";
str += " Home - Restart from initial frame \n\n";
str += " R - Reload \"rules\" and \"output\" maps \n";
str += " from files\n";
str += " G - Stop/Go animation toggle\n";
str += " SPC - Single frame step when anim stopped \n";
str += " B - Toggle border wrapping\n\n";
str += " 1 - Draw neighbor accumulation map\n";
str += " 2 - Draw current generation\n";
str += " 3 - Draw initial, temp, and output frames\n";
str += " 4 - Draw color re-map if enabled\n";
str += " F - Toggle additional color re-map step\n\n";
str += " M - Increase # frames to skip\n";
str += " N - Decrease # frames to skip\n";
str += " S - Slow updates to ~20 fps\n\n";
::MessageBoxEx( NULL, str.c_str(),
"Help", MB_ICONINFORMATION | MB_TASKMODAL, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) );
}
break;
case EB_WIREFRAME:
{
m_bWireframe = !m_bWireframe;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
case EB_RESET:
{
m_pUI->Reset();
m_bReset = true;
}
break;
case EB_ADD:
break;
case EB_SUBTRACT:
break;
default:
break;
}
}
// Our properties were updated, set the correct shader to match
void CA_Fire::PropertyUpdateCallback(const EBProperty* pProperty, bool bWritten)
{
// If somebody changed the filter we are doing, set the dirty flag and change the
// pixel shader enum to reflect this.
if (pProperty->IsKindOf(EBTYPE_ENUM_PROP))
{
if (bWritten)
{
if (pProperty->GetOffset() == OBJECT_MEMBER(m_strEffectPixelShader))
{
if (m_strEffectPixelShader.compare(GetFilePath("EqualWeightCombine.nvp")) == 0)
{
meDisplayOption = EFFECT_FIRE_01;
}
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
else
{
switch (meDisplayOption)
{
case EFFECT_FIRE_01:
m_strEffectPixelShader = GetFilePath("EqualWeightCombine.nvp");
break;
default:
;
}
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PIXELSHADERS;
}
}
}
}
void CA_Fire::MouseButton(HWND hWnd, eButtonID button, bool bDown, int x, int y)
{
if(button == MOUSE_LEFTBUTTON)
{
if(bDown)
{
m_pUI->OnLButtonDown(x, y);
}
else
{
m_pUI->OnLButtonUp(x, y);
}
}
}
void CA_Fire::MouseMove(HWND hWnd, int x, int y)
{
m_pUI->OnMouseMove(x, y);
return;
}
HRESULT CA_Fire::Tick(EBTimer* pTimer)
{
// Render a new frame
HRESULT hr;
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMATRIX matViewProj;
D3DXMATRIX matWorldViewProj;
// write to constant memory which uv-offsets to use to accumulate neighbor information
D3DXVECTOR4 offset(0.0f, 0.0f, 0.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
// Disable culling
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// set render state
SetVertexShader(m_dwVertexShader);
m_pD3DDev->SetStreamSource(0, m_pVertexBuffer, sizeof(QuadVertex));
D3DXVECTOR3 const vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
D3DXVECTOR3 const vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 const vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
// Set World, View, Projection, and combination matrices.
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
D3DXMatrixOrthoLH(&matProj, 4.0f, 4.0f, 0.2f, 20.0f);
D3DXMatrixMultiply(&matViewProj, &matView, &matProj);
// draw a single quad to texture:
// the quad covers the whole "screen" exactly
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);
if( m_bReset == true )
{
m_bReset = false;
m_nFlipState = 0;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
int tmp;
if( m_nFlipState == 0 )
{
m_pTexSrc = m_pInitialStateTexture->GetTexture();
m_pIntermediateTarg = mpFilterTarget[0];
m_pIntermediateSrc = mpTextureFiltered[0];
m_pTexFinalTarg = mpFilterTarget[1];
m_pTexFinalSrc = mpTextureFiltered[1];
m_nTarget4 = 3;
m_nTarget3 = 2;
// Clear output textures
hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[2], NULL);
ASSERT_IF_FAILED( hr );
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0x0, 0x00, 0x00 ), 1.0, 0);
hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTarget4], NULL);
ASSERT_IF_FAILED( hr );
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0x0, 0x00, 0x00 ), 1.0, 0);
}
else if( m_bAnimate == true || m_bSingleStep == true )
{
switch( m_nFlipState )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -