欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity 屏幕特效 之 热浪扭曲效果的实现

程序员文章站 2022-07-12 23:30:27
...

Unity 屏幕特效 之 热浪扭曲效果的实现

 

目录

Unity 屏幕特效 之 热浪扭曲效果的实现

一、简介

二、关键技术

三、注意事项

四、效果预览

五、实现步骤


 

一、简介

所谓屏幕后处理,简单来说就是渲染流水线的最后阶段,对由整个场景生成的一张图片进行处理,比如HDR,运动模糊等等效果,通过屏幕空间的后处理,可以整体改变整个游戏的风格或者效果。所以,要制作屏幕后处理,我们需要两样东西,一个是用于渲染后处理效果的shader,而另一个是我们需要调用这个渲染的脚本。
 

实现原理:

  •     使用一张噪音云图来获取随机偏移量,然后赋值给主图移动uv值来实现扭曲,实现热浪效果

 

二、关键技术

1、在 Shader 中,获取噪音云图的uv,赋给主图uv,并且uv随时间变化;  

 2、OnRenderImage函数每帧渲染完全部内容后执行,我们在每一帧设置Material的各项参数,通过Material.SetXXX("name",value)可以向shader中传递各种参数;

3、关键代码

float4 noise = tex2D(_NoiseTex, i.uv - _Time.xy * _NoiseTimeScale);
float2 offset = noise.xy * _UVScale ;
return tex2D(_MainTex, i.uv + offset);

三、注意事项

1、各种后处理效果可以叠加,这里的dest并不一定就是屏幕。不过后处理是很耗费性能的,一方面是pixel shader全屏幕overdraw,另一方面,一个rendertexture的内存占用很大,尤其是大分辨率手机上,多个后处理效果可能造成内存耗尽,程序崩溃;

2、注意判断屏幕特效是否支持可以用;

3、注意参数值根据实际效果,合理调节;

 

四、效果预览

Unity 屏幕特效 之 热浪扭曲效果的实现

五、实现步骤

1、新建Unity工程,导入模型,新建脚本,如下

Unity 屏幕特效 之 热浪扭曲效果的实现

2、新建两个camera,Left_Camera 不挂载脚本不做处理,Right_Camera 挂在脚本做扭曲处理,两相机视口作为效果调节对比,如下

Unity 屏幕特效 之 热浪扭曲效果的实现

3、测试效果

Unity 屏幕特效 之 热浪扭曲效果的实现

4、shader 脚本

Shader "Unlit/WaveWarp"
{
    Properties
    {
        _MainTex("Base (RGB)", 2D) = "white" {}
        _NoiseTex("Noise (RGB)", 2D) = "white" {}
        _UVScale("uv scale ", Range(0.0, 1.0)) = 1.0
        _NoiseTimeScale("Noise Time Scale ", Range(0,1)) = 1
    }
    SubShader
    {
        Pass{
            CGPROGRAM
            #pragma vertex vert_img  
            #pragma fragment frag  

            #include "UnityCG.cginc"  

            uniform sampler2D _MainTex;
            uniform sampler2D _NoiseTex;
            fixed _UVScale;
            float _NoiseTimeScale;

            fixed4 frag(v2f_img i) : COLOR
            {
                float4 noise = tex2D(_NoiseTex, i.uv - _Time.xy * _NoiseTimeScale);
                float2 offset = noise.xy * _UVScale ;
                return tex2D(_MainTex, i.uv + offset);
            }
            ENDCG
        }
    }
    FallBack "Diffuse"

}

5、C# 脚本

using UnityEngine;

//非运行时也触发效果
[ExecuteInEditMode]
//屏幕后处理特效一般都需要绑定在摄像机上
[RequireComponent(typeof(Camera))]
//提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质
public class ScreenPostEffectBase : MonoBehaviour
{

    //Inspector面板上直接拖入
    public Shader shader = null;
    private Material _material = null;
    public Material _Material
    {
        get
        {
            if (_material == null)
                _material = GenerateMaterial(shader);
            return _material;
        }
    }

    //根据shader创建用于屏幕特效的材质
    protected Material GenerateMaterial(Shader shader)
    {
        // 系统是否支持
        if (!SystemInfo.supportsImageEffects)
        {            
            return null;
        }

        if (shader == null)
            return null;
        //需要判断shader是否支持
        if (shader.isSupported == false)
            return null;
        Material material = new Material(shader);
        material.hideFlags = HideFlags.DontSave;
        if (material)
            return material;
        return null;
    }

  void OnDisable()
    {
        if (_material != null)
        {
            DestroyImmediate(_material);
        }
    }

}
using UnityEngine;

public class WaveWarp : ScreenPostEffectBase
{
    public Texture noiseTexure;
    [Range(0.0f, 1.0f)]
    public float noiseTimeScale = 1.0f;
    [Range(0.0f, 1.0f)]
    public float uvScale = 0.15f;


    void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
    {
        if (_Material != null)
        {
            _Material.SetFloat("_UVScale", uvScale);
            _Material.SetFloat("_NoiseTimeScale", noiseTimeScale);
            _Material.SetTexture("_NoiseTex", noiseTexure);

            Graphics.Blit(sourceTexture, destTexture, _Material);
        }
        else
        {
            Graphics.Blit(sourceTexture, destTexture);
        }
    }

}