【Unity3D】高斯模糊特效

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

1 高斯模糊原理

        边缘检测特效中使用了卷积运算进行了边缘检测,本文实现的高斯模糊特效同样使用了卷积运算,关于卷积核和卷积运算的概念,读者可以参考边缘检测特效。

        本文完整资源见→Unity3D高斯模糊特效。

        我们将用于模糊处理的卷积核称为模糊算子,它一般满足以下条件:

  • 卷积核中权值上下对称、左右对称;
  • 卷积核中每个权值大于或等于 0,小于 1;
  • 卷积核中所有权值之和为 1。

        我们将所有权值都为 1 / n(n 为权值个数)的卷积核称为平均模糊算子;将权值随位置变化且符合高斯分布(或正太分布)的卷积核称为高斯模糊算子(或高斯核),它较好地模拟了邻域中每个像素对当前处理像素的影响程度(距离越近,影响越大)。高斯方程如下:

【Unity3D】高斯模糊特效

         σ 是标准差,其值越大,高斯分布函数的图像越矮胖,一般取值为 1,x、y 为当前位置到卷积核中心的整数距离。要构建一个高斯核,我们只需要计算高斯核中各个位置对应的高斯值。为了保证模糊处理后的图像不会变暗,我们需要对高斯核中的元素进行归一化,即将所有元素都除以它们的权值和,从而保证归一化后的权值和为 1。因此,高斯函数中 e 前面的系数不会对高斯核产生任何影响,在计算高斯核的过程中可以省去。

        高斯核的维数越高,模糊程度越大。使用一个 n * n 的卷积核,需要进行 n * n * w * h 次纹理采样(w、h 分别为图像的宽高),为节省性能,我们将二维高斯核拆分为 2 个一维高斯核,采样次数只需要 2 * n * w * h 次。进一步观察到,2 个高斯核中包含了很多重复权重。对于一个大小为 5 的一维高斯核,实际只需记录 3 个权值即可。

【Unity3D】高斯模糊特效

2 代码实现

        GaussianBlur.cs

using UnityEngine;

[ExecuteInEditMode] // 编辑态可以查看脚本运行效果
[RequireComponent(typeof(Camera))] // 需要相机组件
public class GaussianBlur : MonoBehaviour {
    [Range(0, 4)]
    public int iterations = 3; // 高斯模糊迭代次数
    [Range(0.2f, 3.0f)]
    public float blurSpread = 0.6f; // 每次迭代纹理坐标偏移的速度
    [Range(1, 8)]
    public int downSample = 2; // 降采样比率
    private Material material = null; // 材质

    private void Start() {
        material = new Material(Shader.Find("MyShader/GaussianBlur"));
        material.hideFlags = HideFlags.DontSave;
    }

    void OnRenderImage(RenderTexture src, RenderTexture dest) {
        if (material != null) {
            int rtW = src.width / downSample; // 降采样的纹理宽度
            int rtH = src.height / downSample; // 降采样的纹理高度
            RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
            buffer0.filterMode = FilterMode.Bilinear; // 滤波模式设置为双线性
            Graphics.Blit(src, buffer0);
            for (int i = 0; i < iterations; i++) {
                material.SetFloat("_BlurSize", 1.0f + i * blurSpread); // 设置模糊尺寸(纹理坐标的偏移量)
                RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                Graphics.Blit(buffer0, buffer1, material, 0); // 渲染垂直的Pass
                RenderTexture.ReleaseTemporary(buffer0);
                buffer0 = buffer1;
                buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                Graphics.Blit(buffer0, buffer1, material, 1); // 渲染水平的Pass
                RenderTexture.ReleaseTemporary(buffer0);
                buffer0 = buffer1;
            }
            Graphics.Blit(buffer0, dest);
            RenderTexture.ReleaseTemporary(buffer0);
        } else {
            Graphics.Blit(src, dest);
        }
    }
}

        GaussianBlur.shader

Shader "MyShader/GaussianBlur" { // 高斯模糊
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {} // 主纹理
        _BlurSize ("Blur Size", Float) = 1.0 // 模糊尺寸(纹理坐标的偏移量)
    }

    SubShader {
        CGINCLUDE
        
        #include "UnityCG.cginc"
        
        sampler2D _MainTex; // 主纹理
        half4 _MainTex_TexelSize; // _MainTex的像素尺寸大小, float4(1/width, 1/height, width, height)
        float _BlurSize; // 模糊尺寸(纹理坐标的偏移量)
          
        struct v2f {
            float4 pos : SV_POSITION; // 模型空间顶点坐标
            half2 uv[5]: TEXCOORD0; // 5个邻域的纹理坐标
        };
          
        v2f vertBlurVertical(appdata_img v) { // 垂直模糊顶点着色器
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)
            half2 uv = v.texcoord;
            o.uv[0] = uv;
            o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
            o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
            o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
            o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;      
            return o;
        }
        
        v2f vertBlurHorizontal(appdata_img v) { // 水平模糊顶点着色器
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex); // 模型空间顶点坐标变换到裁剪空间, 等价于: mul(UNITY_MATRIX_MVP, v.vertex)
            half2 uv = v.texcoord;
            o.uv[0] = uv;
            o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
            o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
            o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
            o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;      
            return o;
        }

        fixed4 fragBlur(v2f i) : SV_Target {
            float weight[3] = {0.4026, 0.2442, 0.0545}; // 大小为5的一维高斯核,实际只需记录3个权值
            fixed3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
            for (int j = 1; j < 3; j++) {
                sum += tex2D(_MainTex, i.uv[j * 2 - 1]).rgb * weight[j]; // 中心右侧或下侧的纹理*权值
                sum += tex2D(_MainTex, i.uv[j * 2]).rgb * weight[j]; // 中心左侧或上侧的纹理*权值
            }
            return fixed4(sum, 1.0);
        }
            
        ENDCG
        
        ZTest Always Cull Off ZWrite Off
        
        Pass {
            NAME "GAUSSIAN_BLUR_VERTICAL"
            
            CGPROGRAM
              
            #pragma vertex vertBlurVertical  
            #pragma fragment fragBlur
              
            ENDCG  
        }
        
        Pass {  
            NAME "GAUSSIAN_BLUR_HORIZONTAL"
            
            CGPROGRAM  
            
            #pragma vertex vertBlurHorizontal  
            #pragma fragment fragBlur
            
            ENDCG
        }
    }

    FallBack "Diffuse"
}

3 运行效果

        1)原图

【Unity3D】高斯模糊特效

        2)模糊处理

        调整模糊迭代次数 iterations 由 0 ~ 4 变化,效果如下:

【Unity3D】高斯模糊特效文章来源地址https://www.toymoban.com/news/detail-469893.html

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

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

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

相关文章

  • Unity3D教程:2D游戏技能特效

    在我们的2D图形游戏中不可缺少大量的光影、技能特效,像Diablo II中的魔法效果的实现,幸好我们拥有强大的CPU来为我们实现Alpha混合与色彩饱和混合,接下来让我们来讨论一下如何用这些方法来实现我们游戏中所需要的技能特效。     一、Alpha混合特效     Alpha混合可以让我

    2024年02月01日
    浏览(61)
  • Unity3D粒子系统之制作火焰特效

    本文将会介绍如何使用Unity内的粒子系统制作烟雾效果。 如果想了解Unity粒子系统中的基础属性,可以看这篇博客:Unity3D粒子系统之基础属性介绍 先上预览图吧 用自己熟悉的绘画工具画一张类似这样的图片(相似即可,白灰色部分边缘不规则),注意一定要黑底。 将画好的

    2024年02月02日
    浏览(47)
  • Unity3D粒子系统之制作烟雾特效

    本文将会介绍如何使用Unity内的粒子系统制作烟雾效果。 如果想了解Unity粒子系统中的基础属性,可以看这篇博客:Unity3D 粒子系统之基础属性介绍 先附上预览图: 材质贴图 首先我们需要一张烟雾材质用的材质贴图,我是自己画的,可以参考下图自己画一张或者去网上找素材

    2024年02月02日
    浏览(55)
  • 【Unity3D赛车游戏优化篇】【十】汽车粒子特效和引擎咆哮打造极速漂移

    👨‍💻个人主页 :@元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏 :Unity游戏demo – 😶‍🌫️版本: Unity2021 😶‍🌫️适合人群:Unity初学者进阶 😶‍🌫️学习目标:3D赛车游戏的基础制作 😶‍🌫️技能

    2024年02月09日
    浏览(69)
  • 【Unity3d】【原理】【实践】协程的原理和实践

    原理 协程,需要从迭代器说起。 协程的执行,可以归结为,每帧执行一次迭代,直到迭代结束,返回。 迭代器,IEnumerator接口的实现。其中的核心迭代功能,在 bool MoveNext() 中,若返回为true,则表明当前未结束;若返回false,则表明当前迭代结束。 若迭代未结束,则需是的迭代

    2023年04月09日
    浏览(77)
  • Unity3D中的C#协程(概念、使用方法、底层原理)

             Unity3D 中的协程是针对 Unity3D 框架和 C# 编程语言定制的 ,具有便捷的使用方式和良好的效率。其他语言Python、Lua等也支持协程,但是底层实现的细节可能不同。在 Unity3D 引擎中, 协程被 Unity3D 引擎的主循环所驱动 。         协程(Coroutine)是一种编程概念

    2024年02月08日
    浏览(55)
  • Unity3D TCP网络通讯核心意涵与基本原理详解

    在Unity3D中,TCP网络通讯是一种常用的通讯方式,它可以实现可靠的数据传输和连接。 对惹,这里有一 个游戏开发交流小组 ,希望大家可以点击进来一起交流一下开发经验呀 本文将详细介绍Unity3D TCP网络通讯的核心意涵与基本原理,包括技术详解和代码实现。 一、TCP网络通

    2024年03月12日
    浏览(48)
  • 【Unity3D日常开发】Unity3D中协程的使用

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 最近有小伙伴问协程怎么用、怎么写,我也是会用会写,但是原理不是很明白。 学习了一下,总结出

    2024年02月12日
    浏览(59)
  • unity3D基础操作之01--unity3d窗口界面介绍

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 1、Scene场景编辑窗口; 2、Game游戏运行窗口; 3、Hierarchy场景物体列表窗口; 4、Project项目资源列表窗口; 5、Inspector属性编辑列表窗口; 6、其他常调节窗口 在屏幕左上方为场景编辑窗口Scene,在场景编

    2024年02月06日
    浏览(80)
  • 【Unity3D小功能】Unity3D中实现Text显示版本功能

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 在项目开发中,会遇到要控制版本的情况,比如说对比版本号,版本不对再更新版本的功能,这些就是

    2024年02月05日
    浏览(77)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包