美文网首页Unity3D
【Unity3D】运动模糊特效

【Unity3D】运动模糊特效

作者: LittleFatSheep | 来源:发表于2023-08-08 00:54 被阅读0次

    1 运动模糊原理

    开启混合(Blend)后,通过 Alpha 通道控制当前屏幕纹理与历史屏幕纹理进行混合,当有物体运动时,就会将当前位置的物体影像与历史位置的物体影像进行混合,从而实现运动模糊效果,即模糊拖尾效果。主要代码如下:

    Pass {
        Blend SrcAlpha OneMinusSrcAlpha
    
        CGPROGRAM
    
        #pragma vertex vert_img // 使用内置的vert_img顶点着色器
        #pragma fragment fragRGB // _BlurAmount只参与混合, 不影响alpha值
    
        fixed4 fragRGB (v2f_img i) : SV_Target { // v2f_img为内置结构体, 里面只包含pos和uv
            return fixed4(tex2D(_MainTex, i.uv).rgb, _BlurAmount); // 模糊值, 通过alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合
        }
    
        ENDCG
    }
    

    本文完整资源 见→Unity3D运动模糊特效

    2 代码实现

    MotionBlur.cs

    using UnityEngine;
    
    [RequireComponent(typeof(Camera))] // 需要相机组件
    public class MotionBlur : MonoBehaviour {
        [Range(0.0f, 0.9f)]
        public float blurAmount = 0.5f; // 模糊值, 值越大拖尾效果越明显
        private RenderTexture historyTexture; // 历史屏幕纹理
        private Material material = null; // 材质
    
        private void Start() {
            material = new Material(Shader.Find("MyShader/MotionBlur"));
            material.hideFlags = HideFlags.DontSave;
        }
    
        void OnDisable() { // 脚本不运行时立即销毁, 下次开始应用运动模糊时, 重新混合图像
            DestroyImmediate(historyTexture);
        }
    
        void OnRenderImage(RenderTexture src, RenderTexture dest) {
            if (material != null) {
                // 初始化时或窗口尺寸变化时, 创建叠加纹理
                if (historyTexture == null || historyTexture.width != src.width || historyTexture.height != src.height) {
                    DestroyImmediate(historyTexture);
                    historyTexture = new RenderTexture(src.width, src.height, 0);
                    historyTexture.hideFlags = HideFlags.HideAndDontSave;
                    Graphics.Blit(src, historyTexture);
                }
                material.SetFloat("_BlurAmount", 1.0f - blurAmount); // 设置模糊值, 通过alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合
                Graphics.Blit(src, historyTexture, material);
                Graphics.Blit(historyTexture, dest);
            } else {
                Graphics.Blit(src, dest);
            }
        }
    }
    

    MotionBlur.shader

    Shader "MyShader/MotionBlur" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {} // 主纹理
            _BlurAmount ("Blur Amount", Float) = 1.0 // 模糊值, 通过alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合
        }
    
        SubShader {
            CGINCLUDE
    
            #include "UnityCG.cginc"
            
            sampler2D _MainTex; // 主纹理
            fixed _BlurAmount; // 模糊值, 通过alpha通道控制当前屏幕纹理与历史屏幕纹理进行混合
    
            fixed4 fragRGB (v2f_img i) : SV_Target { // v2f_img为内置结构体, 里面只包含pos和uv
                return fixed4(tex2D(_MainTex, i.uv).rgb, _BlurAmount);
            }
    
            half4 fragA (v2f_img i) : SV_Target { // v2f_img为内置结构体, 里面只包含pos和uv
                return tex2D(_MainTex, i.uv);
            }
    
            ENDCG
    
            ZTest Always Cull Off ZWrite Off
    
            Pass {
                Blend SrcAlpha OneMinusSrcAlpha
                ColorMask RGB // 允许通过的颜色通道, 取值有: 0、R、G、B、A、RGBA的组合(RG、RGB等)
    
                CGPROGRAM
    
                #pragma vertex vert_img // 使用内置的vert_img顶点着色器
                #pragma fragment fragRGB // _BlurAmount只参与混合, 不影响alpha值
    
                ENDCG
            }
    
            Pass {
                Blend One Zero
                ColorMask A // 允许通过的颜色通道, 取值有: 0、R、G、B、A、RGBA的组合(RG、RGB等)
    
                CGPROGRAM
    
                #pragma vertex vert_img // 使用内置的vert_img顶点着色器
                #pragma fragment fragA // 使用纹理原本的alpha值
    
                ENDCG
            }
        }
    
        FallBack Off
    }
    

    说明: vert_img 是 Unity 内置的顶点着色器,v2f_img 是 Unity 内置的结构体变量,vert_img 和 v2f_img 的实现见→Shader常量、变量、结构体、函数;第一个 Pass 通过 Alpha 通道控制当前屏幕纹理与历史屏幕纹理进行混合,通过 ColorMask RGB 保证混合不影响 Alpha 通道值;第二个 Pass 对当前屏幕的 Alpha 通道进行采样,通过 ColorMask A 保证采样不影响 RGB 通道的值。

    3 运行效果

    1)原图效果

    将 blurAmount 设置为 0,无运动模糊特效,如下:

    2)运动模糊效果

    将 blurAmount 设置为 0.9,运动模糊特效如下:

    声明:本文转自【Unity3D】运动模糊特效

    相关文章

      网友评论

        本文标题:【Unity3D】运动模糊特效

        本文链接:https://www.haomeiwen.com/subject/wiknpdtx.html