📄 ch14p1_simplewarp.cpp
字号:
/*
#############################################################################
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 + -