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

2023-11-14

https://www.cnblogs.com/kenkao/archive/2011/08/25/2153752.html

Bloom,又称“全屏泛光”,是大名鼎鼎的虚幻3游戏引擎中最通用的后期特效技术~

Bloom特效的实现主要依赖于PostProcess框架,即实时绘制当前场景到一后台渲染表面,而后针对其对应贴图进行像素级渲染~

大家还记得我们之前实现的水面效果中的反射和折射贴图吗?此即为PostProcess的典型应用,与Bloom特效有异曲同工之妙。

下面,我们就来揭秘这个Bloom特效的实现流程~

本节我们实现的Bloom特效,在流程上总共分为4步:

1.提取原场景贴图中的亮色;

2.针对提取贴图进行横向模糊;

3.在横向模糊基础上进行纵向模糊;

4.所得贴图与原场景贴图叠加得最终效果图。

所用到的Shader主要有三个,分别对应如上4个步骤中的第1步、第2、3步和第4步。我们来看源代码:

 

BloomExtract.fx

 

GaussianBlur.fx

 

BloomCombine.fx

 

三个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();          // 关闭Bloom
public:
    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

 

该类共产生了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

 

对Bloom参数体各个成员变量数值进行交叉组合,则我们可以得到一系列不同的Bloom效果:

 

 

 

 

还在羡慕那些专业游戏中美轮美奂的后期特效吗?现在我们也有能力实现了~ 大家赶快动手尝试一下吧 ^ ^

以上,谢谢~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Direct3D轮回:游戏特效之全屏泛光(Bloom) 的相关文章

  • 【漏洞复现】CVE-2021-32682 elFinder ZIP 参数与任意命令注入

    1 Vulhub启动环境 2 查看端口号 3 输入网址 ip 8080 打开网页 4 先创建一个普通的文本文件1 txt 5 然后右键这个文件 对其进行打包 打包后的文件命名为2 zip 并同时进行抓包 获取1 txt的base64编码 6
  • 成员变量与局部变量

    一 成员变量 在类中定义 用来描述对象将要有什么 二 局部变量 在类的方法中定义 在方法中临时保存数据 三 成员变量和局部变量的区别 1 作用域不同 局部变量的作用域仅限于定义它的方法 成员变量的作用域在整个类内部都是可见的 2 初始值不同
  • 【总结】爬虫流程

    爬虫流程 根据所需数据确定爬虫网页 首先考虑resquests 需要提前导入 1 若是文本数据 用response text 2 若是下载视频 图片 音频 用response content 3 若是json接口 用response jso
  • CSS整体界面设计

  • RBAC简介

    RBAC BAC基于角色的访问控制 RBAC认为权限授权的过程可以抽象地概括为 Who是否可以对What进行How的访问操作 RBAC简介 基于角色的权限访问控制模型 在RBAC模型里面 有3个基础组成部分 分别是 用户 角色和权限 RBA
  • Java多线程异常处理

    文章目录 一 线程中出现异常的处理 1 线程出现异常的默认行为 2 setUncaoughtExceptionHandler 方法处理异常 3 setDefaultUncaoughtExceptionHandler 方法进行异常处理 二 线
  • vue3.0的安装配置(含node和npm的配置)

    文章目录 一 下载Node js 二 配置环境变量 三 配置NPM下载存放目录 文件不用事先创建 四 NPM设置镜像仓库 淘宝镜像仓库 五 vue cli脚手架创建Vue3 0项目 一 下载Node js 下载地址 二 配置环境变量 在CM
  • SpringBoot自定义错误页面 与 全局异常处理

    Springboot中需要自定义错误页面 一 使用Springboot默认的配置 1 在templates下穿件一个目录 error 2 在error目录下创建相应的对应的文件即可 如 400 html 500 html 二 自定义错误页面
  • 南大和中大“合体”拯救手残党:基于GAN的PI-REC重构网络,终于有救了

    对于喜欢画画的你来说 总是画得七零八落 不堪入目 但现在 有一种方法可以让你像专业人士那样 让你的糟糕画作变成一副完美的作品 南京大学和中山大学的三位研究人员发布的最新论文中 提出了一种具有边缘和色域的渐进式图像重构网络 PI REC 这是
  • 系统辨识——最小二乘法

    基本原理 数学推导 最小二乘法是通过输入数据与输出数据来拟合已知结构的函数关系 也就是说已知二者的函数关系 通过最小二乘法估计函数的相关参数 假设 x y x y x y存在以下函数关系 但是在实际中 测量数据时存在测量误差或者噪声影响 故
  • pthread 的几个结构体

    Copyright C 2002 2003 2004 2005 2006 2007 Free Software Foundation Inc This file is part of the GNU C Library Contribute
  • Google人机认证解决方法

    针对Chrome浏览器 下载gooreplacer 下载地址1 下载地址2 安装 gooreplacer crx Chrome无法从该网站添加应用 扩展程序和用户脚本 将 crx后缀改为 rar 之后开发者模式安装 重定向网址 重定向 将网
  • cad添加自己线性_创建cad线型的两种方法(线型文件和linetype) - CAD自学网

    作图过程中 我们最常见的线型是实线 虚线 点划线 有的时候这些基本线型可能满足不了你的需求 CAD也有自带的特殊线型 比如 HW 这种自带文字的线型 但你想要的确实 X 那么这便涉及到新线型的建立 建立新线型有两种方法 直接修改线型文档和通
  • CSTrack: Rethinking the competition between detection and ReID in Multi-Object Tracking

    CSTrack Rethinking the competition between detection and ReID in Multi Object Tracking 论文链接 https arxiv org abs 2010 121
  • 什么是标称属性?什么是二元属性?什么是序数属性?

    什么是属性 属性是一个数据字段 表示数据对象的一个特征 一个属性的类型由该属性可能具有的值的集合决定 标称属性 标称意味着 与名称有关 标称属性的值是一些符号或者是事物的名称 每个值代表某种类别 编码或者状态 尽管标称属性有数值 但是不能把
  • 全面剖析《自己动手写操作系统》第四章--FAT12文件系统

    一 FAT12 FAT12是DOS时代就开始使用的文件系统 File System 直到现在仍然在软盘上使用 FAT12软盘的被格式化后为 有两个磁头 每个磁头80个柱面 磁道 每个柱面有18个扇区 每个扇区512个字节空间 所以标准软盘的
  • Android Google Maps 开始

    由于工作需要 最近对Android的各大地图进行了试用 其中有Google地图 百度地图 高德地图 还有开源的OSM 在使用Google地图的时候 官网流程写的非常清楚 但是其中也遇到一些问题 这里我将我的流程写出来 方便他人 这个是官方安
  • 【C++】Boost::circular_buffer——循环缓冲区

    参考 Boost circular buffer 循环缓冲区 一 概述 Boost Circular buffer维护了一块连续内存块作为缓存区 当缓存区内的数据存满时 继续存入数据就覆盖掉旧的数据 它是一个与STL兼容的容器 类似于 st

随机推荐

  • golang json性能分析详解

    原文地址 https www jb51 net article 135264 htm json格式可以算我们日常最常用的序列化格式之一了 Go语言作为一个由Google开发 号称互联网的C语言的语言 自然也对JSON格式支持很好 下面这篇文
  • 基于决策树算法构建员工离职预测模型

    1 1背景介绍 每一个公司都会面临着人才管理的问题 而许多企业在发展中辛苦培养发展起来的技术人才 却不断流失 那么 如何调整公司管理制度 才能最大化保证员工的留任与能力发展 从而促进公司业务持续增长呢 本课程介绍收集了某公司人才流失各方面的
  • GLSL #define GL_SPIRV 100说明

    GLSL define GL SPIRV 100说明 版权 hankern https blog csdn net hankern article details 90690297 Standard Portable Intermediat
  • 【学习笔记】POST和GET的区别

    吃水不忘挖井人系列之 https mp weixin qq com s N2GStE2ksWUO yzIETTcQQ 在开撸之前吗 让我们先看一下标准答案长什么样子 w3school GET 对比 POST 标准答案很美好 但是在面试的时候
  • Chrome 快捷键大全

    从2013年开始使用 Chrome 浏览器 简洁好用 以前是用来专门科学上网 后来工作发现 Chrome 是开发必备 今天整理了一下Chrome的快捷键 有些挺常用 熟悉掌握快捷键 甚至不要鼠标就可以装逼了 标签和窗口 同个窗口新建标签 C
  • 【Linux】软件安装&卸载

    目录 1 notepad plus plus 2 notepadqq 3 pycharm 4 Anaconda 5 vscode 6 android ndk 7 搜狗输入法 8 卸载vmware 9 GIMP 10 git 11 llvm
  • JAVA 写Excel附件 每天定时发送邮件

    JAVA 写Excel附件 每天定时发送邮件 http hi baidu com star850323 blog item 63c5750f520e05ec37d1228d html http hi baidu com star850323
  • HBuilderX 最新安装使用教程,附详细图解,持续更新

    HBuilderX 安装使用教程 HBuilderX是HBuilder的升级版 它是是DCloud 数字天堂 推出为前端开发者服务的通用IDE 或者称为编辑器 HBuilderX的功能从下图可以直观的了解个大概 官网地址 https ask
  • Java基础总结之各个模块重要知识点

    一 对象模块 一 初始化 1 对this super 构造函数 构造代码块 静态代码块总结 this 代表当前对象 也就是所在函数所属对象的引用 this对象后面加 调用的是对象的成员变量和方法 this say this对象后面加 调用的
  • 毕业设计-基于机器视觉的甘蔗茎秆识别方法-OpenCV

    目录 前言 课题背景和意义 实现技术思路 一 总体思路 二 图像处理 三 甘蔗识别 四 结 语 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精力 近几
  • OpenCV中的图像处理

    颜色空间转换 1 基本读写操作 import cv2 import numpy as np img cv2 imread MyPic png cv2 IMREAD GRAYSCALE print img shape cv2 imwrite
  • winusb —— 不再为你的usb设备编写驱动

    blog csdn net lanmanck 曾几何时我们找工作还发现有个驱动工程师职位 月薪也不低 没接触过的人代码压根看不懂 今天可好了 如果不太追求差异化 不用驱动也能让系统与USB设备通信了 Linux就不说了 libusb很好用
  • nginx服务器启动、停止、重启

    启动nginx nginx c path to nginx conf 关闭nginx nginx s stop 快速停止nginx quit 完整有序的停止nginx 重启nginx nginx s reload 修改配置后重新加载生效 n
  • org.springframework.validation.BindException: org.springframework.

    错误信息 org springframework validation BindException org springframework validation BeanPropertyBindingResult 2 errors Fiel
  • Vue实现在页面上添加返回顶部按钮(按钮固定在页面右下角)

    从网站上下载按钮图片 我在图精灵上下载图片到项目src文件夹下的assets文件夹 并命名为topButton png 可以用本地的图片编辑软件 如画图 将按钮图片设置为像素50 50 在App vue文件夹下引入图片 为click事件设置
  • Linux内存宏,linux内核驱动宏定义

    宏符号linux内核中绝大多数初始化函数和变量都利用了各式各样的宏符号 形如 static int init pci porc init void static char version devinitdata drv name modul
  • Eclipse ADT中的logcat不显示解决方法

    1 在Eclipse界面中找到DDMS 然后找到device选项卡 在这个选项卡中选择reset adb 如果不行尝试方法2 2 不用关闭eclipse和模拟器 在Android SDK的tools目录下有个 ddms bat 批处理文件
  • index_join:

    index join index join顾名思义是对index进行关联 oracle通过hash index join的方式实现了避免对表的访问 所有的数据都从索引中直接获得 它不受查询条件影响 可以是唯一索引 也可以是多列索引 SELE
  • [Unity2D/3D]Particle System粒子系统/以实现烟雾效果为例

    Unity3D Particle System粒子系统 首先看一下效果 1 创建一个Particle System 右键Effects gt Particle System Pause暂停播放粒子效果 Restart重新播放粒子系统 Sto
  • Direct3D轮回:游戏特效之全屏泛光(Bloom)

    https www cnblogs com kenkao archive 2011 08 25 2153752 html Bloom 又称 全屏泛光 是大名鼎鼎的虚幻3游戏引擎中最通用的后期特效技术 Bloom特效的实现主要依赖于PostP