📄 ca_waterwaves.cpp
字号:
return S_OK;
}
bool CA_Water::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
// Return true if keyboard key handled.
char charcode;
float eqinc = 0.05f;
float blurinc = 0.01f;
float normalinc = 0.01f;
if( bDown )
{
// Use only capital letters here - these are VK_ codes!
switch( dwKey )
{
case VK_RIGHT:
if( m_dwSleepDelay < 500 )
m_dwSleepDelay += 2;
FDebug("m_dwSleepDelay: %d\n", m_dwSleepDelay );
return(true);
break;
case VK_LEFT:
if( m_dwSleepDelay > 1 )
m_dwSleepDelay -= 2;
FDebug("m_dwSleepDelay: %d\n", m_dwSleepDelay );
return(true);
break;
case VK_UP:
m_fDropletFreq += 0.05f;
if( m_fDropletFreq > 1.0f )
m_fDropletFreq = 1.0f;
FDebug("Droplet Frequency: %f\n", m_fDropletFreq );
return(true);
break;
case VK_DOWN:
m_fDropletFreq -= 0.05f;
if( m_fDropletFreq < 0.0f )
m_fDropletFreq = 0.0f;
FDebug("Droplet Frequency: %f\n", m_fDropletFreq );
return(true);
break;
case 'I':
case 'L':
m_bApplyInteriorBoundaries = !m_bApplyInteriorBoundaries;
FDebug("Apply interior boundaries: %s\n", m_bApplyInteriorBoundaries ? "TRUE" : "FALSE");
return(true);
break;
case 'Z':
if( m_fEqRestore_factor >= eqinc )
m_fEqRestore_factor -= eqinc;
else
m_fEqRestore_factor = 0.0f;
FDebug("m_fEqRestore_factor: %f\n", m_fEqRestore_factor );
return(true);
break;
case 'X':
if( m_fEqRestore_factor <= 1.0f - eqinc )
m_fEqRestore_factor += eqinc;
else
m_fEqRestore_factor = 1.0f;
FDebug("m_fEqRestore_factor: %f\n", m_fEqRestore_factor );
return(true);
break;
case 'C':
if( m_fBlurDist >= blurinc )
m_fBlurDist -= blurinc;
FDebug("m_fBlurDist: %f\n", m_fBlurDist );
UpdateBlurVertOffset();
return(true);
break;
case 'V':
if( m_fBlurDist <= 1.0f - blurinc )
m_fBlurDist += blurinc;
FDebug("m_fBlurDist: %f\n", m_fBlurDist );
UpdateBlurVertOffset();
return(true);
break;
case 'B':
m_bWrap = !m_bWrap;
FDebug("Wrap mode: %d\n", m_bWrap );
return(true);
break;
case 'M':
m_bUseNormalMapMethod2 = !m_bUseNormalMapMethod2;
FDebug("Use normal map method 2 = %s\n", m_bUseNormalMapMethod2 ? "TRUE" : "FALSE" );
return(true);
break;
case 'Y':
if( m_fNrmlSTScale >= normalinc )
m_fNrmlSTScale -= normalinc;
FDebug("Normal ST scale for red & green: %f\n", m_fNrmlSTScale );
return(true);
break;
case 'U':
if( m_fNrmlSTScale <= 1.0f - normalinc )
m_fNrmlSTScale += normalinc;
FDebug("Normal ST scale for red & green: %f\n", m_fNrmlSTScale );
return(true);
break;
case '1' :
m_eRenderMode = FULLSCREEN_NEIGHBOR_CALC;
FDebug("displaying neighbor calc = force texture\n");
return(true);
break;
case '2':
m_eRenderMode = FULLSCREEN_RESULT;
FDebug("displaying result = velocity\n");
return(true);
break;
case '3' :
m_eRenderMode = ALL_TOGETHER;
FDebug("displaying all surfs\n");
return(true);
break;
case '4':
m_eRenderMode = FULLSCREEN_FINALOUT;
FDebug("displaying finalout = height field\n");
return(true);
break;
case 'F':
m_bFarther = !m_bFarther;
return(true);
break;
case 'R':
case '`':
case '~':
FDebug("Loading new droplet and initial maps\n");
LoadRulesAndOtherMaps();
return(true);
break;
case 'G':
// start or stop the animation
m_bAnimate = !m_bAnimate;
return(true);
break;
case VK_SPACE:
m_bSingleStep = !m_bSingleStep;
return(true);
break;
case 'S':
m_bSlow = !m_bSlow;
return(true);
break;
case 'W':
m_bWireframe = !m_bWireframe;
return(false);
break;
default:
charcode = MapVirtualKey( dwKey, 2 ); // VK to char code
switch( charcode )
{
case '<':
case ',':
m_fVelFactor *= 0.98f;
FDebug("velocity factor (mass): %f\n", m_fVelFactor );
return(true);
break;
case '>':
case '.':
m_fVelFactor *= 1.02f;
FDebug("velocity factor (mass): %f\n", m_fVelFactor );
return(true);
break;
case '[':
case '{':
m_fBlend *= 0.98f;
FDebug("blend: %f\n", m_fBlend );
return(true);
break;
case ']':
case '}':
m_fBlend *= 1.02f;
FDebug("blend: %f\n", m_fBlend );
return(true);
break;
};
};
}
return( false );
}
void CA_Water::SetInitialRenderStates()
{
int i;
// set up render state: disable all except texture stage 0 (see below)
for(i = 0; i < 4; i++ )
{
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(i, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP);
m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_POINT );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_POINT );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE );
m_pD3DDev->SetTextureStageState(i,D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
m_pD3DDev->SetTextureStageState(i,D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | i );
m_pD3DDev->SetTextureStageState(i, D3DTSS_RESULTARG, D3DTA_CURRENT );
}
// Set wrap to zero - It will wrap anyway and avoid the problems of
// setting cylindrical wrapping (D3DRS_WRAP0, D3DWRAP_U == cylindrical)
// for texture coords > 1.0f
// For wrapped textures, you should use only the D3DTSS_ADDRESSU/V/W
// states, unless you are doing cube environment mapping.
m_pD3DDev->SetRenderState(D3DRS_WRAP0, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP1, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP2, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP3, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP4, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP5, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP6, 0);
m_pD3DDev->SetRenderState(D3DRS_WRAP7, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_FOGENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_DITHERENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE );
m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO );
m_pD3DDev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_SPECULARENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE );
m_pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE );
m_pD3DDev->SetRenderState(D3DRS_COLORVERTEX, FALSE );
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID );
m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE );
}
HRESULT CA_Water::Tick()
{
// Render a new frame
HRESULT hr;
int i;
SetInitialRenderStates();
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMATRIX matViewProj;
// 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
hr = m_pD3DDev->SetVertexShader( m_dwVertexShader );
ASSERT_IF_FAILED(hr);
hr = m_pD3DDev->SetStreamSource(0, m_pVertexBuffer, sizeof(QuadVertex));
ASSERT_IF_FAILED(hr);
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(&m_mWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&m_mWorldViewProj, &m_mWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &m_mWorldViewProj(0, 0), 4);
if( m_bReset == true )
{
m_bReset = false;
m_nFlipState = 0;
FDebug("Reset water sim to initial conditions\n");
}
int tmp;
switch( m_nFlipState )
{
case 0:
m_pTex_HeightSrc = m_pInitialStateTexture->GetTexture();
m_nTex_HeightTarg = 0;
m_nTex_HeightSrc = 4;
m_pTex_HeightTarg = mpFilterTarget[m_nTex_HeightTarg];
m_nTex_VelSrc = 1;
m_nTex_VelTarg = 2;
m_pTex_VelTarg = mpFilterTarget[m_nTex_VelTarg];
m_pTex_VelCurSrc = mpTextureFiltered[m_nTex_VelTarg];
m_pTex_VelPrevSrc = mpTextureFiltered[m_nTex_VelSrc];
m_pIntermediateTarg = mpFilterTarget[3];
m_pIntermediateSrc = mpTextureFiltered[3];
m_pInt_FinalTarg = mpFilterTarget[5];
m_pInt_FinalSrc = mpTextureFiltered[5];
// use old ht src as temp place to render normals
m_nTex_NrmlAccum = m_nTex_HeightSrc;
m_nTex_NrmlTarg = 3; // use force tex as place to keep em
// Clear initial velocity texture to 0 == gray
hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[1], NULL);
ASSERT_IF_FAILED( hr );
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0x80, 0x80, 0x80 ), 1.0, 0);
break;
case 1:
// Both to 2 as we never read & write height simultaneously so this is ok
tmp = m_nTex_HeightTarg;
m_nTex_HeightTarg = m_nTex_HeightSrc;
m_nTex_HeightSrc = tmp;
m_pTex_HeightTarg = mpFilterTarget[m_nTex_HeightTarg];
m_pTex_HeightSrc = mpTextureFiltered[m_nTex_HeightSrc];
m_nTex_VelSrc = 2;
m_nTex_VelTarg = 1;
m_pTex_VelTarg = mpFilterTarget[m_nTex_VelTarg];
m_pTex_VelCurSrc = mpTextureFiltered[m_nTex_VelTarg];
m_pTex_VelPrevSrc = mpTextureFiltered[m_nTex_VelSrc];
m_pIntermediateTarg = mpFilterTarget[3];
m_pIntermediateSrc = mpTextureFiltered[3];
m_pInt_FinalTarg = mpFilterTarget[5];
m_pInt_FinalSrc = mpTextureFiltered[5];
// use old ht src as temp place to render normals
m_nTex_NrmlAccum = m_nTex_HeightSrc;
m_nTex_NrmlTarg = 3; // use force tex as place to keep em
break;
case 2:
tmp = m_nTex_HeightTarg;
m_nTex_HeightTarg = m_nTex_HeightSrc;
m_nTex_HeightSrc = tmp;
m_pTex_HeightTarg = mpFilterTarget[m_nTex_HeightTarg];
m_pTex_HeightSrc = mpTextureFiltered[m_nTex_HeightSrc];
m_nTex_VelSrc = 1;
m_nTex_VelTarg = 2;
m_pTex_VelTarg = mpFilterTarget[m_nTex_VelTarg];
m_pTex_VelCurSrc = mpTextureFiltered[m_nTex_VelTarg];
m_pTex_VelPrevSrc = mpTextureFiltered[m_nTex_VelSrc];
m_pIntermediateTarg = mpFilterTarget[3];
m_pIntermediateSrc = mpTextureFiltered[3];
m_pInt_FinalTarg = mpFilterTarget[5];
m_pInt_FinalSrc = mpTextureFiltered[5];
// use old ht src as temp place to render normals
m_nTex_NrmlAccum = m_nTex_HeightSrc;
m_nTex_NrmlTarg = 3; // use force tex as place to keep em
break;
}
if( m_bAnimate == true )
{
// Update the textures for one step of the
// game or cellular automata
DoSingleTimeStep();
}
else if( m_bSingleStep == true )
{
DoSingleTimeStep();
m_bSingleStep = false;
}
else
{
// slow down the rendering and give any other apps a chance
Sleep(50);
}
if( m_bSlow )
{
Sleep( m_dwSleepDelay );
}
IDirect3DTexture8 * pSrcTex;
static int nSkip = 0;
if( nSkip >= m_nSkipInterval && m_bDrawOutput == true )
{
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
hr = m_pD3DDev->SetPixelShader(0);
ASSERT_IF_FAILED(hr);
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(&m_mWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&m_mWorldViewProj, &m_mWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &m_mWorldViewProj(0, 0), 4);
// reset offsets to 0 (ie no offsets)
offset.x = 0.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
hr = m_pD3DDev->SetTexture(0, mpTextureFiltered[m_nTex_NrmlTarg] );
ASSERT_IF_FAILED(hr);
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
ASSERT_IF_FAILED(hr);
break;
case FULLSCREEN_RESULT :
// Draw quad over full display
D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
D3DXMatrixMultiply(&m_mWorldViewProj, &matWorld, &matViewProj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -