UnityShader使用图像叠加实现运动模糊

下面是详细讲解"Unity Shader使用图像叠加实现运动模糊"的攻略。

一、前言

在实现游戏视觉效果时,运动模糊是一种非常实用的手段。运动模糊使用了相邻的帧并取平均值以模拟运动物体的模糊效果,使动作看起来更加连续、自然。

二、实现思路

运动模糊的实现思路是将相邻的帧的图像进行叠加处理,最后再进行取平均。具体实现时,需要使用相机的 RenderTexture 功能,将当前相机的图像渲染到 RenderTexture 上,并保存上一帧的 RenderTexture,再将当前帧的 RenderTexture 与上一帧的 RenderTexture 进行叠加,然后再将其取平均值并输出。

三、基础代码

下面是实现运动模糊的基础代码:

Shader "Custom/MotionBlurShader" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _BlurAmount ("Blur Amount", Range(0.0, 1.0)) = 0.5
    }
    SubShader {
        Tags {"Queue"="Transparent" "RenderType"="Transparent"}
        Pass{
            RenderGrabScreenTex {
                Tags { "GrabType"="BeforeRender" }
            }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _BlurAmount;
            uniform float4 _ScreenParams;
            uniform sampler2D _GrabTexture;
            float4 _GrabTexture_TexelSize;

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            float4 frag (v2f i) : SV_Target {
                float4 col = tex2D(_MainTex, i.uv);
                float4 previousCol = tex2D(_GrabTexture, i.uv);
                return col * (1 - _BlurAmount) + previousCol * _BlurAmount;
            }
            ENDCG
        }
        Pass{
            RenderGrabScreenTex {
                Tags { "GrabType"="BeforeRender" }
            }
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _BlurAmount;
            uniform float4 _ScreenParams;
            uniform sampler2D _GrabTexture;
            float4 _GrabTexture_TexelSize;

            struct appdata {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v) {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            float4 frag (v2f i) : SV_Target {
                float4 col = tex2D(_MainTex, i.uv);
                float4 previousCol = tex2D(_GrabTexture, i.uv);
                float4 blurCol = col * (1 - _BlurAmount) + previousCol * _BlurAmount;
                float2 vel = float2(0, 0);
                vel.y = tex2D(_GrabTexture, i.uv + float2(0, 0.001)).a - previousCol.a;
                vel.x = tex2D(_GrabTexture, i.uv + float2(0.001, 0)).a - previousCol.a;
                return blurCol;
            }
            ENDCG
        }
    }
    GrabPass{}
}

在代码中,我们定义了_MainTex作为需要处理的图像,_BlurAmount作为模糊处理的强度参数。在SubShader中,我们定义了两个Pass,第一个用于将当前帧的图像保存到 RenderTexture 上,第二个Pass用于实现运动模糊的实际处理。同时,还添加了一个GrabPass,用于保存当前帧的图像。

四、示例代码

下面是一个实际的示例代码,用于实现一个简单的运动模糊效果:

Camera m_Camera;
RenderTexture m_PrevFrameTexture;
RenderTexture m_CurrentFrameTexture;
Shader m_MotionShader;

private void Start() {
    m_Camera = GetComponent<Camera>();
    m_PrevFrameTexture = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32);
    m_CurrentFrameTexture = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32);
    m_Camera.targetTexture = m_CurrentFrameTexture;
    m_MotionShader = Shader.Find("Custom/MotionBlurShader");
}

private void OnRenderImage(RenderTexture src, RenderTexture dest) {
    m_MotionShader.SetFloat("_BlurAmount", 0.9f);
    Graphics.Blit(src, m_PrevFrameTexture);
    Graphics.Blit(m_CurrentFrameTexture, m_CurrentFrameTexture, m_MotionShader);
    Graphics.Blit(m_CurrentFrameTexture, dest);
}

在代码中,我们首先定义了需要使用的Camera对象、前一帧和当前帧的RenderTexture对象、运动模糊所需的 Shader 对象。在Start()中,我们对前一帧和当前帧的RenderTexture对象进行初始化,并将其绑定到Camera的 targetTexture 上,避免影响到其它渲染内容。在OnRenderImage()回调函数中,我们通过Graphics.Blit()函数进行渲染处理。具体来说,我们首先使用Graphics.Blit()函数对图像进行复制(第一次用),然后再使用Graphics.Blit()函数将当前帧图像绘制到RenderTexture上,并应用运动模糊 m_MotionShader。最后我们将处理结果输出。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:UnityShader使用图像叠加实现运动模糊 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • c# .net 生成图片验证码的代码

    为了在C# .NET中生成图片验证码,我们可以遵循以下步骤: 步骤1:安装NuGet包 我们需要安装 ZXing 和 System.Drawing.Common 两个NuGet包,以便在C#代码中引用。 运行以下命令安装: Install-Package ZXing -Version 1.1.0 Install-Package System.Drawing.…

    C# 2023年5月31日
    00
  • Visual Studio Connected Services 生成http api 调用代码

    生成的代码将和接口对应的参数、返回值一一对应,本文底层使用的工具为NSwag.exe,其他可替代的方案还有AutoSet.exe。本文中生成的代码将在编译过程中自动编译,类似grpc生成代码的模式,如果使用AutoSet则需要手动引入代码。另外也可以使用NSwag对应的vs插件(https://marketplace.visualstudio.com/ite…

    C# 2023年5月11日
    00
  • C#集合Collections购物车Shopping Cart(实例讲解)

    C#集合Collections购物车Shopping Cart(实例讲解) 这篇文章将向您介绍如何使用C#集合实现购物车功能。购物车是电商网站中非常常见的功能之一,它允许用户将他们感兴趣的商品加入到购物车中,随时查看购物车中的商品数量和总价等信息,最终下单付款。 实现思路 为了实现购物车功能,我们需要以下几个步骤: 在页面展示商品列表,并为每个商品提供一个“…

    C# 2023年6月7日
    00
  • C# 实例解释面向对象编程中的单一功能原则(示例代码)

    针对您的问题,以下是C# 实例解释面向对象编程中的单一功能原则的攻略及示例代码。 单一功能原则 单一功能原则(Single Responsibility Principle,SRP)是面向对象编程中的一项核心原则,其核心思想是一个类或模块只负责一项职责(也就是只有一个引起它变化的原因)。这样可以让代码更加易于维护、修改和测试。举例来说,如果一个类负责多项职责…

    C# 2023年6月1日
    00
  • C# FTP操作类分享

    C# FTP操作类分享 在.NET开发中,FTP协议是常用的文件传输方式之一,C#语言也提供了FTP相关的操作类。本文将分享C#中如何操作FTP的实现方法,包括连接FTP服务器、上传文件、下载文件等操作,并附有两条示例说明。 连接FTP服务器 连接FTP服务器通常需要服务器地址、用户名和密码等信息,并使用FTP连接类FtpWebRequest进行连接,示例代…

    C# 2023年6月1日
    00
  • 在winform下实现左右布局多窗口界面的方法

    在WinForm下实现左右布局多窗口界面的方法 1. 思路 在WinForm下实现左右布局多窗口界面,主要的思路是使用SplitContainer控件。SplitContainer控件可分裂成两个窗格,一个在左侧,一个在右侧,可以用来容纳两个不同的控件,以实现布局。 2. 实现步骤 2.1 创建SplitContainer 在VS中创建WinForm窗口,从…

    C# 2023年6月7日
    00
  • 为什么说C语言是永不过时的语言

    C语言是一种高效、灵活、可移植的编程语言,它在计算机科学领域中有着广泛的应用。虽然C语言已经存在了几十年,但它仍然是一种永不过时的语言。以下是几个原因: 1. C语言是一种高效的语言 C语言是一种高效的语言,它可以直接访问计算机的硬件资源,因此可以生成高效的代码。C语言的语法简单,易于学习和使用,同时也具有很高的灵活性。这使得C语言在嵌入式系统、操作系统、编…

    C# 2023年5月15日
    00
  • C#使用LINQ查询操作符实例代码(二)

    首先我们来了解一下这篇文章的大致内容: 本文主要介绍了 C# 使用 LINQ 查询操作符的实例代码,主要包括查询操作符的基础知识、查询语法和方法语法、Lambda表达式等内容。 下面,我们来逐步分析一下这篇文章涉及到的各部分内容。 1. 查询操作符的基础知识 这部分主要介绍了什么是查询操作符,它们的基本结构和分类等。这些基础知识为后续的操作奠定了基础。例如:…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部