您的位置:首页 > 其它

Direct3D轮回:游戏特效之晴天光晕

2011-08-07 11:15 309 查看
基本的场景元素具备之后,本节我们来为已构建的场景新增一些特殊效果~

玩过摄影的朋友应该都知道,当我们把镜头对准某一发光体的时候,会有光晕现象产生,这种光晕现象也称作“镜头眩光”。

在晴天的场景中实现这样一个光晕特效,往往会有意想不到的效果~

晴天光晕特效实现的原理其实挺简单,它可以由一个主光晕加一系列镜头七彩光环组成。主光晕以光源为中心,镜头光环则散列在由光源及镜头中心决定的直线上~

其效果大致如图所示:

D3DGame.cpp

/*-------------------------------------

代码清单:D3DGame.cpp
来自:http://www.cnblogs.com/kenkao

-------------------------------------*/

#include "StdAfx.h"
#include "D3DGame.h"
#include "D3DCamera.h"
#include "D3DEffect.h"
#include "CoordCross.h"
#include "SimpleXMesh.h"
#include "Texture2D.h"
#include "D3DSprite.h"
#include "Skybox.h"
#include "SpriteBatch.h"
#include "BaseTerrain.h"
#include "Water.h"
#include "PlantCollect.h"
#include "LensFlare.h"
#include <stdio.h>
#include <time.h>

//---通用全局变量

HINSTANCE g_hInst;
HWND g_hWnd;
D3DXMATRIX g_matWorld;
D3DXMATRIX g_matProjection;
D3DPRESENT_PARAMETERS g_D3DPP;

//---D3D全局变量

IDirect3D9 *g_pD3D = NULL;
IDirect3DDevice9 *g_pD3DDevice = NULL;
CMouseInput *g_pMouseInput = NULL;
CKeyboardInput *g_pKeyboardInput = NULL;
CD3DCamera *g_pD3DCamera = NULL;
CSpriteBatch *g_pSpriteBatch = NULL;
CSkybox *g_pSkybox = NULL;
CBaseTerrain *g_pBaseTerrain = NULL;
CWater *g_pWater = NULL;
CPlantCollect *g_pPlant = NULL;
CSimpleXMesh *g_pMesh = NULL;
CLensFlare *g_pFlare = NULL;

// 场景绘制
void DrawScene(bool isReflect,bool isRefract);

void Initialize(HINSTANCE hInst, HWND hWnd)
{
g_hInst = hInst;
g_hWnd = hWnd;
InitD3D(&g_pD3D, &g_pD3DDevice, g_D3DPP, g_matProjection, hWnd);
g_pMouseInput = new CMouseInput;
g_pMouseInput->Initialize(hInst,hWnd);
g_pKeyboardInput = new CKeyboardInput;
g_pKeyboardInput->Initialize(hInst,hWnd);
g_pD3DCamera = new CD3DCamera;
g_pSpriteBatch = new CSpriteBatch(g_pD3DDevice);
srand(time(0));
}

CTexture2D* debugTexture = NULL;

void LoadContent()
{
g_pD3DCamera->SetCameraPos(D3DXVECTOR3(600.0f,0.0f,600.0f));

g_pSkybox = new CSkybox;
g_pSkybox->Create("Skybox_0.JPG","Skybox_1.JPG","Skybox_2.JPG"
,"Skybox_3.JPG","Skybox_4.JPG","Skybox_5.JPG");

g_pBaseTerrain = new CBaseTerrain;
g_pBaseTerrain->Create(128,128,10,"HeightData_128x128.raw","Grass.dds");

g_pWater = new CWater;
g_pWater->Create(1280,1280,0.0f,0.0f,40.0f);

g_pPlant = new CPlantCollect;
g_pPlant->Create(60,90,15);

g_pMesh = new CSimpleXMesh;
g_pMesh->LoadXMesh("WindMill.x");

g_pFlare = new CLensFlare;
g_pFlare->Create(D3DXVECTOR3(-1600,700,600),D3DXVECTOR2(800,600));
}

void Update(float gameTick)
{
g_pMouseInput->GetState();
g_pKeyboardInput->GetState();

// 更新摄影机高度
D3DXVECTOR3 CameraPos = g_pD3DCamera->GetCameraPos();
float roleHeight = 25.0f;
float Ty = g_pBaseTerrain->GetExactHeightAt(CameraPos.x,CameraPos.z) + roleHeight;
g_pD3DCamera->SetCameraPos(D3DXVECTOR3(
CameraPos.x,
Ty,
CameraPos.z));

g_pD3DCamera->Update();
}

void Draw(float gameTick)
{
g_pD3DDevice->GetTransform(D3DTS_WORLD, &g_matWorld);
g_pD3DDevice->SetTransform(D3DTS_VIEW, &g_pD3DCamera->GetViewMatrix());
if(SUCCEEDED(g_pD3DDevice->BeginScene()))
{
g_pWater->BeginReflect();
DrawScene(true,false);
g_pWater->EndReflect();

g_pWater->BeginRefract();
DrawScene(false,true);
g_pWater->EndRefract();

g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);
DrawScene(false,false);
g_pWater->Draw(gameTick);
g_pPlant->Draw(gameTick);
// 绘制镜头光晕
g_pFlare->Draw();
g_pD3DDevice->EndScene();
}
g_pD3DDevice->Present(NULL, NULL, NULL, NULL);
}

void DrawScene(bool isReflect,bool isRefract)
{
g_pSkybox->Draw(isReflect,isRefract);
g_pBaseTerrain->Draw();

D3DXMATRIX scalTrans;
D3DXMatrixScaling(&scalTrans,5.0f,5.0f,5.0f);
D3DXMATRIX movTrans;
D3DXMatrixTranslation(&movTrans,366,g_pBaseTerrain->GetExactHeightAt(366,190)-5.0f,190);
g_pMesh->DrawXMesh(scalTrans * movTrans);
}

void UnloadContent()
{
ReleaseCOM(g_pFlare);
ReleaseCOM(g_pPlant);
ReleaseCOM(g_pWater);
ReleaseCOM(g_pBaseTerrain);
ReleaseCOM(g_pSkybox);
}

void Dispose()
{
ReleaseCOM(g_pSpriteBatch);
ReleaseCOM(g_pD3DCamera);
ReleaseCOM(g_pKeyboardInput);
ReleaseCOM(g_pMouseInput);
ReleaseCOM(g_pD3DDevice);
ReleaseCOM(g_pD3D);
}
最后是效果图:



是否有一种身临其境的感觉呢?呵呵~

最后需要顺带一提的是,镜头光晕应当仅在光源可见时才进行绘制。而本节中实现的CLensFlare类下的IsVisible方法还存在很大的瑕疵,并不能精确判断光源的可见性。

D3D中要精确实现光源的可见性判断,常规的做法应当是采用“遮挡查询”机制,相关内容后续有时间的话会为大家做更进一步的讲解~

以上,谢谢~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: