【转载】UE4 (自定义节点)高斯模糊后处理

1,543 阅读2分钟

原文链接:UE4 高斯模糊后处理

去饱和测试

自定义 Desaturate 节点中的代码如下

return dot(SceneTexture,float3(0.3,0.59,0.11));

材质中的节点连接如下

image.png

最终效果如下

image.png

高斯模糊

首先我们需要将 SceneTexture 节点转换为 HLSL,为了方便我们后续的操作,查看着色器代码可以看到 HLSL 代码

SceneTextureLookup(GetDefaultSceneTextureUV(Parameters, 14), 14, false);

SceneTextureLookup

float4 SceneTextureLookup(float2 UV, int SceneTextureIndex, bool Filtered)

三个参数的含义如下

  • uv: 采样UV
  • SceneTextureIndex: 要采样的贴图 Index
  • Filtered: 是否需要双线性过滤

UE4 的相关贴图 Index 如下所示

image.png

这时候如果我们直接断开 SceneTexture,并修改 Gaussain.usf

return SceneTextureLookup(GetDefaultSceneTextureUV(Parameters, 8), 8, false);

报错了,是因为 SceneTextureLookup 需要引入头文件才能使用,所以我们需要连接 SceneTexture 节点用于引入头文件。

image.png

恢复正常

image.png

开始

首先确定好高斯模糊公式,接受 -1 到 1 的输入,输出 0 到 1 的值。可以看出和平均模糊不同,距离当前像素越远,那么对中心的越小

image.png

image.png

在结构体中自定义函数

struct FunctionStruct
{
    //计算一维高斯模糊
    float Cal_1DGaussian(float x)
    {
        return exp(-0.5f * pow(3.141 * x, 2));
    }
};

初始化数据

FunctionStruct FS;

//需要获得的场景贴图 index
static const int SceneTextureID = 14;
//纹素大小,比如一张 512 X 512 大小的纹理,那么纹素大小为(1/512)
//用于 UV 的偏移
float2 TexelSize = View.ViewSizeAndInvSize.zw;
//获取当前像素的 UV
float2 UV = GetDefaultSceneTextureUV(Parameters, SceneTextureID);
//用于存储累积的颜色
float3 PixelSum = float3(0, 0, 0);
//累积权重值
float WeightSum = 0;

用两个 for 循环来进行水平和垂直的模糊处理

//水平与垂直模糊
for (int x = -BlurRadius;x<=BlurRadius;x++)
{
    for (int y = -BlurRadius;y<=BlurRadius;y++)
    {
        //计算偏移的UV
        float2 offsetUV = UV + float2(x,y)*TexelSize;
        //采样偏移后的贴图颜色
        float3 PixelColor = SceneTextureLookup(offsetUV,SceneTextureID,false).rgb;
        //计算采样像素的权重,/Raduis 的原因是为了限制输入范围为 -1到1
        float weight = FS.Cal_1DGaussian(x / BlurRadius) * FS.Cal_1DGaussian(y / BlurRadius);
        //累加颜色
        PixelSum += PixelColor*weight;
        //累加权重值
        WeightSum += weight;
    }
}

//返回加权平均值
return PixelSum / WeightSum;

蓝图传递 BlurRadius,其实就是卷积核大小范围,比如传入了 BlurRadius2,那么卷积核大小为 5x5

image.png

最终结果

image.png