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

📄 ch22p1_lensflare.cpp

📁 游戏开发特殊技巧-special.effects.game.programming
💻 CPP
字号:
#include "Ch22p1_LensFlare.h"

CLensFlareSpot::CLensFlareSpot()
{
	m_pTexture = NULL;
	m_fSize = 1.0f;
	m_fLinePos = 0.0f;
  m_Color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
}

CLensFlareSpot::CLensFlareSpot(LPDIRECT3DTEXTURE8 pTex, float fSize, 
                               float fLinePos, D3DXCOLOR Color)
{
	m_pTexture = pTex;
	m_fSize = fSize;
	m_fLinePos = fLinePos;
  m_Color = Color;
	
}
	
CLensFlareSpot::~CLensFlareSpot()
{
}

CLensFlare::CLensFlare()
{
	SetIntensity(CMinMax<float>(0.0f, 1.0f));
	SetIntensityBorder(300);
  m_pd3dDevice = NULL;
}

CLensFlare::~CLensFlare()
{
  InvalidateDeviceObjects();
}

HRESULT CLensFlare::RestoreDeviceObjects(LPDIRECT3DDEVICE8 pDev)
{
	m_pd3dDevice = pDev;
  m_pVBSpots = NULL;
	m_iVBSize = 1;
	return(RecreateVB());
}

HRESULT CLensFlare::RecreateVB()
{
	HRESULT hr = S_OK;
  
	SAFE_RELEASE(m_pVBSpots);
	
	if (m_iVBSize) {
		hr = m_pd3dDevice->CreateVertexBuffer(m_iVBSize*sizeof(VERTEX_LENSFLARE)*6,
			0, D3DFVF_LENSFLARE, D3DPOOL_MANAGED, &m_pVBSpots);

		if (FAILED(hr)) {
			m_pVBSpots = NULL;
		}
	}
  return hr;
}

void CLensFlare::InvalidateDeviceObjects()
{
  DeleteTextures();
	DeleteSpots();
  SAFE_RELEASE(m_pVBSpots);
}

void CLensFlare::CalcLightSourceScreenCoords(CCamera &camera, D3DXMATRIX matProj,
												D3DXVECTOR3 vLightPos, int iScreenWidth, int iScreenHeight,
												int &iCoordX, int &iCoordY, int &iCoordW)
{
	D3DXMATRIX matWorld, matView, matConcat, matViewportScale;
	D3DXVECTOR4 vResult;
	
	matViewportScale = D3DXMATRIX(
	  iScreenWidth/2, 0, 0, 0,
		0, -iScreenHeight/2, 0, 0,
		0, 0, 1, 0,
		iScreenWidth/2, iScreenHeight/2, 0, 1
	);

	matView = camera.GetViewMatrix();
	D3DXMatrixIdentity(&matWorld); // no need for a world xform
	matConcat = matWorld;
	matConcat *= matView;
	matConcat *= matProj;
	matConcat *= matViewportScale;

	D3DXVec3Transform(&vResult, &vLightPos, &matConcat);

	iCoordX = vResult.x/vResult.w;
	iCoordY = vResult.y/vResult.w;
	iCoordW = vResult.w;
}
void CLensFlare::Render(CCamera &camera, D3DXMATRIX matProj,
												D3DXVECTOR3 vLightPos, int iScreenWidth, 
												int iScreenHeight, bool bFirstOnly)
{
	int iScreenX, iScreenY, iScreenW;
	CalcLightSourceScreenCoords(camera, matProj, vLightPos, iScreenWidth, iScreenHeight,
		iScreenX, iScreenY, iScreenW);
	
	if (iScreenW >= 0.0f) 
		Render(iScreenX, iScreenY, iScreenWidth, iScreenHeight, bFirstOnly);
}

void CLensFlare::Render(int iLightSourceX, int iLightSourceY, int iScreenWidth, 
												int iScreenHeight, bool bFirstOnly)
{
	// calculate actual intensity based on the given intensity and how far
	// from the edge of the screen the sun is.
	
	float fRealIntensity;
	int iAwayX = (iLightSourceX < 0) ? -iLightSourceX : 
	  (iLightSourceX > iScreenWidth) ? iLightSourceX-iScreenWidth : 0;
	int iAwayY = (iLightSourceY < 0) ? -iLightSourceY : 
	  (iLightSourceY > iScreenHeight) ? iLightSourceY-iScreenHeight : 0;

	float fAway = (iAwayX > iAwayY) ? iAwayX : iAwayY;

	if (fAway > m_fIntensityBorder) fAway = m_fIntensityBorder;
	
	fRealIntensity = 1.0f - (fAway / m_fIntensityBorder);

	fRealIntensity = m_fIntensity.m_Min + (fRealIntensity*(m_fIntensity.GetRange()));

  // calculate spot positions and fill VB
	{
	
		int iCenterOfScreenX = iScreenWidth/2;
		int iCenterOfScreenY = iScreenHeight/2;

		int iDistanceX = iCenterOfScreenX - iLightSourceX;
		int iDistanceY = iCenterOfScreenY - iLightSourceY;

		// lock the vertex buffer
		VERTEX_LENSFLARE *pVertices;
  
		if(FAILED(m_pVBSpots->Lock( 0, m_iVBSize*6*sizeof(VERTEX_LENSFLARE), (BYTE**)&pVertices, 0)))
			return;

		// for each spot in this flare...
		for (std::vector<CLensFlareSpot>::iterator i = m_Spots.begin(); i != m_Spots.end(); i++) {
			CLensFlareSpot &spot = (*i);

			// calculate this spot's center position
			int iSpotCenterPosX = iCenterOfScreenX - ((float)iDistanceX * spot.GetLinePos());
			int iSpotCenterPosY = iCenterOfScreenY - ((float)iDistanceY * spot.GetLinePos());
			int iSizeDiv2 = (int)((float)iScreenWidth * spot.GetSize()/2.0f);

			D3DXCOLOR color = spot.GetColor();
			color.a *= fRealIntensity;
			if (color.a > 1.0f) color.a = 1.0f;
			if (color.a < 0.0f) color.a = 0.0f;
			if (bFirstOnly && i != m_Spots.begin()) color.a = 0.0f;

			// first triangle
			pVertices->color = color;
			
			pVertices->position = D3DXVECTOR3(iSpotCenterPosX-iSizeDiv2, iSpotCenterPosY-iSizeDiv2, 0);
			pVertices->tu = 0.0f; pVertices->tv = 0.0f;	pVertices->rhw = 1.0f;
			pVertices++;

			pVertices->color = color;
			pVertices->position = D3DXVECTOR3(iSpotCenterPosX+iSizeDiv2, iSpotCenterPosY-iSizeDiv2, 0);
			pVertices->tu = 1.0f; pVertices->tv = 0.0f; pVertices->rhw = 1.0f;
			pVertices++;

			pVertices->color = color;
			pVertices->position = D3DXVECTOR3(iSpotCenterPosX+iSizeDiv2, iSpotCenterPosY+iSizeDiv2, 0);
			pVertices->tu = 1.0f; pVertices->tv = 1.0f; pVertices->rhw = 1.0f;
			pVertices++;
			

			// second triangle
			pVertices->color = color;
			pVertices->position = D3DXVECTOR3(iSpotCenterPosX-iSizeDiv2, iSpotCenterPosY-iSizeDiv2, 0);
			pVertices->tu = 0.0f; pVertices->tv = 0.0f; pVertices->rhw = 1.0f;
			pVertices++;

			pVertices->color = color;
			pVertices->position = D3DXVECTOR3(iSpotCenterPosX+iSizeDiv2, iSpotCenterPosY+iSizeDiv2, 0);
			pVertices->tu = 1.0f; pVertices->tv = 1.0f; pVertices->rhw = 1.0f;
			pVertices++;

			pVertices->color = color;
			pVertices->position = D3DXVECTOR3(iSpotCenterPosX-iSizeDiv2, iSpotCenterPosY+iSizeDiv2, 0);
			pVertices->tu = 0.0f; pVertices->tv = 1.0f; pVertices->rhw = 1.0f;
			pVertices++;
		} // next spot

		// unlock VB
		m_pVBSpots->Unlock();
	}

	// render spots
	{
		m_pd3dDevice->SetRenderState(D3DRS_LIGHTING,  FALSE );
    m_pd3dDevice->SetRenderState(D3DRS_CULLMODE,  D3DCULL_NONE );
  
		// turn on additive alpha blending
		m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
		m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
		m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);

		m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
		m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
		m_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE);

		m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
		m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE);
		m_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);

		// set custom vertex shader
		m_pd3dDevice->SetStreamSource(0, m_pVBSpots, sizeof(VERTEX_LENSFLARE));
		m_pd3dDevice->SetVertexShader(D3DFVF_LENSFLARE);

		// this isn't the fastest way to do things, but it's easy to understand.
		// optimization left as an exercise for the reader :)
		for (int q=0; q < m_Spots.size(); q++) {
			m_pd3dDevice->SetTexture(0, m_Spots[q].GetTexture());
			m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, q*6, 2);
		}
	}
	
}

void CLensFlare::DeleteTextures()
{
  for (std::vector<LPDIRECT3DTEXTURE8>::iterator i = m_Textures.begin(); 
       i != m_Textures.end(); i++) {
    SAFE_RELEASE((*i));
  }
  m_Textures.clear();
}

void CLensFlare::DeleteSpots()
{
  m_Spots.clear();
	m_iVBSize = 0;
	RecreateVB();
}

LPDIRECT3DTEXTURE8 CLensFlare::AddTexture(const char *strFilename)
{
  LPDIRECT3DTEXTURE8 pTexture = NULL;
  
  // create this texture
  if (FAILED(D3DXCreateTextureFromFile(m_pd3dDevice, 
    strFilename, &pTexture))) {
    return(NULL);
  }
  
  // add to vector
  m_Textures.push_back(pTexture);
  return(pTexture);
}

void CLensFlare::AddSpot(CLensFlareSpot &spot)
{
  m_Spots.push_back(spot);
	m_iVBSize = m_Spots.size();
	RecreateVB();
}

⌨️ 快捷键说明

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