Unity FairyGUI高斯模糊实现方法

方法一:使用 FairyGUI 内置的 BlurFilter(推荐)

1. 基本使用

csharp

复制代码
using FairyGUI;

// 创建模糊滤镜
BlurFilter blurFilter = new BlurFilter();
blurFilter.blurSize = 2f; // 模糊半径
blurFilter.downsample = 1; // 下采样倍数,值越大性能越好但质量越低

// 应用到组件
GComponent comp = GetComponent<GComponent>();
comp.filter = blurFilter;

2. 动态模糊效果

csharp

复制代码
using UnityEngine;
using FairyGUI;

public class BlurEffectDemo : MonoBehaviour
{
    private GComponent _mainView;
    private BlurFilter _blurFilter;
    
    void Start()
    {
        // 创建UI
        _mainView = UIPackage.CreateObject("PackageName", "ComponentName").asCom;
        GRoot.inst.AddChild(_mainView);
        
        // 创建模糊滤镜
        _blurFilter = new BlurFilter();
        _blurFilter.blurSize = 0f;
        _mainView.filter = _blurFilter;
        
        // 添加按钮控制
        GButton btn = _mainView.GetChild("btn_blur").asButton;
        btn.onClick.Add(() => {
            // 开启模糊动画
            PlayBlurAnimation(5f, 0.3f);
        });
    }
    
    void PlayBlurAnimation(float targetBlurSize, float duration)
    {
        // 使用 FairyGUI 的动画系统
        GTween.To(_blurFilter.blurSize, targetBlurSize, duration)
            .SetEase(EaseType.Linear)
            .OnUpdate(tweener => {
                _blurFilter.blurSize = tweener.value.x;
                _mainView.InvalidateBatchingState();
            });
    }
}

方法二:使用 RenderTexture + 后处理Shader

1. 创建高斯模糊 Shader

glsl

复制代码
// GaussianBlur.shader
Shader "FairyGUI/GaussianBlur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BlurSize ("Blur Size", Range(0, 10)) = 1
    }
    
    SubShader
    {
        Tags { "Queue"="Transparent" }
        Blend SrcAlpha OneMinusSrcAlpha
        
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            float _BlurSize;
            
            v2f vert(appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                // 高斯模糊核心算法
                float2 texelSize = _MainTex_TexelSize.xy * _BlurSize;
                float4 color = float4(0, 0, 0, 0);
                float weightSum = 0;
                
                // 5x5 高斯核
                float weights[5] = {0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216};
                float offsets[5] = {0.0, 1.0, 2.0, 3.0, 4.0};
                
                // 水平模糊
                color += tex2D(_MainTex, i.uv) * weights[0];
                for(int j = 1; j < 5; j++)
                {
                    color += tex2D(_MainTex, i.uv + float2(offsets[j] * texelSize.x, 0)) * weights[j];
                    color += tex2D(_MainTex, i.uv - float2(offsets[j] * texelSize.x, 0)) * weights[j];
                }
                
                return color;
            }
            ENDCG
        }
    }
}

2. 在代码中使用

csharp

复制代码
using UnityEngine;
using FairyGUI;

public class AdvancedBlur : MonoBehaviour
{
    private RenderTexture _blurRT;
    private Material _blurMaterial;
    
    void Start()
    {
        // 创建模糊材质
        _blurMaterial = new Material(Shader.Find("FairyGUI/GaussianBlur"));
        
        // 创建 UI
        GComponent comp = UIPackage.CreateObject("Package", "Component").asCom;
        
        // 先渲染到 RenderTexture
        CreateBlurTexture(comp);
    }
    
    void CreateBlurTexture(GComponent comp)
    {
        // 获取 UI 的渲染尺寸
        Vector2 size = comp.size;
        
        // 创建 RenderTexture
        _blurRT = new RenderTexture((int)size.x, (int)size.y, 0);
        
        // 设置模糊参数
        _blurMaterial.SetFloat("_BlurSize", 3f);
        
        // 创建一个图片显示模糊结果
        GImage blurImage = new GImage();
        blurImage.SetSize(size.x, size.y);
        blurImage.texture = new NTexture(_blurRT);
        
        // 将模糊图片添加到 UI
        comp.AddChild(blurImage);
    }
}

方法三:使用 Unity Post Processing Stack v2

1. 配置步骤

  1. 安装 Post Processing Package

  2. 创建 Post Process Layer 和 Volume

  3. 添加 Blur 效果

2. 代码实现

csharp

复制代码
using UnityEngine;
using UnityEngine.Rendering.PostProcessing;
using FairyGUI;

public class PostProcessBlur : MonoBehaviour
{
    public PostProcessVolume blurVolume;
    private DepthOfField _dof;
    
    void Start()
    {
        // 获取或创建 DepthOfField 效果
        blurVolume.profile.TryGetSettings(out _dof);
        
        // 创建UI
        GComponent comp = UIPackage.CreateObject("Package", "Component").asCom;
        GRoot.inst.AddChild(comp);
        
        // 添加切换模糊的按钮
        GButton btn = comp.GetChild("btn_toggle_blur").asButton;
        btn.onClick.Add(ToggleBlur);
    }
    
    void ToggleBlur()
    {
        if (_dof != null)
        {
            _dof.active = !_dof.active;
            // 设置模糊参数
            _dof.focusDistance.value = 0.1f;
            _dof.aperture.value = 32f;
            _dof.focalLength.value = 50f;
        }
    }
}

方法四:性能优化建议

1. 缓存模糊结果

csharp

复制代码
public class CachedBlur
{
    private Dictionary<string, NTexture> _blurCache = new Dictionary<string, NTexture>();
    
    public NTexture GetCachedBlur(GObject obj, float blurSize)
    {
        string cacheKey = $"{obj.id}_{blurSize}";
        
        if (!_blurCache.ContainsKey(cacheKey))
        {
            // 生成模糊纹理
            NTexture blurTex = GenerateBlurTexture(obj, blurSize);
            _blurCache[cacheKey] = blurTex;
        }
        
        return _blurCache[cacheKey];
    }
    
    private NTexture GenerateBlurTexture(GObject obj, float blurSize)
    {
        // 实现纹理生成逻辑
        return null;
    }
}

2. 按需模糊

csharp

复制代码
public class OnDemandBlur : MonoBehaviour
{
    public GComponent targetComp;
    public float checkInterval = 0.5f;
    
    void Start()
    {
        StartCoroutine(CheckAndApplyBlur());
    }
    
    IEnumerator CheckAndApplyBlur()
    {
        while (true)
        {
            // 检查是否需要模糊(例如UI是否在屏幕上)
            if (IsUIVisible())
            {
                ApplyBlurIfNeeded();
            }
            yield return new WaitForSeconds(checkInterval);
        }
    }
    
    bool IsUIVisible()
    {
        // 检查UI是否在屏幕内
        return targetComp.onStage;
    }
}

注意事项

  1. 性能考量

    • 移动设备建议使用较小的 blurSize(≤3)

    • 使用 downsampling 提高性能

    • 避免每帧更新模糊效果

  2. 内存管理

    • 及时释放不再使用的 RenderTexture

    • 使用对象池管理模糊材质

  3. 平台兼容性

    • 在 iOS 上确保使用正确的 Metal/GLES 配置

    • Android 上注意纹理格式兼容性

选择哪种方法取决于你的具体需求:

  • 简单模糊:使用 FairyGUI 的 BlurFilter

  • 高质量模糊:使用自定义 Shader + RenderTexture

  • 全屏后处理:使用 Post Processing Stack

  • 性能优先:使用缓存和按需渲染策略

验证和确认

1. 官方文档支持

FairyGUI 官方文档明确支持 BlurFilter

  • BlurFilter 类存在于 FairyGUI 命名空间

  • 这是官方提供的内置滤镜效果

2. 实际使用示例

这里提供一个完整可运行的示例:

csharp

复制代码
using UnityEngine;
using FairyGUI;

public class BlurDemo : MonoBehaviour
{
    void Start()
    {
        // 1. 创建UI
        GComponent view = UIPackage.CreateObject("包名", "组件名").asCom;
        view.SetSize(400, 300);
        view.Center();
        GRoot.inst.AddChild(view);
        
        // 2. 添加一个文本组件用于测试
        GTextField text = new GTextField();
        text.text = "这是测试文本,将会被模糊";
        text.SetSize(200, 50);
        text.SetXY(100, 125);
        view.AddChild(text);
        
        // 3. 创建并应用模糊滤镜
        BlurFilter blur = new BlurFilter();
        blur.blurSize = 3f; // 模糊程度,0-10
        blur.downsample = 1; // 下采样,1表示不降采样
        
        // 应用到整个组件
        view.filter = blur;
        
        // 或者应用到特定子组件
        // text.filter = blur;
        
        Debug.Log("模糊滤镜已应用!当前模糊大小:" + blur.blurSize);
    }
}

3. 关键参数说明

csharp

复制代码
// 创建模糊滤镜
BlurFilter blur = new BlurFilter();

// 主要参数:
blur.blurSize = 2f;      // 模糊半径,值越大越模糊(0-10)
blur.downsample = 1;     // 下采样,1=原始,2=1/2分辨率,性能更好但质量更低
blur.color = Color.white; // 颜色叠加
blur.strength = 1;       // 模糊强度(0-1)

4. 动态修改示例

csharp

复制代码
public class DynamicBlur : MonoBehaviour
{
    private BlurFilter _blurFilter;
    private GComponent _target;
    
    void Start()
    {
        _target = GetComponent<GComponent>();
        
        // 创建模糊滤镜
        _blurFilter = new BlurFilter();
        _target.filter = _blurFilter;
        
        // 按钮点击事件
        GButton btn = _target.GetChild("btnBlur").asButton;
        btn.onClick.Add(() => {
            // 点击时增加模糊
            _blurFilter.blurSize += 1f;
            if (_blurFilter.blurSize > 5f)
                _blurFilter.blurSize = 0f;
            
            // 必须调用这个来刷新显示
            _target.InvalidateBatchingState();
        });
    }
    
    void Update()
    {
        // 实时更新模糊(如果需要)
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _blurFilter.blurSize = 2f;
            _target.InvalidateBatchingState();
        }
    }
}

5. 常见应用场景

csharp

复制代码
// 场景1:弹窗背景模糊
public void ShowPopupWithBlur()
{
    // 获取当前界面
    GComponent currentView = GetCurrentView();
    
    // 创建模糊滤镜
    BlurFilter blur = new BlurFilter();
    blur.blurSize = 2f;
    currentView.filter = blur;
    
    // 显示弹窗
    ShowPopup();
    
    // 弹窗关闭时移除模糊
    // popup.OnClose += () => currentView.filter = null;
}

// 场景2:加载界面模糊
public void ShowLoadingWithBlur(GComponent target)
{
    BlurFilter blur = new BlurFilter();
    blur.blurSize = 3f;
    blur.downsample = 2; // 使用下采样提高性能
    target.filter = blur;
}

6. 性能测试代码

csharp

复制代码
using System.Diagnostics;
using FairyGUI;

public class BlurPerformanceTest : MonoBehaviour
{
    void Start()
    {
        TestBlurPerformance();
    }
    
    void TestBlurPerformance()
    {
        GComponent comp = UIPackage.CreateObject("包名", "组件名").asCom;
        
        Stopwatch sw = new Stopwatch();
        
        // 测试不同模糊半径的性能
        for (int i = 1; i <= 5; i++)
        {
            sw.Restart();
            
            BlurFilter blur = new BlurFilter();
            blur.blurSize = i;
            blur.downsample = 1;
            
            comp.filter = blur;
            comp.InvalidateBatchingState();
            
            sw.Stop();
            Debug.Log($"模糊半径 {i},耗时:{sw.ElapsedMilliseconds}ms");
        }
    }
}

注意事项

  1. 必须调用 InvalidateBatchingState()

    csharp

    复制代码
    // 修改模糊参数后必须调用
    component.InvalidateBatchingState();
  2. 下采样优化

    csharp

    复制代码
    // 移动设备建议使用下采样
    blur.downsample = 2; // 性能更好,但效果稍差
  3. 避免过度使用

    • 不要在每帧都修改模糊参数

    • 不使用时设置为 null 来释放资源:

      csharp

      复制代码
      component.filter = null;

验证你的项目

如果你不确定,可以在项目中运行这个测试:

csharp

复制代码
// 测试脚本
void TestBlur()
{
    GTextField text = new GTextField();
    text.text = "测试模糊";
    text.SetSize(200, 50);
    GRoot.inst.AddChild(text);
    
    BlurFilter blur = new BlurFilter();
    blur.blurSize = 3f;
    text.filter = blur;
    
    Debug.Log("如果没有报错,说明 BlurFilter 可用");
}
相关推荐
小南家的青蛙1 小时前
O3DE社区发布2510.1版本
游戏引擎·图形引擎
示申○言舌1 小时前
Unity高性能参数差异化URP Shader圆角圆环UI进度条
ui·unity·游戏引擎·圆环进度条·参数差异化·材质参数独立·圆角圆环
一只一只13 小时前
Unity之协程
unity·游戏引擎·协程·coroutine·startcoroutine
NIKITAshao1 天前
Unity 跨项目稳定迁移资源
unity·游戏引擎
sindyra1 天前
Unity资源内存管理与释放
unity·游戏引擎·资源管理·资源释放·内存释放
avi91111 天前
Unity半官方的AssetBundleBrowser插件说明+修复+Reporter插件
unity·游戏引擎·打包·assetbundle·游戏资源
郝学胜-神的一滴1 天前
深入理解Mipmap:原理、实现与应用
c++·程序人生·unity·游戏程序·图形渲染·unreal engine
一个笔记本1 天前
godot log | 修改main scene
游戏引擎·godot
nnsix2 天前
Unity PicoVR开发 实时预览Unity场景 在Pico设备中(串流)
unity·游戏引擎