本篇教程来自国外一位大佬的文章,在这里我会总结下制作过程,有些不重要的地方可能会直接跳过。原文链接:

https://www.raywenderlich.com/57-unreal-engine-4-custom-shaders-tutorial

关于如何在custom node中引用.usf文件,还是移步这里:

https://blog.csdn.net/weixin_43369654/article/details/92607776

准备工作

首先在工程文件根目录创建一个Shaders的文件夹,打开shaders文件夹,创建一个名为Gaussian.usf的文件。

新建一个材质球,并把细节面板的Material Domain设置成postprocess。按照如图的方式连接。Round(四舍五入)保证半径总是一个整数。Gaussian Blur(高斯模糊)就是我们本次的重点了,这是一个custom node:

创建好custom node后,看细节面板:

Code:写shader代码的地方,UE4只支持HLSL

Description:命名你的自定义节点

Inputs:输入接口

在custom node里写代码时需要注意的是,并不能按照常规的方法来写。

比如你写了如下代码:

return 1;

编译器会翻译成如下(没有缩进):

MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)
{
return 1;
}

如果你的代码是这样写的:

    return 1;
}float MyGlobalVariable;int MyGlobalFunction(int x)
{return x;

得到的HLSL语法结果将会是:

MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)
{return 1;
}float MyGlobalVariable;int MyGlobalFunction(int x)
{return x;
}

注意开头和结尾处会少两个大括号,务必按照这种方式来写custom node,不然会报错。

高斯模糊公式

函数的表现形式如下:

这是一个简化的一维高斯模糊公式,如图可见它的接收值域为[-1,1],输出值域为[0,1]。

接下来,新建一个custom node并命名为Global,在代码栏里输入下列文本:

    return 1;
}float Calculate1DGaussian(float x)
{return exp(-0.5 * pow(3.141 * (x), 2));

Calculate 1DGaussian():这个函数就是上述一维高斯模糊公式的代码化。

注意Output Type要改成Float4,因为接下来你需要将GlobalSceneTexture相乘,得到如下:

如此一来任何后续的自定义节点都可以使用Global中定义的函数。

打开Gaussian.usf 并将里面的代码替换为下述代码:

static const int SceneTextureId = 14;
float2 TexelSize = View.ViewSizeAndInvSize.zw;  //将偏移量转换到UV空间
float2 UV = GetDefaultSceneTextureUV(Parameters, SceneTextureId);   //当前像素的UV
float3 PixelSum = float3(0, 0, 0);    //将内核(kernel)中每个像素的颜色累加(sum)起来。
float WeightSum = 0;    //将内核中每个像素的权重累加起来。

对于SceneTexture的ID这里有一个对照的列表:

故SceneTextureId = 14 对应的就是Post Process Input 0 了。

关于内核(kernel)的概念会在下一篇文章单独拿出来讲,这里不理解的朋友可以暂时不用管它是什么意思。

紧接着上述代码下面加入两个嵌套的for循环,加入后如下:

static const int SceneTextureId = 14;
float2 TexelSize = View.ViewSizeAndInvSize.zw;                      //将偏移量转换到UV空间
float2 UV = GetDefaultSceneTextureUV(Parameters, SceneTextureId);   //当前像素的UV
float3 PixelSum = float3(0, 0, 0);                                  //将内核(kernel)中每个像素的颜色累加(sum)起来。
float WeightSum = 0;                                                //将内核中每个像素的权重累加起来。for (int x = -Radius; x <= Radius; x++)           //水平方向
{for (int y = -Radius; y <= Radius; y++)       //垂直方向{}
}

其中最外层的for循环是x轴(水平方向)的偏移量,嵌在内部的for循环是y轴(垂直方向)的偏移量。理论上来讲,这个两层嵌套的for循环将会以当前的像素为中心形成一个内核,如下:

不断运动的九宫格网格就是内核(kernel)。

内核的尺寸是2r+1,比如半径(radius)= 2,则内核 = (2 * 2+1)x(2 * 2+1)即 5x5网格。

接下来在内层的for循环里加入以下代码:

float2 Offset = UV + float2(x, y) * TexelSize;           //计算采样像素的相对偏移量并将其转换为UV空间
float3 PixelColor = SceneTextureLookup(Offset, SceneTextureId, 0).rgb;    //通过偏移量对场景纹理进行采样
float Weight = Calculate1DGaussian(x / Radius) * Calculate1DGaussian(y / Radius);    //计算采样像素的加权。为了计算二维的高斯模糊,你需要将两个一维的高斯模糊相乘(multiply),除以(divide)radius是因为简化的高斯模糊公式的值域是[-1,1],所以需要将它们的值归一化。
PixelSum += PixelColor * Weight;          //将加权的颜色添加到PixelSum
WeightSum += Weight;                      //将权重添加给WeightSum

最后,在for嵌套循环外加上返回值:

static const int SceneTextureId = 14;
float2 TexelSize = View.ViewSizeAndInvSize.zw;                      //将偏移量转换到UV空间
float2 UV = GetDefaultSceneTextureUV(Parameters, SceneTextureId);   //当前像素的UV
float3 PixelSum = float3(0, 0, 0);                                  //将内核(kernel)中每个像素的颜色累加(sum)起来。
float WeightSum = 0;                                                //将内核中每个像素的权重累加起来。for (int x = -Radius; x <= Radius; x++)           //水平方向
{for (int y = -Radius; y <= Radius; y++)       //垂直方向{float2 Offset = UV + float2(x, y) * TexelSize;           //计算采样像素的相对偏移量并将其转换为UV空间float3 PixelColor = SceneTextureLookup(Offset, SceneTextureId, 0).rgb;    //通过偏移量对场景纹理进行采样float Weight = Calculate1DGaussian(x / Radius) * Calculate1DGaussian(y / Radius);    //计算采样像素的加权。为了计算二维的高斯模糊,你需要将两个一维的高斯模糊相乘(multiply),除以(divide)radius是因为简化的高斯模糊公式的值域是[-1,1],所以需要将它们的值归一化。PixelSum += PixelColor * Weight;          //将加权的颜色添加到PixelSumWeightSum += Weight;                      //将权重添加给WeightSum}
}return PixelSum / WeightSum;

应用后,调节Radius就可以看到效果了(记得要把该材质赋给PostProcess才能看到效果)。

Custom Node的局限性

  • 访问限制

Custom Node无法访问大部分的渲染管线,例如光照信息和运动方向。

  • 引擎版本兼容性

你在4.19版本写的Custom Node不保证能在4.22也可以继续运行。建议多留意每次更新的官方文档。

  • 优化

这一条可以算作是优点而非局限性了。自定义节点最大的好处就是观赏简洁,不必在打开一个shader的时候发现满屏幕的连线而感到头疼。官方的建议是,如果使用连线的方式很麻烦的时候,可以选择使用自定义节点自己去写。

在UE4中创建高斯模糊后期材质相关推荐

  1. 游戏建模在UE4中创建科幻环境:功率过载(二)

    烘烤阶段 为节省导入Marmoset的时间,使用良好的命名法非常重要.我通常使用Marmoset Quick Loader,通过此工具,我只需要为低多边形模型的每个部分选择一个名称,后缀"_ ...

  2. 在UE4中创建CG动画 How to create a movie in Unreal Engine 4 using Metahuman

    MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:1.55 GB |时长:1h 16m 你会学到什么 如何在 ...

  3. 在UE4中创建受《羞辱》启发的环境

    Laetitia Bertrand谈到了受Dishonored 2启发并在Vertex学校的环境艺术训练营期间创建的她的项目的制作. 1.介绍 嗨,我叫Laetitia Bertrand,我是法国巴黎 ...

  4. [unreal4入门系列之十二] 在UE4中创建非玩家角色(NPC)

    现在我们来创建一些NPC(non-playable characters,非玩家角色).在这个游戏中,当我们靠近NPC时,它们会做出相应的反应. 创建C++类 1) 在UE编辑器中,打开文件-新建C+ ...

  5. 如何在UE4中创建线程

    FRunnable和FRunnableThread方法对于大多数问题来说无疑是一个可行的解决方案. 但是,在创建许多任务时,您可能会达到CPU可以处理的并发上限,此时并发线程实际上会在争用CPU时间时 ...

  6. 在UE4中创建蓝图类,点开蓝图类没有编辑界面

    UE4系列文章目录 文章目录 UE4系列文章目录 前言 一.解决办法 总结 前言 当我们在UE4的内容浏览器中新建了蓝图类,例如AKM_Bullet_BP,第一次点开这个蓝图类一切正常,有编辑窗口: ...

  7. 用Kinect2将人物画面抠图显示在UE4中

    目录 一.目的 1.用Kinect2人物画面抠图显示在UE4中 二.参考 1.固始<三防知识介绍>中的体感项目 三.过程 1.运行效果: 1.版本 1.新建工程:第三人称类型:MyKine ...

  8. ue4 截图_UE4中创建赛博朋克中国城市

    设为星标,不错过任何干货 先点上方" CG自学站"再点右上角" ..."最后设置星标★ CG自学站专注分享国内外CG教程和大师名家推介 专业词汇翻译疏漏之处请理 ...

  9. ue4中面部动画制作视频教程 Facial Animation More In Unreal Engine 4

    ue4中面部动画制作视频教程 Facial Animation & More In Unreal Engine 4 时长4h 包含项目文件 1920X1080 MP4 大小解压后:5.75G ...

最新文章

  1. VMWare常用快捷键
  2. python通过什么来体现逻辑关系_Python语言通过()来体现语句之间的逻辑关系。
  3. 下取整函数的含义_Excel将3.14159取值为3.15或3.1415? 两个函数为你效劳,拿走不谢...
  4. css圆角box(网上流行用b标签)
  5. 使用ExecutorService来停止线程服务
  6. 坚持不放弃,修得好结果。
  7. sql between包括两端吗_SQL大全
  8. VS2010下的多线程窗口
  9. 016 pickle
  10. 6_python基础—循环
  11. 对索引像素格式的图片进行Setpixel(具有索引像素格式的图像不支持SetPixel)解决方案
  12. mahout0.7 示例运行纪实
  13. go 模板(template)的常用基本语法
  14. 解决 eclipse 生成 javadoc 中文乱码的问题
  15. const,readonly字段的取舍!
  16. 冒泡排序(数组排序不用Array.Sort)
  17. 用友文件服务器设置,u8文件服务器如何设置
  18. html 页面加载事件,页面加载事件--DOMContentLoaded
  19. 网易云课堂计算机专业,网易云课堂“计算机专业课程”开课
  20. 代理记账公司如何寻找客户群体,客户群体有那些

热门文章

  1. LocalDateTime运算案例,以及参考网站
  2. git连接github 上传项目到github服务器----这波操作真的很酷
  3. C++写算法|A+B问题
  4. 哈哈日语 学渣的日语N1失败经验谈
  5. openstack neutron
  6. swift Rswift 替换文件 无妄之灾 Build Phases->Copy Bundle Resrces Phase
  7. 在本地安装 godoc
  8. [测试十年]搜狗测试第一年:责任心篇
  9. LeanCloud 推出 10x 程序员专用笔记本
  10. 第一次登录阿里云服务器ECS详解及利用MSTSC,XShell,XFTP进行连接