请选择 进入手机版 | 继续访问电脑版

查看: 901|回复: 2

[原创] 科幻特效:UI中的噪波效果

[复制链接]

911

主题

1571

帖子

2万

贡献

管理员

Rank: 9Rank: 9Rank: 9

积分
20200
QQ
发表于 2017-10-7 02:41:33 | 显示全部楼层 |阅读模式
Unity中实现一些科幻特效,需要在UI或者物体表面产生一些颗粒状的波动。今天这篇文章将由Unity开发者李晔,为大家分享在AR中实现UI嗓波效果的方法。

介绍嗓波

噪波也叫噪声或噪点,在图像中往往表现为不规则的杂点或波纹。科幻影视作品中较为常见。例如:空间的扭曲效果,机械表面的换装效果,受到震荡波影响的表面颤抖效果,模拟全息通信不稳定效果等,这些都属于噪波效果。随着游戏中对画面效果要求的提升以及VR技术的出现,特效的需求已经不再仅仅满足于手游级别的粒子光影,尤其是在AR/MR技术中由于加入了现实影像的对比,使得特效的设计标准越来越多地参考影视中的作品以提高与真实世界的协调与融合度。噪波效果是影视特效中常用的一种方式,合理的加入一些噪波效果,可以在保证真实度的前提下很大程度上提升整个画面的科幻效果。

下面以AR画面中UI界面的出现为例,为大家分享在UI里加入噪波效果的实现方法。

AR中实现UI的嗓波效果

实现UI从无到逐渐出现,扭曲波动最后稳定显示的效果。如下图所示:

Noise.gif


效果使用C#脚本与Shader结合实现,用一个噪波图片,提取其中的噪波信息与主纹理叠加。

13.jpg


定义Shader,接收C#传来的振动值与振动进度。获取噪波纹理中的噪波偏移值使顶点函数中的坐标值发生偏移。用振动进度来控制显示的Alpha透明度,为了让透明度的变化更平滑,给振动进度乘以二次方。

[C#] 纯文本查看 复制代码
Shader "Noise/UI_Noise"
{
        Properties
        {
                _Color("Color", Color) = (1,1,1,1)
                //颜色
                _MainTex("MainTex", 2D) = "white" {}
                //主纹理
                _NoiseTex("NoiseTex", 2D) = "white" {}
                //噪波纹理
                _ShakeStrength("ShakeStrength", Float) = 1
                //振动值
        }

                SubShader
        {
                Blend SrcAlpha OneMinusSrcAlpha

                Pass
        {
                CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
#include "UnityUI.cginc"

                struct a2v
        {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
        };

        struct v2f
        {
                float4 vertex   : SV_POSITION;
                fixed4 color : COLOR;
                half2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
        };

        fixed4 _Color;

        sampler2D _MainTex;
        sampler2D _NoiseTex;

        fixed _ShakeStrength;
        fixed _ProgressRate;


        v2f vert(a2v v)
        {
                v2f f;
                f.worldPosition = v.vertex;

                float3 noiseOffset = tex2Dlod(_NoiseTex, float4(v.texcoord* _Time, 0.0, 0.0)).rgb;
                //计算噪波偏移

                float strength = _ShakeStrength;

                noiseOffset = noiseOffset *strength;

                f.worldPosition.xy += noiseOffset.xy * 15;
                //噪波的扭曲程度

                f.vertex = UnityObjectToClipPos(f.worldPosition);

                f.texcoord = v.texcoord;

                f.color = v.color * _Color;

                f.color.a *= pow(_ProgressRate,2);

                return f;
        }


        fixed4 frag(v2f f) : SV_Target
        {
                
                half4 color = (tex2D(_MainTex, f.texcoord)) * f.color;

                return color;
        }
                ENDCG
        }

        }
}



在C#脚本中用曲线来控制波动时间与波动,用一个浮点数来调控振动幅度。代码如下:

[C#] 纯文本查看 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Noise_UI : MonoBehaviour
{

    public Graphic graphic;
    //要实现噪波的UI
    public float intensity = 1f;
    //强度系数
    public AnimationCurve curve = new AnimationCurve(new Keyframe(0f, 0f, 0f, 0f), new Keyframe(0.5f, 1f, 0f, 0f), new Keyframe(1f, 0f, 0f, 0f));
    //振动与时间的曲线
    public Material material_Noice;
    //叠加的噪波材质
    private int shakeStrength;
    //波动强度
    private int progressRate;
    //波动进度
    private float lifeTime = 0;
    //噪波抖动的生命周期
    private float currentTime = 0f;
    //当前波动时间

    void Awake()
    {
        shakeStrength = Shader.PropertyToID("_ShakeStrength");  //获取shaderValue的属性标识符

        progressRate = Shader.PropertyToID("_ProgressRate");  //从"_NormalizedTime"中获取shaderValue的属性标识符       
    }

    public void Shake()
    {
        graphic.material = material_Noice;

        StartCoroutine(Interactive());
    }

    private IEnumerator Interactive()
    {
        currentTime = 0f; //已运行时间

        lifeTime = curve.keys[curve.length - 1].time;   //从曲线中获取振动的生命周期

        while (currentTime < lifeTime)  //如果在生命周期内
        {
            currentTime += Time.deltaTime;

            var shakeValue = curve.Evaluate(currentTime) * intensity;

            graphic.material.SetFloat(shakeStrength, shakeValue);  //把振动值传递给Shader

            graphic.material.SetFloat(progressRate, currentTime / lifeTime);  //把运行进度传递给Shader

            yield return null;   //等待画面刷新
        }
        graphic.material = null;
    }
}


指定UI和噪波纹理,调整时间曲线就实现UI的噪波效果了。

结语

Unity可以实现风格各异的超酷炫的游戏特效,希望大家可以应用到自己的项目中。后面我们还会继续为大家分享更多特效方面的精彩内容在Unity官方中文社区(unitychina.cn),请保持关注。

11.jpg
12.jpg

0

主题

3

帖子

85

贡献

初级UU族—2级

Rank: 2

积分
85
发表于 2017-10-7 05:23:57 | 显示全部楼层
能给shader中代码注释一下就好了~

3

主题

47

帖子

415

贡献

初级UU族—3级

Rank: 3Rank: 3

积分
415
发表于 2017-10-9 03:48:36 | 显示全部楼层
该好好研究学习一下shader了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表