Direct3D轮回:游戏特效之全屏泛光(Bloom)

来源:互联网 发布:php 企业模板 编辑:程序博客网 时间:2024/04/28 03:03

Bloom,又称“全屏泛光”,是大名鼎鼎的虚幻3游戏引擎中最通用的后期特效技术~ Bloom特效的实现主要依赖于PostProcess框架,即实时绘制当前场景到一后台渲染表面,而后针对其对应贴图进行像素级渲染~ 大家还记得我们之前实现的水面效果中的反射和折射贴图吗?此即为PostProcess的典型应用,与Bloom特效有异曲同工之妙。 下面,我们就来揭秘这个Bloom特效的实现流程~ 本节我们实现的Bloom特效,在流程上总共分为4步: 1.提取原场景贴图中的亮色; 2.针对提取贴图进行横向模糊; 3.在横向模糊基础上进行纵向模糊; 4.所得贴图与原场景贴图叠加得最终效果图。 所用到的Shader主要有三个,分别对应如上4个步骤中的第1步、第2、3步和第4步。我们来看源代码:   /*-------------------------------------代码清单:BloomExtract.fx来自:http://create.msdn.com/en-US/ (AppHub)-------------------------------------*/// 提取原始场景贴图中明亮的部分// 这是应用全屏泛光效果的第一步sampler TextureSampler : register(s0);float BloomThreshold;float4 ThePixelShader(float2 texCoord : TEXCOORD0) : COLOR0{    // 提取原有像素颜色    float4 c = tex2D(TextureSampler, texCoord);    // 在BloomThreshold参数基础上筛选较明亮的像素    return saturate((c - BloomThreshold) / (1 - BloomThreshold));    }technique BloomExtract{    pass Pass1    {        PixelShader = compile ps_2_0 ThePixelShader();    }}   /*-------------------------------------代码清单:GaussianBlur.fx来自:http://create.msdn.com/en-US/ (AppHub)-------------------------------------*/// 高斯模糊过滤// 这个特效要应用两次,一次为横向模糊,另一次为横向模糊基础上的纵向模糊,以减少算法上的时间复杂度// 这是应用Bloom特效的中间步骤sampler TextureSampler : register(s0);#define SAMPLE_COUNT 15// 偏移数组float2 SampleOffsets[SAMPLE_COUNT];// 权重数组float SampleWeights[SAMPLE_COUNT];float4 ThePixelShader(float2 texCoord : TEXCOORD0) : COLOR0{    float4 c = 0;        // 按偏移及权重数组叠加周围颜色值到该像素    // 相对原理,即可理解为该像素颜色按特定权重发散到周围偏移像素    for (int i = 0; i < SAMPLE_COUNT; i++)    {        c += tex2D(TextureSampler, texCoord + SampleOffsets[i]) * SampleWeights[i];    }        return c;}technique GaussianBlur{    pass Pass1    {        PixelShader = compile ps_2_0 ThePixelShader();    }}   /*-------------------------------------代码清单:BloomCombine.fx来自:http://create.msdn.com/en-US/ (AppHub)-------------------------------------*/// 按照特定比例混合原始场景贴图及高斯模糊贴图,产生泛光效果// 这是全屏泛光特效的最后一步// 模糊场景纹理采样器sampler BloomSampler : register(s0);// 原始场景纹理及采样器定义texture BaseTexture;sampler BaseSampler = sampler_state{    Texture   = (BaseTexture);    MinFilter = Linear;    MagFilter = Linear;    MipFilter = Point;    AddressU  = Clamp;    AddressV  = Clamp;};float BloomIntensity;float BaseIntensity;float BloomSaturation;float BaseSaturation;// 减缓颜色的饱和度float4 AdjustSaturation(float4 color, float saturation){    // 人眼更喜欢绿光,因此选取0.3, 0.59, 0.11三个值    float grey = dot(color, float3(0.3, 0.59, 0.11));    return lerp(grey, color, saturation);}float4 ThePixelShader(float2 texCoord : TEXCOORD0) : COLOR0{    // 提取原始场景贴图及模糊场景贴图的像素颜色    float4 bloom = tex2D(BloomSampler, texCoord);    float4 base = tex2D(BaseSampler, texCoord);        // 柔化原有像素颜色    bloom = AdjustSaturation(bloom, BloomSaturation) * BloomIntensity;    base = AdjustSaturation(base, BaseSaturation) * BaseIntensity;        // 结合模糊像素值微调原始像素值    base *= (1 - saturate(bloom));        // 叠加原始场景贴图及模糊场景贴图,即在原有像素基础上叠加模糊后的像素,实现发光效果    return base + bloom;}technique BloomCombine{    pass Pass1    {        PixelShader = compile ps_2_0 ThePixelShader();    }}   三个Shader均来自于微软WP7开发者俱乐部,如有引用,敬请标明AppHub字样及其站点网址:http://create.msdn.com/en-US/,以示对作者原创版权的尊重!   具备相应的Shader之后,下面我们来看如何运用他们来实现Bloom特效的四个关键步骤~ 因为最终的效果贴图本质上是一张与屏幕大小相同的纹理,因此,我们使用原来构建的CSpriteBatch进行绘制。而CSpriteBatch提供的接口是针对于CTexture2D的,所以我们首先要增强并完善CTexture2D类的功能~ 以下提供两个函数,使得CTexture2D可以直接产生渲染贴图,并允许获取其后台渲染表面:   bool CTexture2D::CreateRenderTarget(UINT SizeX, UINT SizeY){    // 创建渲染贴图    HRESULT hr;    hr = D3DXCreateTexture(g_pD3DDevice, SizeX, SizeY, 1,        D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pTexture);    if(FAILED(hr))        return false;    m_Width  = SizeX;    m_Height = SizeY;    m_SurRect.top    = 0;    m_SurRect.left   = 0;    m_SurRect.right  = m_Width;    m_SurRect.bottom = m_Height;    return true;}bool CTexture2D::GetRenderSurface(IDirect3DSurface9** pOutSurface){    // 获得贴图的渲染表面    HRESULT hr;    hr = m_pTexture->GetSurfaceLevel(0, pOutSurface);    if(FAILED(hr))        return false;    else        return true;}   之后,就可以着手构建我们的CBloomEffect效果类了:   /*-------------------------------------代码清单:BloomEffect.h来自:http://www.cnblogs.com/kenkao-------------------------------------*/#include "D3DEffect.h"#include "Texture2D.h"#pragma once// Bloom参数体typedef struct _BloomParam{    char*  _Name;              // Bloom特效名称    float  _BloomThreshold;    // 饱和度    float  _BlurAmount;        // 模糊程度    float  _BloomIntensity;    // 模糊剧烈度    float  _BaseIntensity;     // 原始剧烈度    float  _BloomSaturation;   // 模糊饱和度    float  _BaseSaturation;    // 原始饱和度    _BloomParam(){}    _BloomParam(char* name, float bloomThreshold, float blurAmount,        float bloomIntensity, float baseIntensity,        float bloomSaturation, float baseSaturation)    {        _Name = name;  _BloomThreshold = bloomThreshold; _BlurAmount = blurAmount;        _BloomIntensity = bloomIntensity;   _BaseIntensity = baseIntensity;        _BloomSaturation = bloomSaturation; _BaseSaturation = baseSaturation;    }}BloomParam;class CBloomEffect{public:    CBloomEffect(void);    ~CBloomEffect(void);public:    void Create();       // 创建Bloom特效    void Release();      // 释放Bloom特效    void DrawScene();    // 场景绘制    void Begin();        // 开启Bloom    void End();          // 关闭Bloompublic:    void        SetParam(BloomParam* pParam){m_pParam = pParam;}  // 参数体设置    BloomParam* GetParam()                  {return m_pParam;}    // 参数体获取private:    void PostScene();                   // Bloom场景投递    void PostSurface(                   // 应用特效投递贴图到特定缓存表面,本质就是将一个贴图应用Shader之后的效果写入另一个贴图         CTexture2D* pTexture,          // 后台纹理         IDirect3DSurface9* pSurface,   // 渲染表面         CD3DEffect* pEffect);          // 目标特效    bool LoadContent();                 // 加载内容    bool GetSurfaces();                 // 获取渲染表面private:    float ComputeGaussian(float n);                 // 计算高斯模糊参数    void  SetBlurEffectParam(float dx, float dy);   // 计算偏移数组及权重数组private:    CD3DEffect* m_pBloomExtractEffect;  // Bloom依次用到的三个特效    CD3DEffect* m_pGaussianBlurEffect;    CD3DEffect* m_pBloomCombineEffect;private:    CTexture2D*        m_pResolveTarget;   // 原始贴图    CTexture2D*        m_pTexture1;        // 模糊贴图    CTexture2D*        m_pTexture2;        // 临时模糊贴图    IDirect3DSurface9* m_pResolveSurface;  // 原始贴图渲染表面    IDirect3DSurface9* m_pSurface1;        // 模糊贴图渲染表面    IDirect3DSurface9* m_pSurface2;        // 临时贴图渲染表面    IDirect3DSurface9* m_pOriSurface;      // 初始渲染表面private:    BloomParam* m_pParam;                  // Bloom参数体};   /*-------------------------------------代码清单:BloomEffect.cpp来自:http://www.cnblogs.com/kenkao-------------------------------------*/#include "StdAfx.h"#include "BloomEffect.h"#include "D3DGame.h"#include "SpriteBatch.h"#include <math.h>extern IDirect3DDevice9*     g_pD3DDevice;extern CSpriteBatch*         g_pSpriteBatch;extern D3DPRESENT_PARAMETERS g_D3DPP;CBloomEffect::CBloomEffect(void){}CBloomEffect::~CBloomEffect(void){}void CBloomEffect::Release(){    ReleaseCOM(m_pBloomExtractEffect);    ReleaseCOM(m_pBloomCombineEffect);    ReleaseCOM(m_pGaussianBlurEffect);    ReleaseCOM(m_pTexture1);    ReleaseCOM(m_pTexture2);    ReleaseCOM(m_pSurface1);    ReleaseCOM(m_pSurface2);}void CBloomEffect::Create(){    if(!LoadContent())        Release();}bool CBloomEffect::LoadContent(){    // 初始化并加载特效    m_pBloomExtractEffect = new CD3DEffect;    m_pBloomCombineEffect = new CD3DEffect;    m_pGaussianBlurEffect = new CD3DEffect;    if( !m_pBloomExtractEffect->LoadEffect("BloomExtract.fx")||        !m_pBloomCombineEffect->LoadEffect("BloomCombine.fx")||        !m_pGaussianBlurEffect->LoadEffect("GaussianBlur.fx"))    {        return false;    }    // 获得渲染表面    if(!GetSurfaces())    {        return false;    }    return true;}bool CBloomEffect::GetSurfaces(){    // 初始化纹理并获得渲染表面    m_pResolveTarget = new CTexture2D;    m_pTexture1 = new CTexture2D;    m_pTexture2 = new CTexture2D;    if( !m_pResolveTarget->CreateRenderTarget(g_D3DPP.BackBufferWidth,g_D3DPP.BackBufferHeight)||        !m_pResolveTarget->GetRenderSurface(&m_pResolveSurface))    {        return false;    }    if( !m_pTexture1->CreateRenderTarget(g_D3DPP.BackBufferWidth,g_D3DPP.BackBufferHeight)||        !m_pTexture1->GetRenderSurface(&m_pSurface1))    {        return false;    }    if( !m_pTexture2->CreateRenderTarget(g_D3DPP.BackBufferWidth,g_D3DPP.BackBufferHeight)||        !m_pTexture2->GetRenderSurface(&m_pSurface2))    {        return false;    }    return true;}void CBloomEffect::Begin(){    // 暂存原始渲染表面    g_pD3DDevice->GetRenderTarget(0, &m_pOriSurface);    // 设定后台渲染表面    g_pD3DDevice->SetRenderTarget(0, m_pResolveSurface);    g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);}// Begin及End之间绘制原始场景,则得到原始场景贴图m_pResolveTargetvoid CBloomEffect::End(){    // 绘制后台场景    PostScene();    // 还原渲染表面    g_pD3DDevice->SetRenderTarget(0, m_pOriSurface);}void CBloomEffect::PostSurface(CTexture2D* pTexture, IDirect3DSurface9* pSurface, CD3DEffect* pEffect){    // 设定后台渲染表面    g_pD3DDevice->SetRenderTarget(0, pSurface);    g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_RGBA(100,149,237,255), 1.0f, 0);    // 应用特效绘制纹理到后台渲染表面    g_pSpriteBatch->Begin(SPRITEBLENDMODE_NONE, pEffect);    g_pSpriteBatch->Draw(pTexture, D3DXVECTOR2_ZERO);    g_pSpriteBatch->End();}void CBloomEffect::PostScene(){    // Bloom第1步:    m_pBloomExtractEffect->GetEffect()->SetFloat("BloomThreshold",m_pParam->_BloomThreshold);    PostSurface(m_pResolveTarget,m_pSurface1,m_pBloomExtractEffect);    // Bloom第2步:    SetBlurEffectParam(1.0f / (float)g_D3DPP.BackBufferWidth, 0);    PostSurface(m_pTexture1,m_pSurface2,m_pGaussianBlurEffect);    // Bloom第3步:    SetBlurEffectParam(0, 1.0f / (float)g_D3DPP.BackBufferHeight);    PostSurface(m_pTexture2,m_pSurface1,m_pGaussianBlurEffect);}void CBloomEffect::DrawScene(){    // 设定BloomCombine特效参数,控制原始场景m_pResolveTarget及模糊场景m_pTexture1的混合比例    m_pBloomCombineEffect->GetEffect()->SetFloat("BloomIntensity",m_pParam->_BloomIntensity);    m_pBloomCombineEffect->GetEffect()->SetFloat("BaseIntensity",m_pParam->_BaseIntensity);    m_pBloomCombineEffect->GetEffect()->SetFloat("BloomSaturation",m_pParam->_BloomSaturation);    m_pBloomCombineEffect->GetEffect()->SetFloat("BaseSaturation",m_pParam->_BaseSaturation);    m_pBloomCombineEffect->GetEffect()->SetTexture("BaseTexture",m_pResolveTarget->GetTexture());    // Bloom第4步:    g_pSpriteBatch->Begin(SPRITEBLENDMODE_NONE, m_pBloomCombineEffect);    g_pSpriteBatch->Draw(m_pTexture1, D3DXVECTOR2_ZERO);    g_pSpriteBatch->End();}void CBloomEffect::SetBlurEffectParam(float dx, float dy){    // 按场景尺寸计算偏移数组及权重数组(高斯模糊固定计算公式)    D3DXHANDLE weightsParameter, offsetsParameter;    int sampleCount = 15;    weightsParameter = m_pGaussianBlurEffect->GetEffect()->GetParameterByName(0,"SampleWeights");    offsetsParameter = m_pGaussianBlurEffect->GetEffect()->GetParameterByName(0,"SampleOffsets");    float sampleWeights[15];    float sampleOffsets[30];    sampleWeights[0] = ComputeGaussian(0);    sampleOffsets[0] = 0.0f;    sampleOffsets[1] = 0.0f;    float totalWeights = sampleWeights[0];    for (int i = 0; i < sampleCount / 2; i++)    {        float weight = ComputeGaussian(i + 1);        sampleWeights[i * 2 + 1] = weight;        sampleWeights[i * 2 + 2] = weight;        totalWeights += weight * 2;        float sampleOffset = i * 2 + 1.5f;        D3DXVECTOR2 delta = D3DXVECTOR2(dx, dy) * sampleOffset;        sampleOffsets[i * 4 + 1] = delta.x;        sampleOffsets[i * 4 + 2] = delta.y;        sampleOffsets[i * 4 + 3] = -delta.x;        sampleOffsets[i * 4 + 4] = -delta.y;    }    for (int i = 0; i < sampleCount; i++)    {        sampleWeights[i] /= totalWeights;    }    // 将计算结果传递到GaussianBlur特效    m_pGaussianBlurEffect->GetEffect()->SetFloatArray(weightsParameter,sampleWeights,sampleCount);    m_pGaussianBlurEffect->GetEffect()->SetFloatArray(offsetsParameter,sampleOffsets,sampleCount*2);}float CBloomEffect::ComputeGaussian(float n){    // 高斯参数计算公式    float theta = m_pParam->_BlurAmount;    return (float)((1.0 / sqrt(2 * MATH_PI * theta)) *        exp(-(n * n) / (2 * theta * theta)));}   该类共产生了3个渲染表面,并在渲染过程中发生了相互叠加,嗯…有点混乱… 我们不妨来看一看每个步骤所得到的渲染效果,而后再针对4个步骤进行分析。如下是我在渲染过程中提取的效果图:


有了这个流程图,大家的思路是不是清晰了一些呢?下面,大家结合这个流程图来分析各个步骤: 第一步: 应用BloomExtract特效提取原始场景贴图m_pResolveTarget中较明亮的颜色绘制到m_pTexture1贴图中(m_pResolveTarget--->m_pTexture1) 第二步: 应用GaussianBlur特效,在m_pTexture1贴图基础上进行横向高斯模糊到m_pTexture2贴图(m_pTexture1--->m_pTexture2) 第三步: 再次应用GaussianBlur特效,在横向模糊之后的m_pTexture2贴图基础上进行纵向高斯模糊,得到最终的模糊贴图m_pTexture1(m_pTexture2--->m_pTexture1) 注意:此时,m_pTexture1贴图即为最终的模糊效果贴图 如果大家不明白高斯模糊的内部原理,可以参看老师为大家翻译的这篇文章:http://shiba.hpe.sh.cn/jiaoyanzu/WULI/showArticle.aspx?articleId=518&classId=4 第四步: 应用BloomCombine特效,叠加原始场景贴图m_pResolveTarget及两次模糊之后的场景贴图m_pTexture1,从而实现发光效果(m_pResolveTarget+m_pTexture1) 怎么样?大家明白了吗?呵呵~   我们来看主体代码: /*-------------------------------------代码清单: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效果:





原创粉丝点击