当前位置:   article > 正文

在UE4中创建高斯模糊后期材质_ue4高斯模糊材质

ue4高斯模糊材质

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

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的文件。

unreal engine shadersunreal engine shaders

unreal engine shaders

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

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

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

Description:命名你的自定义节点

Inputs:输入接口

 

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

比如你写了如下代码:

return 1;

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

  1. MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)
  2. {
  3. return 1;
  4. }

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

  1. return 1;
  2. }
  3. float MyGlobalVariable;
  4. int MyGlobalFunction(int x)
  5. {
  6. return x;

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

  1. MaterialFloat3 CustomExpression0(FMaterialPixelParameters Parameters)
  2. {
  3. return 1;
  4. }
  5. float MyGlobalVariable;
  6. int MyGlobalFunction(int x)
  7. {
  8. return x;
  9. }

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

 

 

高斯模糊公式

\LARGE f(x) = e^{-0.5(\pi x)^{2}

 

函数的表现形式如下:

unreal engine shaders

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

 

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

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

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

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

unreal engine shaders

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

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

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

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

unreal engine shaders

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

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

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

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

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

unreal engine toon outline

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

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

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

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

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

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

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

 

Custom Node的局限性

  • 访问限制

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

  • 引擎版本兼容性

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

  • 优化

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/107528
推荐阅读
相关标签
  

闽ICP备14008679号