Niagara_Advanced内容示例 1.3 Communicate with External Render Targets
粒子效果
场景中有一个纹理和一个模型(应用了Unreal Engine 4的logo),但是没有Niagara粒子的标识符。这次展示出来的是一个Actor蓝图类,里面包含了两个组件,UNiagaraComponent和StaticMeshComponent,分别对应了我们看见的纹理和模型。
Actor蓝图类的构造脚本(Construction Script)里,首先创建Render Target 2D(256*256),然后将这个返回值设置为Niagara中一个变量(Variable)的引用,这个变量名字是TextureRenderTargetObject;随后为我们的StaticMesh(是一个平面)创建动态材质实例,最后再以Render Target 2D的值作为材质实例中纹理参数的值。
这里执行的操作其实就是将Render Target 2D作为外部变量传入Niagara系统(之前都是在Niagara内部创建Render Target 2D,而这里是要让Niagara内部创建的Render Target 2D引用外部创建的这个),在Niagara系统里对它进行一顿操作,再把用一个材质把操作过后的Render Target 2D在静态网格体上显示出来。
我们打开引用的Niagara System来看看内部发生了什么。
Niagara蓝图部分
可以看到,发射器部分和之前1.2中的例子在结构上非常相似,都是用Emitter级别的属性进行渲染。在Simulation Stage里,亦是三个阶段:Fill Grid with Texture,Blur Grid,Fill Render Target with Grid。其中Blur Grid是对纹理(Gird中的数据)的模糊化处理。
效果实现分析
前面说过,Actor蓝图类在Niagara外部创建了一个Render Target 2D(256*256),并将返回值传入Niagara系统中的变量TextureRenderTargetObject。这个变量是我们自己创建的,位于USER命名空间下的一个只读的属性,所以我们才需要用一个Render Target 2D作为接口,从而可编辑其中的值。需要注意的是,Niagara里创建的这个Render Target 2D尺寸是512,与传入的尺寸不同,Niagara会自动做这个适应性的调整(即以512为准)。
Fill Grid with Texture,用纹理数据填充Grid2D Collection。值得注意的是,这里的Emitter Reset Only勾选,意味着这个阶段只会在每次Emitter重置之后才会运行,也就不会让这里的采样结果在后续干扰模糊操作的显示。
Execution Index to Unit构建UV,乘以1.5将范围拉伸到01.5(原先采1的跑去采1.5了,原先采0.66的跑来采1了),减去0.25范围下降为-0.251.25(最原先采1到跑去采1.25了,最原先采0.83的跑来采1了),再Clamp一下取到0~1(掐头去尾可以吃了,最原先采0.83的跑去采1了,最远先采0.16的跑来采0了),这样相当于对纹理进行了缩小(可以理解成一张图片,画框大小不变,你把它从中心缩小,从中心用画框截取)。之后再作一个灰度处理,得到两个float值(一个代表RGB,一个代表A,即透明度值),存储在该Grid2D Collection的属性中(次级属性,命名空间是STACKCONTENT)。
未缩小的画和缩小的画(画框大小不变)。
Blur Grid,是对纹理进行的模糊处理。我们先看看这段HLSL的代码各个输入:Blurred Grid即是Grid2D Collection,TickCount是系统的帧计数,Unit是用来描述当前正在处理Grid2D Collection上的哪一个Cell,Index X和Index Y分别是当前整个Cell的横纵Index,dxdy是横向宽度和纵向长度的倒数,StageIterations代表了当前所处的迭代数。
细看HLSL代码片段,我尽可能得添加了注释(中文部分)
//每次迭代进来要重新初始化这两个值
OutputUnitGrid = float2(0,0);
OutputBlurGrid = float2(0,0);#if GPU_SIMULATION//一些局部变量(作用域就是这个片段)
float2 Offsets = float2(0.5, -0.5);
StageIterations += 1;//
float2 Outputs[4];
float2 Taps[4];
float2 CornerTap;//是对前一帧的值进行采样,即取到Grid2D Collection前一帧的FloatPlusAlpha属性值,怎么采呢?根据Unit传入的位置信息,最后输出到OutputUnitGrid
Grid2DCollection.SampleGridVector2Value<Attribute=FloatPlusAlpha>(Unit, OutputUnitGrid);//就是(1/512,1/512) * StageIterations
// For each iteration, reach a little further out to neighboring texels
CornerTap = dxdy * StageIterations;//随着迭代层数的增加,StageIterations越来越大,这四个位置的Taps值也会越来越大(意味着越来越深/长/距离采样点越远)//左上角,(1/512,1/512) * StageIterations * (-0.5,-0.5)
Taps[0] = CornerTap * Offsets.yy;
//右上角,(1/512,1/512) * StageIterations * (0.5,-0.5)
Taps[1] = CornerTap * Offsets.xy;
//左下角,(1/512,1/512) * StageIterations * (-0.5,0.5)
Taps[2] = CornerTap * Offsets.yx;
//右下角,(1/512,1/512) * StageIterations * (0.5,0.5)
Taps[3] = CornerTap * Offsets.xx;// Sample our four corners, average the samples.
//向Grid2D Collection中正在进行的采样点的四个边角进行采样(FloatPlusAlpha),得到的值输出到Output里
Grid2DCollection.SampleGridVector2Value<Attribute=FloatPlusAlpha>(Unit+Taps[0], Outputs[0]);
Grid2DCollection.SampleGridVector2Value<Attribute=FloatPlusAlpha>(Unit+Taps[1], Outputs[1]);
Grid2DCollection.SampleGridVector2Value<Attribute=FloatPlusAlpha>(Unit+Taps[2], Outputs[2]);
Grid2DCollection.SampleGridVector2Value<Attribute=FloatPlusAlpha>(Unit+Taps[3], Outputs[3]);//取四个边角采样值的平均值,输出到OutputBlurGrid里
OutputBlurGrid += (Outputs[0]+Outputs[1]+Outputs[2]+Outputs[3]) / 4;
if (TickCount <= 1)
{//TickCount是系统的计时器,
}
else
{
OutputBlurGrid = OutputUnitGrid;
}//如果是从点下Save/Apply那一刻起的第一帧,以OutputBlurGrid(总共走8个循环后)设置FloatPlusAlpha属性;后面的每帧输出OutputUnitGrid(对第八帧的FloatPlusAlpha采样,是经历了8层模糊循环后的结果),以保持一个恒定的模糊度。
//这也就是为什么Fill Grid with Texture要勾选Emitter Reset Only,否则如果Fill Grid with Texture每帧更新的话,会刷掉已近写过的FloatPlusAlpha值,就意味着要输出未被模糊的结果
Grid2DCollection.SetVector2Value<Attribute=FloatPlusAlpha>(IndexX, IndexY, OutputBlurGrid);#endif
Fill Render Target with Grid,将Grid2D Collection的数据写入到Render Target 2D里。
最后再通过材质参数绑定写入到材质纹理中(这样就得到了最开始那副效果图中左侧的那个纹理(实际上Niagara Emitter级的Sprite粒子))。
而右侧的那个StaticMesh上的纹理则是通过读到其上的材质纹理参数,再用Render Target对这个参数进行赋值。还记得开局Actor蓝图中的那两个节点吗(下图)?此时蓝图中创建的Render Target已经经过了Niagara System里的一些列计算并赋了模糊化后的值,这些值又要传入NiagaraRT这个参数里。
材质中的这个参数的B值决定了这个材质的Emissive Color和顶点的偏移值,所以才会有凸起的效果。
总结
本例中涉及的知识点相当得驳杂,当时我还是尽力将其全部梳理了出来(蓝图和Niagara数据传递,材质,模糊卷积算法(不算是完全的卷积),系统数据更新等等)。其中甚至一些点我之前都没有了解过,比如说我在TickCount的作用上纠结了比较久。最后还是多个概念的综合理解、结合蓝图和代码的上下文才将流程梳理通畅。
Niagara_Advanced内容示例 1.3 Communicate with External Render Targets相关推荐
- Niagara_Advanced内容示例 1.2 Advect Grid 2D Collection
粒子效果 这个例子主要由三部分组成:上边悬于空中.始终面向相机的Unreal Engine 4的黑白Logo,它还会受到某种噪声的影响向四周扭曲:地面上贴着的两张纹理图片,左侧类似于一张迷宫图,但是斜 ...
- Niagara_Advanced内容示例 1.5 Skeletal Mesh Reproduction
粒子效果 中心是一个人物模型,似乎也是由粒子贴片而成的.此外还有一些发光粒子,在无规则运动,不时会撞击到模型上,导致模型裂开成一些粒子.这些散落的粒子被撞击裂开后,会逐渐恢复原先在模型上的位置. Ni ...
- js动态改变下拉菜单内容示例 .
<HTML><HEAD><TITLE>动态改变下拉菜单内容示例</TITLE></HEAD><SCRIPT LANGUAGE=java ...
- python用方括号提取字符中的数值_Python使用re模块正则提取字符串中括号内的内容示例...
Python使用re模块正则提取字符串中括号内的内容示例 本文实例讲述了Python使用re模块正则提取字符串中括号内的内容操作.分享给大家供大家参考,具体如下: 直接上代码吧: # -*- codi ...
- python爬去新浪微博_Python爬虫爬取新浪微博内容示例【基于代理IP】
Python爬虫爬取新浪微博内容示例[基于代理IP] 发布时间:2020-09-07 10:08:14 来源:脚本之家 阅读:120 本文实例讲述了Python爬虫爬取新浪微博内容.分享给大家供大家参 ...
- Python使用re模块正则提取字符串中括号内的内容示例
Python使用re模块正则提取字符串中括号内的内容示例 这篇文章主要介绍了Python使用re模块正则提取字符串中括号内的内容,结合实例形式分析了Python使用re模块进行针对括号内容的正则匹配操 ...
- 学习Cascade粒子系统:观察内容示例所展示的特性
目标 内容示例中有展示粒子特效的场景: 目标是观察场景中几个范例想要展示的是粒子系统的哪个功能,并尝试了解如何操作.需要注意的是:由于并没有实际用资源复现一遍,所以很可能有疏漏之处,即有些效果的实现还 ...
- python修改html内容_详解Python利用Beautiful Soup模块修改内容示例代码
Beautiful Soup是一个可以从HTML或XML文件中提取数据的Python 库.它能够通过你喜欢的转换器实现惯用的文档导航.查找.修改文档的方式.他还能够修改HTML/XML文档的内容.这篇 ...
- Niagara内容示例 4.3 Mesh Orientation vs. Rotational Force
粒子效果 有三竖列的粒子,都在绕某个轴进行旋转.根据下面的文本提示来看,应该是每堆粒子的旋转操作的赋予方式不同,分别是直接操作网格体朝向(Mesh Orientation),操作旋转的速度(Rotat ...
最新文章
- HashMap和HashTable区别
- Cervical Cancer mechanism
- git Rebase 变基 教程
- 关于jquery-Validate
- SGU 201 Non Absorbing DFA (DP)
- TypeScript 的存在削弱了 JavaScript 生态系统?
- java ssm网上超市购物管理系统
- 英语背单词软件需求分析
- wps参考文献乱码。英文的行间距怎么调?
- Office中快速删除批注
- 在Ubuntu上安装Azure DevOps self-hosted agent
- 备案域名服务器DNS修改,未备案域名也可以用高防CDN加速
- JavaScript常用的字符串操作对象方法
- 龙芯1c300b开发语言,龙芯 1C0300B 主控芯片已成功进入激光打印机市场
- 数字逻辑设计基础(何建新)第三章
- svn不小心ignore了怎么办
- 中国书法艺术会消亡吗?
- SAP FICO 基础(1)中日双语
- sublime text3 多窗口打开设置
- 404(not found)错误
热门文章
- 微积分:闭区间上 有界、可积、连续、可导 的强弱关系
- Android Studio中对res、AndroidManifest、buil.gradle文件夹的讲解
- spark RDD 打印元素
- 小木虫内蒙古科技大学计算机,2019年内蒙古科技大学招收考研调剂(二)
- 个人计算机是国产芯片,全球最纯国产PC诞生!所有芯片/系统都是国产
- 中南大学复试上机:1009: 安全路径
- Code Project精彩系列(转)
- 数据结构与算法笔记:哈希表——力扣389
- 2021年中国学前教育行业发展现状及未来发展趋势分析:毛入学率达88.1%[图]
- 开发团队建设与管理的一些心得