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

📄 ch15p1_simpleclouds.cpp

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

  Ch15p1_SimpleClouds.cpp: a program that demonstrates the water algorithm,
  without any annoying bells and/or whistles.
  
#############################################################################
*/

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

using namespace std;
const int NUMOCTAVES = 4;

//===========================================================================
//
// class: CCloudOctave.  Represents a single octave of Perlin noise for our
// cloud.
//
//===========================================================================
class CCloudOctave
{
public:
  CCloudOctave(int iOctaveSize, LPDIRECT3DDEVICE8 pDev,
    LPDIRECT3DVERTEXBUFFER8 pvbQuad);

  virtual ~CCloudOctave();
  
  LPDIRECT3DTEXTURE8 m_ptexOctave; // each octave of noise
  LPDIRECT3DTEXTURE8 m_ptexSmoothOctave; // smoothed octave 

  HRESULT GenerateRegularNoise();
  HRESULT SmoothLayer();

  int m_iOctaveSize;
private:
  LPDIRECT3DDEVICE8 m_pd3dDevice;
  LPDIRECT3DVERTEXBUFFER8 m_pvbQuad;

};

typedef vector<CCloudOctave *> CloudOctaveVector;

CCloudOctave::CCloudOctave(int iOctaveSize, LPDIRECT3DDEVICE8 pDev,
                           LPDIRECT3DVERTEXBUFFER8 pvbQuad)
{
  HRESULT hr;
  // squirrel away the device and vertex buffer pointers for later
  m_pd3dDevice = pDev;
  m_pvbQuad = pvbQuad;
  m_iOctaveSize = iOctaveSize;

  OutputDebugString("\nCCloudOctave::CCloudOctave: Allocating Cloud Octave Textures...");

  if (FAILED(hr = D3DXCreateTexture(pDev, iOctaveSize, iOctaveSize, 
      1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, 
      &m_ptexSmoothOctave))) throw(hr);

  if (FAILED(hr = D3DXCreateTexture(pDev, iOctaveSize, iOctaveSize, 
      1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_ptexOctave))) throw(hr);
}

CCloudOctave::~CCloudOctave()
{
  OutputDebugString("\nCCloudOctave::CCloudOctave: Freeing Cloud Octave Textures...");
  // the device and vertex buffers do not belong to us, so we don't 
  // delete them.
  SAFE_RELEASE(m_ptexSmoothOctave);
  SAFE_RELEASE(m_ptexOctave);
}

HRESULT CCloudOctave::SmoothLayer()
{
  return(SmoothRenderCopy(m_ptexOctave, m_ptexSmoothOctave, 
    m_iOctaveSize, m_iOctaveSize, m_pd3dDevice, m_pvbQuad));
}

/****************************************************************************

 GenerateRegularNoise: Creates what Kim Pallister refers to as "Salt and
 Pepper" noise.  Each texel is assigned a random shade of gray.

 ****************************************************************************/
HRESULT CCloudOctave::GenerateRegularNoise()
{
  HRESULT hr;
	
	// lock the textures 
  D3DLOCKED_RECT lockedrect;
  ::ZeroMemory(&lockedrect, sizeof(lockedrect));
  
  if (FAILED(hr = m_ptexOctave->LockRect(0, &lockedrect, NULL, 0))) return(hr);
  
  // our texture surface is now locked, and we can use the pitch to traverse it.
  unsigned char *pSurfBits = static_cast<unsigned char *>(lockedrect.pBits);
  
  int index=0;
  for (int y=0; y < m_iOctaveSize; y++) {
    for (int x=0; x < m_iOctaveSize; x++) {
      /*
      
      // Unremark this (and remark out the section below this) to generate 
      // color clouds instead of normal clouds.

      char cIntensityR = (char)((1.0f+Noise3D(x,y,0)) * 128);
      char cIntensityG = (char)((1.0f+Noise3D(x,y,1)) * 128);
      char cIntensityB = (char)((1.0f+Noise3D(x,y,2)) * 128);

      // the intensity determines the color of this texel
      pSurfBits[index++] = cIntensityB; // blue
      pSurfBits[index++] = cIntensityG; // green
      pSurfBits[index++] = cIntensityR; // red
      pSurfBits[index++] = 0xff;       // alpha

      */

      // this chunk of code generates normal clouds

      char cIntensity = (char)((1.0f+Noise2D(x,y)) * 128);
      // the intensity determines the color of this texel
      pSurfBits[index++] = cIntensity; // blue
      pSurfBits[index++] = cIntensity; // green
      pSurfBits[index++] = cIntensity; // red
      pSurfBits[index++] = 0xff;       // alpha
    }
    // next line
    index += lockedrect.Pitch - (m_iOctaveSize*4);
  }

  // unlock texture surface
  if (FAILED(hr = m_ptexOctave->UnlockRect(0))) return(hr);
	return S_OK;
}

//===========================================================================
//
// class: CCloud.  This class represents a cloud texture.  
//
//===========================================================================
class CCloud
{
public:
  // pointers must be set to NULL so that SAFE_RELEASE doesn't try
  // to release something that isn't there.
  CCloud() : m_ptexFinal(NULL), m_ptexComposite(NULL), m_pvbAlphaBlendingQuad(NULL),
    m_iTextureSize(0) { }
  virtual ~CCloud() { InvalidateDeviceObjects(); }

  HRESULT RestoreDeviceObjects(LPDIRECT3DDEVICE8 pDev, 
    LPDIRECT3DVERTEXBUFFER8 pvbQuad, int iNumOctaves, int iTextureSize);
  HRESULT InvalidateDeviceObjects();

  void RenderToFinalTexture();

  // you can change this to m_ptexComposite to see what it looks like
  // without squaring.
  LPDIRECT3DTEXTURE8 GetFinalTexture() { return(m_ptexComposite); }

  CloudOctaveVector m_vOctaves; // individual cloud layers
private:
  
  LPDIRECT3DTEXTURE8 m_ptexComposite; // the composite noise texture
  LPDIRECT3DTEXTURE8 m_ptexFinal; // the final cloud texture (composite squared)

  void CompositeLayers();
  void SquareCompositeLayer();

  LPDIRECT3DVERTEXBUFFER8 m_pvbAlphaBlendingQuad; // 0.5 alpha quad
  
  int m_iTextureSize;

  LPDIRECT3DDEVICE8 m_pd3dDevice;
  LPDIRECT3DVERTEXBUFFER8 m_pvbQuad; // normal (opaque) quad for rendering textures
};

void CCloud::CompositeLayers()
{
  // get surface interfaces
  LPDIRECT3DSURFACE8 psurfComposite;
  m_ptexComposite->GetSurfaceLevel(0, &psurfComposite);

  // set new rendering target & clear
  m_pd3dDevice->SetRenderTarget(psurfComposite, NULL);
  m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x000000, 1.0f, 0L );
  
  // set up orthogonal projection matrix
  SetupOrthoProjForRenderCopy(m_pd3dDevice, m_iTextureSize, m_iTextureSize);

  // begin rendering the scene
  if (FAILED(m_pd3dDevice->BeginScene())) return;
  m_pd3dDevice->SetStreamSource(0, m_pvbAlphaBlendingQuad, sizeof(VERTEX_XYZ_DIFFUSE_TEX1));
  m_pd3dDevice->SetVertexShader(D3DFVF_XYZ_DIFFUSE_TEX1);

  // now alpha blend (using a factor of 0.5) all other octaves onto the final dest.
  // D3D gets the alpha value from our vertices' alpha components.
  
  // set up texture stages for simple texture stage copy
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
	m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  m_pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE); 

  m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
  m_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
  m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
  m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
	m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCCOLOR);
		
  
  for (CloudOctaveVector::iterator i = m_vOctaves.begin(); i != m_vOctaves.end(); ++i) {
    CCloudOctave *octave = (*i);
  
    // set the source texture active
    m_pd3dDevice->SetTexture(0, octave->m_ptexSmoothOctave);

    // this "blits" the texture
    m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
  }

  // end scene
  m_pd3dDevice->EndScene();

  // release the dest surface 
  psurfComposite->Release();
}

void CCloud::SquareCompositeLayer()
{
  // get surface interfaces
  LPDIRECT3DSURFACE8 psurfFinal;
  m_ptexFinal->GetSurfaceLevel(0, &psurfFinal);

  // set new rendering target & clear
  m_pd3dDevice->SetRenderTarget(psurfFinal, NULL);
  m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET, 0x000000, 1.0f, 0L );
  
  // set up orthogonal projection matrix
  SetupOrthoProjForRenderCopy(m_pd3dDevice, m_iTextureSize, m_iTextureSize);

  // begin rendering the scene
  if (FAILED(m_pd3dDevice->BeginScene())) return;
  
  m_pd3dDevice->SetStreamSource(0, m_pvbQuad, sizeof(VERTEX_XYZ_DIFFUSE_TEX1));
  m_pd3dDevice->SetVertexShader(D3DFVF_XYZ_DIFFUSE_TEX1);
  
  m_pd3dDevice->SetTexture(0,m_ptexComposite);
	m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG2, D3DTA_DIFFUSE);
  
  m_pd3dDevice->SetTexture(1,m_ptexComposite);
	m_pd3dDevice->SetTextureStageState(1,D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	m_pd3dDevice->SetTextureStageState(1,D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pd3dDevice->SetTextureStageState(1,D3DTSS_COLORARG2, D3DTA_CURRENT);
  
	m_pd3dDevice->SetTexture(2,NULL);
	m_pd3dDevice->SetTextureStageState(2,D3DTSS_COLOROP, D3DTOP_DISABLE); 
	
	m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);

	// this "blits" the texture
  m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 2 );
  
  // end scene
  m_pd3dDevice->EndScene();

  // release the dest surface 
  psurfFinal->Release();
}

void CCloud::RenderToFinalTexture()
{
  // get the current depth buffer (we have to pass this into SetRenderTarget
  // so we don't inadvertently drop our depth buffer.)
  LPDIRECT3DSURFACE8 pDepthSurf;
  m_pd3dDevice->GetDepthStencilSurface(&pDepthSurf);

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

  // combine all the noise layers together onto m_ptexComposite
  CompositeLayers();

  // now square the composite texture and put it on the final texture.
  //SquareCompositeLayer();

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

  // release the depth surface interface.
  pDepthSurf->Release();

}

HRESULT CCloud::RestoreDeviceObjects(LPDIRECT3DDEVICE8 pDev, 
                                     LPDIRECT3DVERTEXBUFFER8 pvbQuad,
                                     int iNumOctaves, int iTextureSize)
{
  HRESULT hr;
  InvalidateDeviceObjects(); // just in case something's left over

  // squirrel away the device and vertex buffer pointers for later

⌨️ 快捷键说明

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