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

📄 ch14p1_simplewarp.cpp

📁 游戏开发特殊技巧-special.effects.game.programming
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
#############################################################################

  Ch14p1_SimpleWarp.cpp: a program that demonstrates orthographic projections,
  and how they can be used to copy a texture.
  
#############################################################################
*/

// include files ////////////////////////////////////////////////////////////
#define STRICT
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <D3DX8.h>
#include "D3DApp.h"
#include "D3DFile.h"
#include "D3DUtil.h"
#include "DXUtil.h"
#include "D3DHelperFuncs.h"
#include "Ch14p1_resource.h"
#include "CommonFuncs.h"

// A structure for our custom vertex type. 
struct CUSTOMVERTEX
{
  D3DXVECTOR3 position; // The position
  D3DCOLOR    color;    // The color
  FLOAT       tu, tv;   // The texture coordinates
};

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)

const int VERTEX_GRID_DENSITY = 50;

//-----------------------------------------------------------------------------
// Name: class CMyD3DApplication
// Desc: Application class. The base class (CD3DApplication) provides the 
//       generic functionality needed in all Direct3D samples. CMyD3DApplication 
//       adds functionality specific to this sample program.
//-----------------------------------------------------------------------------
class CMyD3DApplication : public CD3DApplication
{
  // original image texture, plus two effect textures
  LPDIRECT3DTEXTURE8 m_pImageTex;
  LPDIRECT3DTEXTURE8 m_pTex1;
  LPDIRECT3DTEXTURE8 m_pTex2;

  // these are actually just texture pointers, so that we can flip/flop our
  // active/scratch textures easily.
  LPDIRECT3DTEXTURE8 m_pActiveTex;
  LPDIRECT3DTEXTURE8 m_pScratchTex;
  
  // width and height of source image
  int m_iImageWidth, m_iImageHeight;
  
  // vertex buffer used to render texture onto back buffer
  LPDIRECT3DVERTEXBUFFER8 m_pVB;

  // vertex buffer used to store vertex grid
  LPDIRECT3DVERTEXBUFFER8 m_pVBGrid;
  LPDIRECT3DINDEXBUFFER8 m_pIBGrid;

protected:
  void ProcessFeedback();
  HRESULT OneTimeSceneInit();
  HRESULT InitDeviceObjects();
  HRESULT RestoreDeviceObjects();
  HRESULT InvalidateDeviceObjects();
  HRESULT DeleteDeviceObjects();
  HRESULT FinalCleanup();
  HRESULT Render();
  HRESULT FrameMove();
  HRESULT ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format );
  LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

public:
  CMyD3DApplication();
};

//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
//       message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
  CMyD3DApplication d3dApp;

  if( FAILED( d3dApp.Create( hInst ) ) )
    return 0;

  return d3dApp.Run();
}

//-----------------------------------------------------------------------------
// Name: CMyD3DApplication()
// Desc: Application constructor. Sets attributes for the app.
//-----------------------------------------------------------------------------
CMyD3DApplication::CMyD3DApplication()
{
  m_strWindowTitle    = _T("Ch14p1_SimpleWarp");
  m_bUseDepthBuffer   = TRUE;
  m_pTex1             = NULL;
  m_pTex2             = NULL;
  m_pImageTex         = NULL;
  m_pVB               = NULL;
  m_pVBGrid           = NULL;
  m_pIBGrid           = NULL;
}


//-----------------------------------------------------------------------------
// Name: OneTimeSceneInit()
// Desc: Called during initial app startup, this function performs all the
//       permanent initialization.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::OneTimeSceneInit()
{
  return S_OK;
}

void SetupVertexGrid(LPDIRECT3DVERTEXBUFFER8 pVBGrid, int iGridWidth, 
                     int iGridHeight)
{
  HRESULT hr;
  CUSTOMVERTEX* pVertices; 
 
  if( FAILED( hr = pVBGrid->Lock( 0, iGridWidth*iGridHeight*sizeof(CUSTOMVERTEX), 
      (BYTE**)&pVertices, 0 ) ) )
    return;

  for (int x=0; x < iGridWidth; x++) {
    for (int y=0; y < iGridHeight; y++) {
      pVertices[(y*iGridWidth)+x].position = D3DXVECTOR3((((float)x/(float)(iGridWidth-1))*2.0f)-1.0f, (((float)(iGridHeight-1-y)/(float)(iGridHeight-1))*2.0f)-1.0f, 0.0f);
      pVertices[(y*iGridWidth)+x].color    = D3DCOLOR_ARGB(255,0,0,0);
      pVertices[(y*iGridWidth)+x].tu       = (float)x/(float)(iGridWidth-1);
      pVertices[(y*iGridWidth)+x].tv       = (float)y/(float)(iGridHeight-1);

      // the four lines above will create a grid that doesn't warp the image at
      // all.  But now, we jiggle the texture coordinates slightly to achieve
      // the image warp.
      
      // get 2 random numbers - the range of possible values is slightly lopsided,
      // because the effect has a tendency to move to the lower-right.
      float fRandAmtX = RandomNumber(-75,100)/50.0f;
      float fRandAmtY = RandomNumber(-75,100)/50.0f;

      // use the random numbers to calculate the final amount to move.
      pVertices[(y*iGridWidth)+x].tu       += fRandAmtX/(float)(iGridWidth*2);
      pVertices[(y*iGridWidth)+x].tv       += fRandAmtY/(float)(iGridHeight*2);
    }
  }
  if(FAILED(hr = pVBGrid->Unlock())) return;
}

void ProcessBlendEffect(LPDIRECT3DDEVICE8 pd3dDevice,
                        LPDIRECT3DTEXTURE8 pOrigTex, LPDIRECT3DTEXTURE8 pDestTex,
                        LPDIRECT3DVERTEXBUFFER8 pVBGrid, LPDIRECT3DINDEXBUFFER8 pIBGrid,
                        int iTextureWidth,int iTextureHeight)
{
  SetupVertexGrid(pVBGrid, VERTEX_GRID_DENSITY, VERTEX_GRID_DENSITY);
  
  // get the current depth buffer (we have to pass this into SetRenderTarget
  // so we don't inadvertently drop our depth buffer.)
  LPDIRECT3DSURFACE8 pDepthSurf;
  pd3dDevice->GetDepthStencilSurface(&pDepthSurf);

  // get the current rendering target (we'll set it back later)
  LPDIRECT3DSURFACE8 pOldRenderTarget;
  pd3dDevice->GetRenderTarget(&pOldRenderTarget);

  // get surface interfaces for our textures, so we can set them as rendering
  // surfaces later.
  LPDIRECT3DSURFACE8 pDestSurf;
  pDestTex->GetSurfaceLevel(0, &pDestSurf);
  
  // set scratch surface active and clear it.
  // SetRenderTarget will also set our viewport so that it completely fills
  // pDestSurf.
  pd3dDevice->SetRenderTarget(pDestSurf, NULL);
  pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);

  // Set up an orthagonal projection matrix, so we can render the entire
  // texture.
  D3DXMATRIX mat;
  D3DXMatrixOrthoLH(&mat, (float)iTextureWidth, (float)iTextureHeight, 
    0.0, 100.0);
  pd3dDevice->SetTransform( D3DTS_PROJECTION, &mat );

  // this world matrix, combined with orthogonal projection, causes the 
  // texture to completely and exactly fill the rendering surface.
  D3DXMATRIX matWorld,matTrans,matScale;
  D3DXMatrixScaling(&matScale, (float)iTextureWidth/2.0f, (float)iTextureHeight/2.0f, 1.0);

  // move the quad left and up 0.5 units, so that the texels are perfectly
  // centered on the screen pixels.
  D3DXMatrixMultiply(&matWorld, &matScale, D3DXMatrixTranslation(&matTrans, -0.5f, -0.5f, 0));

  // our matrix is now finished.  Tell D3D to use it!
  pd3dDevice->SetTransform( D3DTS_WORLD, &matScale );

  // Clear the backbuffer
  pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,
                       0x00ff00, 1.0f, 0L );

  // begin rendering the scene
  if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  {
    // no alpha blending
    pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
  
    // set our texture active...
    pd3dDevice->SetTexture( 0, pOrigTex );

    // set up our texture stages for a simple texture copy...
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
    pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );

    // draw our quad
    
    pd3dDevice->SetStreamSource( 0, pVBGrid, sizeof(CUSTOMVERTEX) );
    pd3dDevice->SetIndices(pIBGrid, 0);
    pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX );
    pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 
      VERTEX_GRID_DENSITY*VERTEX_GRID_DENSITY, 0, VERTEX_GRID_DENSITY*VERTEX_GRID_DENSITY*2);
    

    // End the scene.
    pd3dDevice->EndScene();
  }

  // release the surface of the scratch texture.
  pDestSurf->Release();

  // set the rendering target back to the old target.
  pd3dDevice->SetRenderTarget(pOldRenderTarget, pDepthSurf);
  pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
  pOldRenderTarget->Release();

  // release the depth surface interface.
  pDepthSurf->Release();
}
//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
//       the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FrameMove()
{
  FLOAT fSecsPerFrame = m_fElapsedTime;
  const float DELAY = 0.05f; // Our Warp effect runs at 20 FPS
  static float fTimeToProcess = DELAY;

  if (m_fElapsedTime < 0.0001) m_fElapsedTime = 0.0001f;

  fTimeToProcess -= m_fElapsedTime;
  if (fTimeToProcess < 0) {
    ProcessBlendEffect(m_pd3dDevice, m_pActiveTex, m_pScratchTex, 
      m_pVBGrid, m_pIBGrid, GetLowestPowerOf2(m_iImageWidth), 
      GetLowestPowerOf2(m_iImageHeight));

    LPDIRECT3DTEXTURE8 pTemp;
    pTemp = m_pActiveTex;
    m_pActiveTex = m_pScratchTex;
    m_pScratchTex = pTemp;

    fTimeToProcess = DELAY;
  }
  
  
  return S_OK;
}

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
//       rendering. This function sets up render states, clears the
//       viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::Render()
{
  // we need to use the actual texture dims here, not the image dims.  
  // we don't care about the size of the image; regardless of its size, we 
  // rendered our image onto a texture.
  int texwidth  = GetLowestPowerOf2(m_iImageWidth);   
  int texheight = GetLowestPowerOf2(m_iImageHeight);  

  // Set up an orthagonal projection matrix, so we can render the entire
  // texture.
  D3DXMATRIX mat;

⌨️ 快捷键说明

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