⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ca_water.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	// no need to clear temporary target


	// even if wireframe mode, render to texture as solid
	m_pD3DDev->SetRenderState(D3DRS_FILLMODE,			D3DFILL_SOLID );



	DWORD wrapval = m_bWrap ?  D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP;
	m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSU,  wrapval);
	m_pD3DDev->SetTextureStageState(0, D3DTSS_ADDRESSV,  wrapval);
	m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSU,  wrapval);
	m_pD3DDev->SetTextureStageState(1, D3DTSS_ADDRESSV,  wrapval);
	m_pD3DDev->SetTextureStageState(2, D3DTSS_ADDRESSU,  wrapval);
	m_pD3DDev->SetTextureStageState(2, D3DTSS_ADDRESSV,  wrapval);
	m_pD3DDev->SetTextureStageState(3, D3DTSS_ADDRESSU,  wrapval);
	m_pD3DDev->SetTextureStageState(3, D3DTSS_ADDRESSV,  wrapval);


    for(i = 0; i < 4; i++ )
    {
        m_pD3DDev->SetTextureStageState(i, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
	    m_pD3DDev->SetTextureStageState(i, D3DTSS_MINFILTER, D3DTEXF_LINEAR );

    }


	/////////////////////////////////////////////////////////////
	//  Render first 3 components of force from three neighbors
	//  Offsets selected are 1 center texel for center height
	//    and 3 of the 4 nearest neighbors.  Texture selected
	//    is same for all stages as we're turning height difference
	//    of nearest neightbor texels into a force value.


	hr = m_pD3DDev->SetPixelShader( m_dwNeighborForceCalc_1 );
	ASSERT_IF_FAILED( hr );
	
	hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nForceStepOne], NULL);
	ASSERT_IF_FAILED( hr );


	// write first part of force calc
	m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );


	hr = m_pD3DDev->SetTexture(0, m_pTex_HeightSrc );
	ASSERT_IF_FAILED(hr);
	hr = m_pD3DDev->SetTexture(1, m_pTex_HeightSrc );
	ASSERT_IF_FAILED(hr);
	hr = m_pD3DDev->SetTexture(2, m_pTex_HeightSrc );
	ASSERT_IF_FAILED(hr);
	hr = m_pD3DDev->SetTexture(3, m_pTex_HeightSrc );
	ASSERT_IF_FAILED(hr);


	// Render using offset set 1
	offset.x = 1.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	// draw the quad with texture coords doing difference of 
	//  nearby texels for force calc.
	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);



	////////////////////////////////////////////////////////////////
	// Now add in last component of force for the 4th neighbor
	//  that we didn't have enough texture lookups to do in the 
	//  first pass

	hr = m_pD3DDev->SetPixelShader( m_dwNeighborForceCalc_2 );
	ASSERT_IF_FAILED( hr );

	// Cannot use additive blending as the force contribution might
	//   be negative and would have to subtract from the dest.
	// We must instead use an additional texture as target and read
	//   the previous partial 3-neighbor result into the pixel shader
	//   for possible subtraction

	// Alphablend must be false

	//; t0 = center
	//; t1 = 2nd axis final point
	//; t2 = previous partial result texture sampled at center
	//; t3 = not used

	m_pD3DDev->SetTexture(0, m_pTex_HeightSrc );
	m_pD3DDev->SetTexture(1, m_pTex_HeightSrc );
	m_pD3DDev->SetTexture(2, mpTextureFiltered[m_nForceStepOne] );


	// Render to the final force texture 
	hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nForceTexture], NULL);
	ASSERT_IF_FAILED( hr );



	offset.x = 2.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);




	/////////////////////////////////////////////////////////////////
	// Apply the force with a scale factor to reduce it's magnitude.
	// Add this to the current texture representing the water height.

	hr = m_pD3DDev->SetPixelShader( m_dwApplyForceShader );
	ASSERT_IF_FAILED( hr );


	// use offsets of zero
	offset.x = 0.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	
	m_pD3DDev->SetTexture(0, mpTextureFiltered[m_nTex_VelSrc]	);// 1st is offset to 0 with offsets 1.0
	m_pD3DDev->SetTexture(1, mpTextureFiltered[m_nForceTexture]	);				// stage 2,3 not used


	hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTex_VelTarg], NULL);
	ASSERT_IF_FAILED( hr );


	// no more additive blending - math for signed values has to be
	//   done in the pixel shader	
	m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );

	// Set constant at which to apply force to velocity
	float pix_force_mult[4] = { m_fBlend, m_fBlend, m_fBlend, 1.0f };	// RGBA

	hr = m_pD3DDev->SetPixelShaderConstant( PCN_MULTFACTOR_1, &pix_force_mult, 1 );
	ASSERT_IF_FAILED(hr);



	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);





	///////////////////////////////////////////////////////////////////
	// With velocity texture selected, render new excitation droplets
	//   at random freq.


	float rnd_freq;
	rnd_freq = (float)rand()/((float)RAND_MAX);

	if( m_fDropletFreq > rnd_freq )
	{
		// a drop falls - decide where

		float x = (float)rand()/((float)RAND_MAX);
		float y = (float)rand()/((float)RAND_MAX);

		// pick a droplet size at random:
		float scale = 10.0f;
		scale += 25.0f * ((float)rand()/((float)RAND_MAX));

		AddDroplet( x, y, scale );
	}

	//  Now draw the droplets:
	DrawDroplets();


	//////////////////////////////////////////////////////////////////////
	// Apply velocity to position


	hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTex_HeightTarg], NULL);
	ASSERT_IF_FAILED( hr );


	hr = m_pD3DDev->SetPixelShader( m_dwApplyVelocityShader );
	ASSERT_IF_FAILED( hr );
	
	m_pD3DDev->SetTexture(0, m_pTex_HeightSrc );
	m_pD3DDev->SetTexture(1, mpTextureFiltered[m_nTex_VelTarg] );
	m_pD3DDev->SetTexture(2, 0);
	m_pD3DDev->SetTexture(3, 0);


	// no more additive blending - math for signed values has to be
	//   done in the pixel shader	
	m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );

	// Set constant at which to apply velocity to height
	float pix_vel_mult[4] = { m_fVelFactor, m_fVelFactor, m_fVelFactor, 1.0f };	// RGBA

	hr = m_pD3DDev->SetPixelShaderConstant( PCN_MULTFACTOR_1, &pix_vel_mult, 1 );
	ASSERT_IF_FAILED(hr);


	// use offsets of zero
	offset.x = 0.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
	ASSERT_IF_FAILED(hr);


	///////////////////////////////////////////////////////////////////
	//  blur positions to smooth noise & generaly dampen things
	//  degree of blur is controlled by magnitude of 4 neighbor texel
	//   offsets with bilinear on


	// Swap height targ & src

	tmp = m_nTex_HeightTarg;
	m_nTex_HeightTarg = m_nTex_HeightSrc;
	m_nTex_HeightSrc = tmp;

	m_pTex_HeightSrc	= mpTextureFiltered[m_nTex_HeightSrc];

	// Now blur height

	m_pD3DDev->SetTexture(0, m_pTex_HeightSrc );
	m_pD3DDev->SetTexture(1, m_pTex_HeightSrc );
	m_pD3DDev->SetTexture(2, m_pTex_HeightSrc );
	m_pD3DDev->SetTexture(3, m_pTex_HeightSrc );


	m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, false );

	hr = m_pD3DDev->SetRenderTarget( mpFilterTarget[m_nTex_HeightTarg], NULL);
	ASSERT_IF_FAILED( hr );

	hr = m_pD3DDev->SetPixelShader( m_dwEqualWeight_PostMultShader );
	ASSERT_IF_FAILED( hr );

	
	offset.x = 3.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
	ASSERT_IF_FAILED(hr);


	////////////////////////////
	// Draw fixed objects within the texture

	if( m_bApplyInteriorBoundaries )
	{
		DrawInteriorBoundaryObjects();
	}

	///////////////////////////////////////////////////////////////////
	// If selected, create a normal map from the height
	
	if( m_bCreateNormalMap )
	{
		Do_CreateNormalMapSteps();
	}

	


	// Flip the state variable for the next round of rendering
	switch( m_nFlipState )
	{
	case 0:
		m_nFlipState = 1;
		break;
	case 1:
		m_nFlipState = 2;
		break;
	case 2:
		m_nFlipState = 1;
		break;
	}


	return hr;



}


IDirect3DTexture8 *		CA_Water::GetOutputTexture()
{
	int texture_index;

	switch( m_SimulationMode )
	{
	case SM_NORMAL_GRAY:
		texture_index = m_nTex_NrmlTarg;
		break;

	case SM_RGB_GLOW:
		texture_index = m_nTex_HeightTarg;
		break;

	case SM_HUE_DROPLETS:
		texture_index = m_nTex_HeightTarg;
		break;
	}


	assert( mpTextureFiltered[texture_index] != NULL );

	return( mpTextureFiltered[texture_index] );
}



void CA_Water::CreateAndWriteUVOffsets(int width, int height)
{

	// This sets vertex shader constants used to displace the
	//  source texture over several additive samples.  This is 
	//  used to accumulate neighboring texel information that we
	//  need to run the simulation.
	// Label the texels as follows, with the source texel being
	//   rendered as "e"
	//		(0.0)
    //            abc
    //            def
    //            ghi
	//				   (1,1)


    
    m_fPerTexelWidth  = 1.0f/static_cast<float>(width);
    m_fPerTexelHeight = 1.0f/static_cast<float>(height);
	

	// A multiplier for sampling beyond the 8 nearest neighbors
	// For this, we don't use the multiplier, so it is just 1.0

	m_fPerTexelWidth	*= 1.0f;	  // 1 = no change - run standard game of life
    m_fPerTexelHeight   *= 1.0f;


	// Half-texel width and height offsets for sampling from the
	//  exact center of a texel when rendering a full-coverage quad
	//  to a texture target.  Without these, a full-coverage quad with
	//  texture coords from 0 to 1.0 would sample from the lower corner
	//  of each source texel in rendering to a texture target of the 
	//  same resolution as the source texture.

	float woff, hoff;
	woff =  m_fPerTexelWidth/2.0f;
	hoff =  m_fPerTexelHeight/2.0f;


	// Offsets set 0 - all zeros for center of texel sampling.

    // first the easy one: no offsets for sampling the center
	//  'e' texel
	// Use index offset value 0.0 to access these in the 
	//  vertex shader.

    float      noOffsetX[4] = { 0.0f + woff, 0.0f + woff, 0.0f + woff, 0.0f + woff}; 
    float      noOffsetY[4] = { 0.0f + hoff, 0.0f + hoff, 0.0f + hoff, 0.0f + hoff};


	// Offset set 1:  For use with neighbor force pixel shader 1
	//  samples center with 0, +u, -u, and +v,
	//	ie the 'e','f','d', and 'h' texels

    float		type1OffsetX[4] = {	   0.0f + woff,
									-  m_fPerTexelWidth  + woff, 
                                       m_fPerTexelWidth  + woff,
									   0.0f + woff					};

    float		type1OffsetY[4] = {	   0.0f + hoff,
									   0.0f + hoff, 
                                       0.0f + hoff,
									   m_fPerTexelHeight + hoff		};



 

	// Offset set 2:  for use with neighbor force pixel shader 2
	//  samples center with 0, and -v texels 
	//  ie the 'e' and 'b' texels
	// This completes a pattern of sampling center texel and it's
	//   4 nearest neighbors to run the height-based water simulation

	// 3rd must be 0 0 to sample texel center from partial result
	//   texture.

    float		type2OffsetX[4] = {		0.0f + woff,
										0.0f + woff,
										0.0f + woff,
										0.0f + woff					};

    float		type2OffsetY[4] = {		0.0f + hoff,
									-  m_fPerTexelHeight + hoff, 
										0.0f + hoff,
										0.0f + hoff					};


	// Now we change all that & instead of sampling 1 texel from center, we
	//  sample 1.5 texels from center and use bilinear sampling.  This reduces
	//  some of the noise and high-frequency oscillation from sampling the 
	//  exact texel neighbor only, giving smoother results in the height field
	//  and smoother water ripples

	// Displacements 1.5 texels from center texel
	//
	// 0 = 0 0
	// 1 = -s -t
	// 2 = +s -t
	// 3 = +s +t
// /*
	type1OffsetX[0] =	0.0f + woff;
	type1OffsetX[1] = - m_fPerTexelWidth  ;
	type1OffsetX[2] =	m_fPerTexelWidth  + 2.0f * woff;
	type1OffsetX[3] =	m_fPerTexelWidth  + 2.0f * woff;

	type1OffsetY[0] =	0.0f + hoff;
	type1OffsetY[1] = -	m_fPerTexelHeight;
	type1OffsetY[2] = -	m_fPerTexelHeight;
	type1OffsetY[3] =	m_fPerTexelHeight + 2.0f * woff;


	// Displacements 1.5 texels from center texel
	// 0 = 0 0
	// 1 = -s +t
	// 2 = 0 0

	type2OffsetX[0] =	0.0f + woff;
	type2OffsetX[1] = - m_fPerTexelWidth;
	type2OffsetX[2] =	0.0f + woff;
	type2OffsetX[3] =	0.0f + woff;

	type2OffsetY[0] =	0.0f + hoff;
	type2OffsetY[1] =   m_fPerTexelHeight + 2.0f * hoff;
	type2OffsetY[2] =	0.0f + hoff;
	type2OffsetY[3] =	0.0f + hoff;
// */
	

	// Offsets 3 are set in separate function


	//////////////////////////////////////////////////////////////
	// Nearest neighbor offsets:

	float		type4OffsetX[4] = { -  m_fPerTexelWidth	+ woff, 
                                       m_fPerTexelWidth	+ woff,  
                                       0.0f	+ woff,
									   0.0f	+ woff };

    float		type4OffsetY[4] = {    0.0f		+ hoff, 
                                       0.0f		+ hoff,
									   m_fPerTexelHeight		+ hoff, 
                                    -  m_fPerTexelHeight		+ hoff  };

	int i;

    // write all these offsets to constant memory
    for ( i = 0; i < 4; ++i)
    {
        D3DXVECTOR4  noOffset(      noOffsetX[i],    noOffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type1Offset(type1OffsetX[i], type1OffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type2Offset(type2OffsetX[i], type2OffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type4Offset(type4OffsetX[i], type4OffsetY[i], 0.0f, 0.0f);

    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_NO_OFFSET + 5*i, &noOffset,    1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE1     + 5*i, &type1Offset, 1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE2     + 5*i, &type2Offset, 1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE4     + 5*i, &type4Offset, 1);
    }


	// Set offsets set 3.0 used to further filter the high-frequency
	//  oscillations

	UpdateBlurVertOffset();

}



void CA_Water::SetSimMode( int simmode )
{


	m_SimulationMode = simmode;

	if( m_SimulationMode >= SM_LAST )
		m_SimulationMode = 0;


	switch( m_SimulationMode )
	{
	case SM_NORMAL_GRAY:
		m_fEqRestore_factor = 0.5f;
		m_fBlurDist = 0.5f;
		UpdateBlurVertOffset();

		m_eRenderMode = FULLSCREEN_RESULT;
		m_bDrawOutput = false;

		m_fBlend = 0.25f;
		m_fVelFactor = 0.5;
		m_fDropletFreq = 0.1750f;

		m_bCreateNormalMap = true;


		FDebug("Set sim mode to NORMAL_GRAY\n");
		break;

	case SM_RGB_GLOW:
		m_fEqRestore_factor = 0.0f;
		m_fBlurDist = 0.01f;
		UpdateBlurVertOffset();


		m_eRenderMode = FULLSCREEN_FINALOUT;
		m_bDrawOutput = true;

		m_fBlend = 0.25f;
		m_fVelFactor = 0.5;
		m_fDropletFreq = 0.0f;
		
		m_bCreateNormalMap = false;
		m_bApplyInteriorBoundaries = true;


		FDebug("Set sim mode to RGB_GLOW\n");
		break;

	case SM_HUE_DROPLETS:
		m_fEqRestore_factor = 0.0f;
		m_fBlurDist = 0.01f;
		UpdateBlurVertOffset();

		m_fBlend = 0.02f;
		m_fVelFactor = 0.082994f;
		m_fDropletFreq = 0.0f;

		m_eRenderMode = FULLSCREEN_FINALOUT;
		m_bDrawOutput = true;

		m_bCreateNormalMap = false;
		m_bApplyInteriorBoundaries = false;

		FDebug("Set sim mode to HUE_DROPLETS\n");

		m_fBlurDist = 0.020f;
		m_fVelFactor = 0.0637f;
		m_fBlend = 0.01158f;


		break;

	default:
		FDebug("weird sim mode!\n");


	}
}







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -