📄 ca_water.cpp
字号:
// Reset bilinear filtering, as that is most common
for( i=0; i < 4; i++ )
{
m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(i, D3DTSS_MIPFILTER, D3DTEXF_NONE );
}
return( hr );
}
void CA_Water::SetNormalMapSTScale( float STScale )
{
m_fNrmlSTScale = STScale;
}
void CA_Water::SetBlurDistance( float fac )
{
m_fBlurDist = fac;
UpdateBlurVertOffset();
}
void CA_Water::SetEqRestoreFac( float fac )
{
m_fEqRestore_factor = fac;
}
void CA_Water::SetVelocityApplyFac( float fac )
{
m_fVelFactor = fac;
}
void CA_Water::SetBlendFac( float fac )
{
m_fBlend = fac;
}
void CA_Water::UpdateBlurVertOffset()
{
float woff, hoff;
woff = m_fPerTexelWidth / 2.0f;
hoff = m_fPerTexelHeight / 2.0f;
float type3OffsetX[4] = { - m_fPerTexelWidth/2.0f + woff,
m_fPerTexelWidth + woff,
m_fPerTexelWidth/2.0f + woff,
- m_fPerTexelWidth + woff };
float type3OffsetY[4] = { - m_fPerTexelHeight + hoff,
- m_fPerTexelHeight/2.0f + hoff,
m_fPerTexelHeight + hoff,
m_fPerTexelHeight/2.0f + hoff };
float interp_x, interp_y;
for (int i = 0; i < 4; ++i)
{
interp_x = m_fBlurDist * ( type3OffsetX[i] - woff ) + woff;
interp_y = m_fBlurDist * ( type3OffsetY[i] - hoff ) + hoff;
D3DXVECTOR4 vec_type3Offset( interp_x, interp_y, 0.0f, 0.0f);
m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE3 + 5*i, &vec_type3Offset, 1);
}
}
void CA_Water::DrawInteriorBoundaryObjects()
{
bool bInlineDroplet = true;
HRESULT hr;
assert( m_pD3DDev != NULL );
int i;
IDirect3DSurface8 *pBack_Color = NULL;
IDirect3DSurface8 *pBack_Depth = NULL;
/////////////////////////////
const int numobjects = 1;
int ind = 0;
float xmin[numobjects];
float xmax[numobjects];
float ymin[numobjects];
float ymax[numobjects];
DWORD color = 0x00000000; // ARGB
xmin[ind] = 0.0f;
xmax[ind] = 1.0f;
ymin[ind] = 0.0f;
ymax[ind] = 1.0f;
ind++;
// Could also draw a few fixed objects with
// preset positions, etc..
// Select a different texture or constant color
// as the source for these objects
/*
const int numobjects = 2;
int ind = 0;
float xmin[numobjects];
float xmax[numobjects];
float ymin[numobjects];
float ymax[numobjects];
DWORD color = 0x00000000; // ARGB
xmin[ind] = 0.485f;
xmax[ind] = 0.50f;
ymin[ind] = 0.15f;
ymax[ind] = 0.40f;
ind++; assert( ind < numobjects );
xmin[ind] = 0.485f;
xmax[ind] = 0.50f;
ymin[ind] = 0.45f;
ymax[ind] = 0.55f;
ind++;
*/
float x_center[ numobjects ];
float y_center[ numobjects ];
float x_size[ numobjects ];
float y_size[ numobjects ];
for( i=0; i < numobjects; i++ )
{
x_center[i] = (xmin[i] + xmax[i])/2.0f;
y_center[i] = (ymin[i] + ymax[i])/2.0f;
x_size[i] = (xmax[i] - xmin[i]);
y_size[i] = (ymax[i] - ymin[i]);
}
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
// Draw into the velocity texture:
if( bInlineDroplet )
{
// Rendering is happening in middle of physics calc.
// Render to appropriate texture - this doesn't require
// any special work
}
else
{
// rendering happening outside physics calc
// Render to appropriate velocity texture for next frame,
// also save and restore current render targets
m_pD3DDev->GetRenderTarget( &pBack_Color );
m_pD3DDev->GetDepthStencilSurface( &pBack_Depth );
SetInitialRenderStates();
hr = m_pD3DDev->SetStreamSource(0, m_pVertexBuffer, sizeof(QuadVertex));
ASSERT_IF_FAILED(hr);
hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTex_VelTarg], NULL);
ASSERT_IF_FAILED(hr);
}
hr = m_pD3DDev->SetVertexShader( m_dwVertexShader );
ASSERT_IF_FAILED(hr);
///////////////////////////////////////
// Set render mode to use source texture
// Alpha determines fixed vs. free areas
hr = m_pD3DDev->SetPixelShader( 0 );
ASSERT_IF_FAILED(hr);
m_pD3DDev->SetTexture(0, m_pInitialStateTexture->GetTexture() );
// Additive blend
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pD3DDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// m_pD3DDev->SetRenderState( D3DRS_TEXTUREFACTOR, color ); // ARGB
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
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_SELECTARG1 );
m_pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
m_pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
float x,y;
for( i=0; i < numobjects; i++ )
{
// shift x,y into -1 to 1 range
x = (x_center[i] - 0.5f)*2.0f;
y = (y_center[i] - 0.5f)*2.0f;
// alter matrix to place the droplet
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMATRIX matViewProj;
D3DXMATRIX matWorldViewProj;
D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
D3DXVECTOR3 vLookatPt = D3DXVECTOR3( x, y, 0.0f );
D3DXVECTOR3 vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
// Set World, View, Projection, and combination matrices.
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
// 2.0f cause translation extends from -1 to 1
D3DXMatrixOrthoLH(&matProj, 2.0f, 2.0f, 0.2f, 20.0f); // x,y, zmin zmax
D3DXMatrixMultiply(&matViewProj, &matView, &matProj);
// draw a single quad to texture:
// the quad covers the whole "screen" exactly
D3DXMatrixScaling(&matWorld, x_size[i], y_size[i], 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// Draw the square object
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
ASSERT_IF_FAILED(hr);
}
// reset world view proj matrix
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &m_mWorldViewProj(0, 0), 4);
// Reset to original render target & depth
if( !bInlineDroplet )
{
hr = m_pD3DDev->SetRenderTarget( pBack_Color, pBack_Depth );
ASSERT_IF_FAILED(hr);
}
SAFE_RELEASE(pBack_Color);
SAFE_RELEASE(pBack_Depth);
}
void CA_Water::AddDroplet( float x, float y, float scale )
{
// Adds a droplet to the rendering queue.
// These are then rendered when DrawDroplets() is called
// Coords are from 0 to 1.0 across texture surface
// Size of droplet is determined at draw time - Could add
// another variable to override this
D3DXVECTOR3 pos( x,y,scale );
m_Droplets.push_back( pos );
}
void CA_Water::DrawDroplets()
{
//////////////////////////////////////////////////
// input x,y in range 0.0 to 1.0 to cover whole target
HRESULT hr;
int i;
float x,y;
float scale;
assert( m_pD3DDev != NULL );
/////////////////////////////
// Draw into the velocity texture:
// Rendering is happening in middle of physics calc.
// Render to appropriate velocity texture
IDirect3DSurface8 *pBack_Color = NULL;
IDirect3DSurface8 *pBack_Depth = NULL;
m_pD3DDev->GetRenderTarget( &pBack_Color );
m_pD3DDev->GetDepthStencilSurface( &pBack_Depth );
hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTex_VelTarg], NULL);
ASSERT_IF_FAILED(hr);
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DXMATRIX matProj;
D3DXMATRIX matViewProj;
D3DXMATRIX matWorldViewProj;
D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
D3DXVECTOR3 vUp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
// 2.0f cause translation extends from -1 to 1
D3DXMatrixOrthoLH(&matProj, 2.0f, 2.0f, 0.2f, 20.0f); // x,y, zmin zmax
///////////////////////////////////////
// Set render mode - additive
hr = m_pD3DDev->SetPixelShader( 0 );
ASSERT_IF_FAILED(hr);
hr = m_pD3DDev->SetVertexShader( m_dwVertexShader );
ASSERT_IF_FAILED(hr);
m_pD3DDev->SetTexture(0, m_pDropletTexture->GetTexture() );
// Additive blend
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, true );
m_pD3DDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
m_pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
m_pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
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 );
for( i=0; i < m_Droplets.size(); i++)
{
// shift [0,1.0] coords into [-1,1] range
x = ( m_Droplets[i].x - 0.5f ) * 2.0f;
y = ( m_Droplets[i].y - 0.5f ) * 2.0f;
scale = m_Droplets[i].z;
// alter matrix to place the droplet appropriately
D3DXVECTOR3 vLookatPt = D3DXVECTOR3( x, y, 0.0f );
// Set World, View, Projection, and combination matrices.
D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
D3DXMatrixMultiply(&matViewProj, &matView, &matProj);
D3DXMatrixScaling(&matWorld, 1.0f/scale, 1.0f/scale, 1.0f);
D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
// Draw a single quad to the texture render target
// The quad is textured with the initial droplet texture, and
// covers some small portion of the render target
// Draw the droplet
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
ASSERT_IF_FAILED(hr);
}
// Clear the array of droplets that we've just drawn
m_Droplets.clear();
// reset world view proj matrix
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &m_mWorldViewProj(0, 0), 4);
// restore orig render targets
hr = m_pD3DDev->SetRenderTarget( pBack_Color, pBack_Depth );
ASSERT_IF_FAILED(hr);
SAFE_RELEASE(pBack_Color);
SAFE_RELEASE(pBack_Depth);
}
void CA_Water::Do_CreateNormalMapSteps()
{
HRESULT hr = S_OK;
D3DXVECTOR4 offset( 0.0f, 0.0f, 0.0f, 0.0f);
hr = m_pD3DDev->SetTexture( 0, mpTextureFiltered[m_nTex_HeightTarg] );
hr = m_pD3DDev->SetTexture( 1, mpTextureFiltered[m_nTex_HeightTarg] );
hr = m_pD3DDev->SetTexture( 2, mpTextureFiltered[m_nTex_HeightTarg] );
hr = m_pD3DDev->SetTexture( 3, mpTextureFiltered[m_nTex_HeightTarg] );
ASSERT_IF_FAILED(hr);
m_pD3DDev->SetRenderTarget( mpFilterTarget[ m_nTex_NrmlTarg ], NULL );
ASSERT_IF_FAILED( hr );
// if( m_bUseNormalMapMethod2 )
{
// Set constants for red & green scale factors (also essential color masks)
// Red mask first
float pix_masks[4] = { m_fNrmlSTScale, 0.0f, 0.0f, 0.0f };
hr = m_pD3DDev->SetPixelShaderConstant( PCN_RED_MASK, &pix_masks, 1 );
ASSERT_IF_FAILED(hr);
// Now green mask & scale:
pix_masks[0] = 0.0f;
pix_masks[1] = m_fNrmlSTScale;
hr = m_pD3DDev->SetPixelShaderConstant( PCN_GREEN_MASK, &pix_masks, 1 );
ASSERT_IF_FAILED(hr);
hr = m_pD3DDev->SetPixelShader( m_dwPSH_NormalMapCreate2_Scale );
ASSERT_IF_FAILED(hr);
}
// use nearest neighbor offsets
offset.x = 4.0f;
m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);
hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
ASSERT_IF_FAILED(hr);
}
HRESULT CA_Water::DoSingleTimeStep()
{
HRESULT hr;
int i;
int tmp;
// Swap texture source & target indices & pointers
// 0 = start from initial loaded texture
// 1/2 = flip flop back and forth between targets & sources
switch( m_nFlipState )
{
case 0:
m_pTex_HeightSrc = m_pInitialStateTexture->GetTexture();
m_nTex_HeightTarg = 0;
m_nTex_HeightSrc = 4;
m_nTex_VelSrc = 1;
m_nTex_VelTarg = 2;
m_nForceStepOne = 3;
m_nForceTexture = 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 0x80 == gray
hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTex_VelSrc], 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_HeightSrc = mpTextureFiltered[m_nTex_HeightSrc];
m_nTex_VelSrc = 2;
m_nTex_VelTarg = 1;
m_nForceStepOne = 3;
m_nForceTexture = 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_HeightSrc = mpTextureFiltered[m_nTex_HeightSrc];
m_nTex_VelSrc = 1;
m_nTex_VelTarg = 2;
m_nForceStepOne = 3;
m_nForceTexture = 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;
}
// 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);
// Set force restoring values to equilibrium (0.5 = gray)
float eq_rest[4] = { m_fEqRestore_factor,m_fEqRestore_factor,m_fEqRestore_factor, 1.0f };
hr = m_pD3DDev->SetPixelShaderConstant( PCN_EQ_REST_FAC, &eq_rest, 1);
ASSERT_IF_FAILED(hr);
//////////////////////////////////////////////////////////
// Set constant for offseting values to 0.5 for gray = 0
m_fhalfoff = 0.500f;
float pix_offset[4] = { m_fhalfoff,m_fhalfoff,m_fhalfoff, 1.0f };
hr = m_pD3DDev->SetPixelShaderConstant( PCN_ADDHALF, &(pix_offset[0]) , 1);
ASSERT_IF_FAILED(hr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -