您当前的位置: 首页 >  ar

开发游戏的老王

暂无认证

  • 1浏览

    0关注

    803博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Unreal Engine 4 手绘风滤镜(Paint Filter)即 桑原滤镜(Kuwahara Filter)教程(上)

开发游戏的老王 发布时间:2021-03-29 20:29:11 ,浏览量:1

原文|《Unreal Engine 4 Paint Filter Tutorial》 作者|Tommy Tran May 1 2018 | 翻译 开发游戏的老王 阅读时长|25分钟 内容难度|入门级 本教程将会教你通过实现桑原滤镜(Kuwahara Filter)让游戏具有手绘风格

文章目录
      • 开始吧
      • 桑原滤镜
      • 桑原滤镜的工作原理
      • 桑原滤镜的例子
      • 创建桑原滤镜
      • 像素抽样
      • 计算平均值和方差

时光流逝,电子游戏的视觉效果越来越好。在这个画面惊艳的游戏层出不穷的时代,让自己的游戏脱颖而出是件很困难的事情。然而有一种方法可以使你的游戏在视觉美学上与众不同,那就是非真实渲染(non-photorealistic rendering)。

非真实渲染的技术范畴非常广,它包含但不仅限于卡通着色,卡通描边以及交叉线。你甚至可以让你的游戏看起来更具手绘风。技术之一就是实现桑原滤镜(Kuwahara Filter)。

要实现桑原滤镜,你将会学到:

  • 如何为多核(Kernel)计算平均值(mean)和方差(variance)
  • 输出具有最小方差的核的平均值
  • 使用索贝尔算子(Sobel)获取像素的局部朝向(local orientation)
  • 基于像素的局部朝向旋转采样核(sampling kernel)

注:本文假定读者已经熟悉Unreal Engine的基础知识。因为本文将使用HLSL,所以你应该熟悉HLSL或至少熟悉一种诸如C#的语言。

本文是Unreal Engine着色器教程四部曲之一:

  • 第一部分: 卡通着色(Cel Shading)
  • 第二部分:卡通轮廓线(Toon Outline)
  • 第三部分:使用HLSL自定义着色器(Custom Shaders Using HLSL)
  • 第四部分:手绘风滤镜(Paint Filter)(当前位置!)
开始吧

译者注: 本教程提供了范例工程,如果需要可以到原文网站免费注册并下载

下载工程文件并解压缩,找到PaintFilterStarter文件夹,打开PaintFilter.uproject,你就会看到下面的场景:

在这里插入图片描述 为了节省大家的时间,这个场景已经包含了自定义节点PP_Kuwahara的Post Process Volume ,这个材质(以及其着色器),就是我们要编辑的。

在这里插入图片描述 那么,我们先来了解一下桑原滤镜和它的工作原理吧。

桑原滤镜

照相的时候,我们有时会在照片表面发现一种颗粒状的纹理。就如同来自我们吵闹的邻居家中的噪声一样,我们往往不喜欢它。

在这里插入图片描述

常用的去噪方法就是使用诸如模糊之类的低通滤镜(low-pass filter ),下图就是使用半径为5的矩形模糊算法处理过的图片。

在这里插入图片描述

如上图所示,噪声基本被消除了,但是所有的边缘也变得模糊了。有没有一种方法能再平滑图像的同时保持边缘呢。

如你猜测的那样,桑原滤镜就能够满足这个需求,让我们看看它是如何工作的。

桑原滤镜的工作原理

和卷积运算一样,桑原滤镜也要使用核(kernel),不同的是它不是使用1个而是4个。4个核如下图(5×5的桑原滤镜)所示布局,每两个核之间会有1个像素重叠(当前像素)

在这里插入图片描述

首先,计算每一个核中颜色的平均值,这步是为了后面要通过模糊来降噪。

对于每个核,还要计算方差,这主要是测量每个核中颜色值的变化大小。如果一个核中的颜色很相近,那么这个方差会很小;反之,如果颜色不相近,那么方差会很大。

最后,我们找到方差最低的核,并输出它的颜色平均值。这种基于方差的选择就是桑原滤镜保持边缘的方法。让我们看几个例子。

桑原滤镜的例子

下面是个10×10的灰度图,我们可以看到一条从左下到右上的边缘,以及某些区域存在的噪声。

在这里插入图片描述

首先,选择一个像素并计算出方差最小的核。下图为本例所选的一个边缘附近的像素以及其相关的核:

在这里插入图片描述 如你所见,在边缘上的核,其颜色是抖动的,这意味着高方差因此它们也不会被选择。也正因此,桑原滤镜防止了边缘的模糊。

本例中,滤镜会选择绿色框框的那个核,因为它最稳定。于是输出的结果就是这个核中颜色的平均值(有点接近黑色)。

下面为另一个像素的以及它的核:

在这里插入图片描述

这次,黄色框框的核拥有最低的方差,因此它是唯一一个不在边缘的。所以本次输出结果为黄色核中颜色的平均值,这次结果有点接近白色。

下图为矩形模糊核桑原滤镜的对比,它们的半径都是5.

在这里插入图片描述

如你所见,桑原滤镜在平滑且保持边缘方面做的相当不错,本例中它让边缘依然保持清晰!

同时,这个边缘保持的平滑特性还给图像带来了一种手绘风。因为,绘画的笔刷通常就是边缘较硬而且不会产生很大(画面)噪声的。于是,桑原滤镜就是一个将写实风转换成手绘风的不错的选择。

以下就是一个使用不同大小桑原滤镜处理照片的效果图

在这里插入图片描述

创建桑原滤镜

本教程中,滤镜将被分割成两个着色器文件:Global.usf 和 Kuwahara.usf。第一个文件要存储计算核平均值以及方差的函数;第二个文件要存储滤镜的入口并且将会为每个核调用上述函数。

首先,我们来定义计算平均值和方差的函数。在范例工程中找到Shaders文件夹,然后打开其中的 Global.usf。我们可以看到其中名为GetKernelMeanAndVariance()的函数。

开始构建函数之前,我们需要添加几个参数。修改后的函数如下:

float4 GetKernelMeanAndVariance(float2 UV, float4 Range)

我们需要两重循环对一个网格进行采样:一个循环负责垂直方向另一个负责水平方向。Range参数的前两个通道存储水平循环的边界,后两个通道存储垂直循环的边界。例如:我们正在对坐上角的核进行采样且核大小为2,那么它的Range即为:

Range = float4(-2, 0, -2, 0);

好,现在开始抽样。

像素抽样

先创建2重循环,在GetKernelMeanAndVariance()函数中添加如下代码:

for (int x = Range.x; x             
关注
打赏
1656935939
查看更多评论
0.0403s