UE 油画滤镜

这篇具有很好参考价值的文章主要介绍了UE 油画滤镜。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

  • 非真实感渲染的风格不经相同,其中一种便是油画风格,本文总结了如何实现油画滤镜的方法
    UE 油画滤镜

Kuwahara Filter

  • 为什么使用Kuwahara Filter?

    一般对图像进行模糊处理,会使用低通滤波器,但往往模糊后图像会失去它们的硬边,但Kuwahara Filter可以在平滑图像的同时也能保留其硬边
    UE 油画滤镜UE 油画滤镜

  • 如何实现Kuwahara Filter?

    • Kuwahara Filter也是使用卷积,但不同之处是Kuwahara Filter需要四个卷积核
      UE 油画滤镜

    • 过程:计算每个卷积核的平均值(平滑噪点)方差(衡量一个内核的颜色变化率),一共四个。找出方差最小的卷积核并输出其平均值

    • 例子
      UE 油画滤镜

      对于上图的计算动图如下
      UE 油画滤镜

      右边的颜色变化率太大了,不会选它,这里选择的是最左边的卷积核,因为它的颜色最均匀,最后输出它的平均值

实现油画滤镜

  • 根节点需要选择"Material Domain"为"Post Process"
    UE 油画滤镜

  • 总体实现框架
    UE 油画滤镜

  • "Global"自定义节点计算平均值和方差

    方差计算公式UE 油画滤镜

    int32 SceneTextureLookup
    (
        int32 ViewportUV,		// 纹理坐标
        uint32 SceneTextureId,	// 节点sceneTexture中的Scene Texture Id索引值
        bool bFiltered	//是否使用双线性插值
    )
    

    UE 油画滤镜

  • 计算四个卷积核
    UE 油画滤镜

  • 效果对比
    UE 油画滤镜
    UE 油画滤镜

实现方向性油画滤镜

  • 为什么需要方向性油画滤镜
    从上图可以看出该滤镜某些地方有点奇怪,过于方正,而方向性油画滤镜可以解决这个问题

  • 如何实现

    • 方向性油画滤镜和之前的差别在于它的卷积核和像素的局部朝向相同
      UE 油画滤镜

    • 计算局部朝向的方法是Sobel

      Sobel需要两个卷积核,Gx提供水平方向的梯度信息,Gy提供垂直方向的梯度信息。使用这两个卷积核分别对像素做一次卷积,再使用atan()求角度,随后以该角度对卷积核进行旋转
      UE 油画滤镜

    • 例子
      UE 油画滤镜

      对上图进行Sobel,得到的结果如下
      UE 油画滤镜
      使用atan()求角度
      UE 油画滤镜

  • 具体实现

    • 求角度
      UE 油画滤镜

    • 修改GetKernelMeanAndVariance()

      float4 GetKernelMeanAndVariance(float2 uv, float4 range, float2x2 rotationMatrix)
      {
          //...
          float2 offset = mul(float2(x, y) * textelSize, rotationMatrix);
      
      
    • 计算旋转矩阵
      UE 油画滤镜

    • 效果对比
      UE 油画滤镜
      UE 油画滤镜

源代码

  • global

    float4 GetKernelMeanAndVariance(float2 uv, float4 range, float2x2 rotationMatrix)
    {
        float2 textelSize = View.ViewSizeAndInvSize.zw; //纹素大小
        const int ppInput0 = 14;    //对应SceneTexture的节点索引值
        float3 mean = 0;    //平均值
        float3 variance = 0;    //方差
        int sampleNums = 0;     //采样次数
        
        for(int x = range.x; x <= range.y; ++x)
        {
            for(int y = range.z; y <= range.w; ++y)
            {
                float2 offset = mul(float2(x, y) * textelSize, rotationMatrix);
                float3 pixelColor = SceneTextureLookup(uv + offset, ppInput0, false).rgb;
    
                mean += pixelColor;
                variance = pixelColor * pixelColor;
                sampleNums++;
            }
        }
        mean /= sampleNums;
        variance = variance / sampleNums - mean * mean;
    
        float totalVariance = variance.r + variance.g + variance.b;
        return float4(mean.r, mean.g, mean.b, totalVariance);
    }
    
    // 求角度
    float4 GetAngle(float2 uv)
    {
        float2 textelSize = View.ViewSizeAndInvSize.zw; //纹素大小
        const int ppInput0 = 14;    //对应SceneTexture的节点索引值
    
        float gradientX = 0.f;  // 水平方向的梯度值
        float gradientY = 0.f;  // 竖直方向的梯度值
        float sobelX[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1};   // 水平方向的卷积核
        float sobelY[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};   // 垂直方向的卷积核
        int i = 0;  //访问sobel的索引
    
        for(int x = -1; x <= 1; ++x)
        {
            for(int y = -1; y <= 1; ++y)
            {
                float2 offset = float2(x, y) * textelSize;
                float3 pixelColor = SceneTextureLookup(uv + offset, ppInput0, false).rgb;
                float pixelValue = dot(pixelColor, float3(0.3,0.59,0.11));  // 转化为灰度值。用于将图像看作一个整体来计算梯度,比计算单个颜色值的梯度快
    
                // 计算梯度值
                gradientX += pixelValue * sobelX[i];
                gradientY += pixelValue * sobelY[i];
                i++;
            }
        }
    
        return atan(gradientY / gradientX);
    
    
  • Kuwahara

    const int ppInput0 = 14;
    float2 uv = GetDefaultSceneTextureUV(Parameters, ppInput0); //目标像素点
    float4 range;   //卷积核范围.xy表示x的范围,zw表示y的范围
    float4 meanAndVariance[4];  //算得的平均值和方差
    
    float angle = GetAngle(uv);
    float2x2 rotationMatrix = float2x2(cos(angle), -sin(angle), sin(angle), cos(angle));
    
    // 计算四个卷积核
    range = float4(-RadiusX, 0, -RadiusY, 0);
    meanAndVariance[0] = GetKernelMeanAndVariance(uv, range, rotationMatrix);
    
    range = float4(-RadiusX, 0, 0, RadiusY);
    meanAndVariance[1] = GetKernelMeanAndVariance(uv, range, rotationMatrix);
    
    range = float4(0, RadiusX, 0, RadiusY);
    meanAndVariance[2] = GetKernelMeanAndVariance(uv, range, rotationMatrix);
    
    range = float4(0, RadiusX, -RadiusY, 0);
    meanAndVariance[3] = GetKernelMeanAndVariance(uv, range, rotationMatrix);
    
    // 求方差最小值的颜色
    float3 finalColor = meanAndVariance[0].rgb;
    float minVariance = meanAndVariance[0].a;
    
    for(int i = 1; i < 4; ++i)
    {
        if(minVariance > meanAndVariance[i].a)
        {
            minVariance = meanAndVariance[i].a;
            finalColor = meanAndVariance[i].rgb;
        }
    }
    
    return finalColor;
    
    

reference

UE4卡通渲染基础教程 Part4:Paint Filter - 知乎 (zhihu.com)

Unreal Engine 4 Paint Filter Tutorial | Kodeco文章来源地址https://www.toymoban.com/news/detail-482204.html

到了这里,关于UE 油画滤镜的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [Unity/URP学习]风格化水体渲染(一)

    着色:水体颜色、水体反射、水体折射、岸边泡沫、水面于天空沿边线消除、水体焦散 动画处理:水体流动、顶点动画、水体交互、水体浮力 (实现顺序没有严格按照着色和动画处理的分类来实现) 要制作水体颜色,要考虑的内容如下: 风格化的水体渐变颜色、水体深浅区

    2024年02月13日
    浏览(57)
  • UE4 云渲染环境搭建

    基于ue4的云渲染目的在与将ue4实时渲染图像帧通过视频流的方式一帧一帧的传到浏览器端,主要是因为基于web的三维渲染效果不佳,通过ue4的强大渲染能力与各种功能的支持能力使得网页端也可以实时看到好的效果。 这个过程服务之间使用的是反向代理的机制,过程大概分为

    2023年04月08日
    浏览(41)
  • 游戏引擎UE如何革新影视行业?创意云全面支持UE云渲染

     虚幻引擎UE(Unreal Engine)作为一款“殿堂级”的游戏引擎,占据了全球80%的商用游戏引擎市场,但如果仅仅将其当做游戏开发的工具,显然是低估了它的能力。比如迪士尼出品的电视剧《曼达洛人》、电影《狮子王》等等都使用了虚幻的虚拟场景。  可见 游戏行业与影视行

    2024年02月16日
    浏览(34)
  • UE虚幻引擎云渲染支持8K方案

    UE自带的pixel streaming只支持4K以内的编码,查看HardwareEncoders插件源码,发现nvenc编码器由于硬件限制,超过4K分辨率的视频编码必须使用h265 hevc编码,默认情况下使用h264不支持8K分辨率。 修改源码PluginsHardwareEncodersSourceEncoderNVENCPrivateNVENC_EncoderH264.cpp 如果需要编码后的裸流,

    2024年02月16日
    浏览(57)
  • UE官方教程笔记02-实时渲染基础下

    对官方教程视频[官方培训]02-实时渲染基础下 | 陈拓 Epic的笔记 没听懂的地方就瞎写 实时渲染中反射是一个非常有挑战的特性 UE中有多种不同的方案,各有各的优势和缺点 反射捕获 屏幕空间反射 平面反射 Lumen RT Reflection 反射捕获 在指定位置捕获一张Cube Map 需要预计算 快速

    2024年02月02日
    浏览(39)
  • UE5.1 透明渲染流程框架图

    相关文章:  UE 透明物体绘制准备_sh15285118586的博客-CSDN博客  透明直接光和间接光生成_sh15285118586的博客-CSDN博客 Scene:Translucency-Translucency(AfterDOF)_sh15285118586的博客-CSDN博客 Scene:Translucency-Distortion PostProcessing:ComposeTranslucencyToNewSceneColor_sh15285118586的博客-CSDN博客

    2024年02月10日
    浏览(41)
  • UE4 顶点网格动画播放后渲染模糊问题

    问题描述:ABC格式的顶点网格动画播放结束后,改模型看起来显得很模糊有抖动的样子 解决办法:关闭逐骨骼动态模糊

    2024年02月07日
    浏览(42)
  • UE5 3DUI Widget 渲染模糊和重影问题

    目录 一、解决重影问题 1、创建3D widget 2、 修改材质  二、提高清晰度 1、使用锐化命令 r.Tonemapper.Sharpen 2                            (修改前)                                        (修改后) 人物是动态图片,用3DWidget在场景中播放的,人物在做眨眼

    2024年02月05日
    浏览(163)
  • UE4 nDisplay:一台电脑对多个显示屏渲染

    问题描述:看似一块大屏,通常是由多块显示屏拼接组装起来的,所以需要一台电脑对多个显示屏渲染 解决方法:启用Surround,并配置每块屏幕的分辨率和顺序

    2024年02月13日
    浏览(49)
  • UE4中如何对Movie Render Queue进行渲染设置

    Movie Render Queue 的渲染设置用于控制序列的渲染方式。它们包括抗锯齿、自定义控制台命令、输出格式、渲染模式和其他功能。本指南将介绍设置界面、可用设置列表以及将设置保存为预设的能力。 首先在 Unreal Engine 中启用 Movie Render Queue 插件。在 Unreal Engine 菜单中,转到 E

    2024年02月04日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包