Direct3D轮回:游戏特效之全屏泛光(Bloom)
2011-08-25 20:40
381 查看
Bloom,又称“全屏泛光”,是大名鼎鼎的虚幻3游戏引擎中最通用的后期特效技术~
Bloom特效的实现主要依赖于PostProcess框架,即实时绘制当前场景到一后台渲染表面,而后针对其对应贴图进行像素级渲染~
大家还记得我们之前实现的水面效果中的反射和折射贴图吗?此即为PostProcess的典型应用,与Bloom特效有异曲同工之妙。
下面,我们就来揭秘这个Bloom特效的实现流程~
本节我们实现的Bloom特效,在流程上总共分为4步:
1.提取原场景贴图中的亮色;
2.针对提取贴图进行横向模糊;
3.在横向模糊基础上进行纵向模糊;
4.所得贴图与原场景贴图叠加得最终效果图。
所用到的Shader主要有三个,分别对应如上4个步骤中的第1步、第2、3步和第4步。我们来看源代码:
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 "Skybox.h"
#include "SpriteBatch.h"
#include "BaseTerrain.h"
#include "Water.h"
#include "PlantCollect.h"
#include "LensFlare.h"
#include "D3DFog.h"
#include "BloomEffect.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;
CBloomEffect *g_pBloom = NULL;
// Bloom参数体数组及全局索引
int g_bloomParamIndex = 0;
BloomParam g_BloomParams[6]={
BloomParam("Default", 0.25f, 4, 1.25f, 1, 1, 1),
BloomParam("Soft", 0, 3, 1, 1, 1, 1),
BloomParam("Desaturated", 0.5f, 8, 2, 1, 0, 1),
BloomParam("Saturated", 0.25f, 4, 2, 1, 2, 0),
BloomParam("Blurry", 0, 2, 1, 0.1f, 1, 1),
BloomParam("Subtle", 0.5f, 2, 1, 1, 1, 1)
};
// 场景绘制
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));
//ResetFog(D3DFOGTYPE_PIXEL,D3DFOG_EXP2,D3DXCOLOR_WHITE,0.001f);
// 创建并初始化Bloom特效
g_pBloom = new CBloomEffect;
g_pBloom->Create();
}
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();
if(g_pKeyboardInput->IsJustKeyDown(DIK_SPACE))
{
g_bloomParamIndex++;
if(g_bloomParamIndex>=6)
g_bloomParamIndex = 0;
}
g_pBloom->SetParam(&g_BloomParams[g_bloomParamIndex]);
}
void Draw(float gameTick)
{
g_pD3DDevice->GetTransform(D3DTS_WORLD, &g_matWorld);
g_pD3DDevice->SetTransform(D3DTS_VIEW, &g_pD3DCamera->GetViewMatrix());
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);
if(SUCCEEDED(g_pD3DDevice->BeginScene()))
{
//BeginFog(g_pD3DDevice);
g_pWater->BeginReflect();
DrawScene(true,false);
g_pWater->EndReflect();
g_pWater->BeginRefract();
DrawScene(false,true);
g_pWater->EndRefract();
// 开启Bloom
g_pBloom->Begin();
// 绘制实时场景到Bloom原始后台表面
DrawScene(false,false);
g_pWater->Draw(gameTick);
g_pPlant->Draw(gameTick);
// 结束Bloom,并触发Bloom前三个步骤
g_pBloom->End();
// 触发Bloom第四个步骤,而后进行Bloom渲染
g_pBloom->DrawScene();
g_pFlare->Draw();
//EndFog(g_pD3DDevice);
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_pBloom);
ReleaseCOM(g_pMesh);
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);
}
对Bloom参数体各个成员变量数值进行交叉组合,则我们可以得到一系列不同的Bloom效果:
还在羡慕那些专业游戏中美轮美奂的后期特效吗?现在我们也有能力实现了~ 大家赶快动手尝试一下吧 ^ ^
以上,谢谢~
Bloom特效的实现主要依赖于PostProcess框架,即实时绘制当前场景到一后台渲染表面,而后针对其对应贴图进行像素级渲染~
大家还记得我们之前实现的水面效果中的反射和折射贴图吗?此即为PostProcess的典型应用,与Bloom特效有异曲同工之妙。
下面,我们就来揭秘这个Bloom特效的实现流程~
本节我们实现的Bloom特效,在流程上总共分为4步:
1.提取原场景贴图中的亮色;
2.针对提取贴图进行横向模糊;
3.在横向模糊基础上进行纵向模糊;
4.所得贴图与原场景贴图叠加得最终效果图。
所用到的Shader主要有三个,分别对应如上4个步骤中的第1步、第2、3步和第4步。我们来看源代码:
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 "Skybox.h"
#include "SpriteBatch.h"
#include "BaseTerrain.h"
#include "Water.h"
#include "PlantCollect.h"
#include "LensFlare.h"
#include "D3DFog.h"
#include "BloomEffect.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;
CBloomEffect *g_pBloom = NULL;
// Bloom参数体数组及全局索引
int g_bloomParamIndex = 0;
BloomParam g_BloomParams[6]={
BloomParam("Default", 0.25f, 4, 1.25f, 1, 1, 1),
BloomParam("Soft", 0, 3, 1, 1, 1, 1),
BloomParam("Desaturated", 0.5f, 8, 2, 1, 0, 1),
BloomParam("Saturated", 0.25f, 4, 2, 1, 2, 0),
BloomParam("Blurry", 0, 2, 1, 0.1f, 1, 1),
BloomParam("Subtle", 0.5f, 2, 1, 1, 1, 1)
};
// 场景绘制
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));
//ResetFog(D3DFOGTYPE_PIXEL,D3DFOG_EXP2,D3DXCOLOR_WHITE,0.001f);
// 创建并初始化Bloom特效
g_pBloom = new CBloomEffect;
g_pBloom->Create();
}
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();
if(g_pKeyboardInput->IsJustKeyDown(DIK_SPACE))
{
g_bloomParamIndex++;
if(g_bloomParamIndex>=6)
g_bloomParamIndex = 0;
}
g_pBloom->SetParam(&g_BloomParams[g_bloomParamIndex]);
}
void Draw(float gameTick)
{
g_pD3DDevice->GetTransform(D3DTS_WORLD, &g_matWorld);
g_pD3DDevice->SetTransform(D3DTS_VIEW, &g_pD3DCamera->GetViewMatrix());
g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);
if(SUCCEEDED(g_pD3DDevice->BeginScene()))
{
//BeginFog(g_pD3DDevice);
g_pWater->BeginReflect();
DrawScene(true,false);
g_pWater->EndReflect();
g_pWater->BeginRefract();
DrawScene(false,true);
g_pWater->EndRefract();
// 开启Bloom
g_pBloom->Begin();
// 绘制实时场景到Bloom原始后台表面
DrawScene(false,false);
g_pWater->Draw(gameTick);
g_pPlant->Draw(gameTick);
// 结束Bloom,并触发Bloom前三个步骤
g_pBloom->End();
// 触发Bloom第四个步骤,而后进行Bloom渲染
g_pBloom->DrawScene();
g_pFlare->Draw();
//EndFog(g_pD3DDevice);
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_pBloom);
ReleaseCOM(g_pMesh);
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);
}
对Bloom参数体各个成员变量数值进行交叉组合,则我们可以得到一系列不同的Bloom效果:
还在羡慕那些专业游戏中美轮美奂的后期特效吗?现在我们也有能力实现了~ 大家赶快动手尝试一下吧 ^ ^
以上,谢谢~
相关文章推荐
- Direct3D轮回:游戏特效之全屏泛光(Bloom)
- Direct3D轮回:游戏特效之风动、雾化
- Direct3D轮回:游戏特效之晴天光晕
- Direct3D轮回:快速构建基于win32工程的Direct3D游戏框架
- Direct3D轮回:游戏场景之天空
- Direct3D轮回:游戏场景之植被
- Direct3D轮回:游戏场景之河流
- Direct3D轮回:游戏场景之河流
- Direct3D轮回:基于HLSL实现D3D中的光照特效
- Direct3D轮回:游戏场景之陆地
- Silverlight 游戏开发小技巧:角色升级特效
- 页面 html5鼠标滚动全屏图片倾斜分割切换特效
- jquery实现的弹出层登录和全屏层注册特效代码分享
- 解决宽屏电脑打游戏不全屏解决方法
- Codrops 优秀教程:基于 CSS3 的全屏网页过渡特效
- windows 7 全屏游戏解决方案
- DirectX 11游戏编程学习笔记之5: 第4章Direct3D Initialization(Direct3D初始化)
- jQuery插件bgStretcher.js实现全屏背景特效
- jQuery带进度条全屏图片轮播特效代码分享
- PPC扑克牌游戏开发实录 第一篇 之 全屏