首页 > 编程语言 > 详细

unity3d可视化音频接入

时间:2020-07-06 00:53:46      阅读:68      评论:0      收藏:0      [点我收藏+]

一、引用:Unity——炫酷的音频可视化

二、引入AudioVisable

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class AudioVisable : MonoBehaviour
{
    AudioSource audioSource;
    public float[] samples = new float[512];
    float[] freqBand = new float[8];
    float[] bandBuffer = new float[8];
    float[] bufferDecrease = new float[8];

    float[] _freqBandHighest = new float[8];
    public static float[] _audioBand = new float[8];
    public static float[] _audioBandBuffer = new float[8];

    public static float _Amplitude, _AmplitudeBuffer;
    float _AmplitudeHighest;
    void Start()
    {
        audioSource = GetComponent<AudioSource>();
    }

    void CreateAudioBands()
    {
        for (int i = 0; i < 8; i++)
        {
            if (freqBand[i] > _freqBandHighest[i])
            {
                _freqBandHighest[i] = freqBand[i];
            }
            _audioBand[i] = (freqBand[i] / _freqBandHighest[i]);
            _audioBandBuffer[i] = (bandBuffer[i] / _freqBandHighest[i]);
        }
    }

    void Update()
    {
        GetSpectrumAduioSource();
        MakeFrequencyBands();
        BandBuffer();
        CreateAudioBands();
        GetAmplitude();
    }
    void GetAmplitude()
    {
        float _CurrentAmplitude = 0;
        float _CurrentAmplitudeBuffer = 0;
        for (int i = 0; i < 8; i++)
        {
            _CurrentAmplitude += _audioBand[i];
            _CurrentAmplitudeBuffer += _audioBandBuffer[i];
        }
        if (_CurrentAmplitude > _AmplitudeHighest)
            _AmplitudeHighest = _CurrentAmplitude;
        _Amplitude = _CurrentAmplitude / _AmplitudeHighest;
        _AmplitudeBuffer = _CurrentAmplitudeBuffer / _AmplitudeHighest;
    }
    void GetSpectrumAduioSource()
    {
        audioSource.GetSpectrumData(samples, 0, FFTWindow.Blackman);
    }
    void MakeFrequencyBands()
    {
        int count = 0;
        for (int i = 0; i < 8; i++)
        {
            float average = 0;
            int sampleCount = (int)Mathf.Pow(2, i + 1);
            if (i == 7)
            {
                sampleCount += 2;
            }
            for (int j = 0; j < sampleCount; j++)
            {
                average += samples[count] * (count + 1);
                count++;
            }
            average /= count;
            freqBand[i] = average * 10;
        }
    }

    void BandBuffer()
    {
        for (int i = 0; i < 8; i++)
        {
            if (freqBand[i] > bandBuffer[i])
            {
                bandBuffer[i] = freqBand[i];
                bufferDecrease[i] = 0.005f;
            }
            if (freqBand[i] < bandBuffer[i])
            {
                bandBuffer[i] -= bufferDecrease[i];
                bufferDecrease[i] *= 1.2f;
            }
        }
    }
}

挂在Camera上。

三、新建一个cube预制体开启,使用standard材质,打开hdr的外发光emission;再新建一个脚本ParamCube,挂在cube预制体上;

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ParamCube : MonoBehaviour
{

    public int band;
    public float startScale, scaleMultiplier;

    Material material;
    void Start()
    {
        material = GetComponent<MeshRenderer>().materials[0];
    }

    // Update is called once per frame
    void Update()
    {

        transform.localScale = new Vector3(transform.localScale.x, (AudioVisable._audioBandBuffer[band]) * scaleMultiplier + startScale, transform.localScale.z);
        Color color = new Color(AudioVisable._audioBandBuffer[band], AudioVisable._audioBandBuffer[band], AudioVisable._audioBandBuffer[band]);
        material.SetColor("_EmissionColor", color);
        material.SetColor("_Color", color);//新加代码
    }
}

四、订制menu.cs,代码如下:

public class Menu : MonoBehaviour {
    public GameObject menuList;
    public GameObject charCtr;
    bool IsMenu;
    bool menuCanMove;
    int MenuIndex;
    int SndIndex;
    public Image[] Img;
    public Material matOutline;
    public AudioSource snd;
    public AudioClip[] audioClips;
    public GameObject CamSnd;
    // Use this for initialization
    void Start () {
        IsMenu = false;
        menuCanMove = true;
        MenuIndex = 0;
        SndIndex = 0;
    }
    
    // Update is called once per frame
    void Update () {
        if (Input.GetKeyUp(KeyCode.JoystickButton11))  //SELECT,注意:windows中对应的是Button8,有差异。
        {
            if (menuList.activeSelf == false)
            {
                menuList.SetActive(true);
                IsMenu = true;
                charCtr.SetActive(false);
            }
            else
            {
                menuList.SetActive(false);
                IsMenu = false;
                charCtr.SetActive(true);
            }

        }
        if (IsMenu)
        {
            MenuSetFocus();
            MenuSelect();
            ChangeSnd();
        }
    }

    private void ChangeSnd()
    {
        if (Input.GetAxis("Vertical") < -0.3)
        {
            if (menuCanMove)
            {
                if (SndIndex > 0)
                {              
                    SndIndex = SndIndex - 1;
                }
                else
                {
                    SndIndex = 2;
                }
                snd.Stop();
                snd.clip = audioClips[SndIndex];
                menuCanMove = false;
            }

        }
        if (Input.GetAxis("Vertical") == 0)
        {
            menuCanMove = true;
        }
        if (Input.GetAxis("Vertical") > 0.3)
        {

            if (menuCanMove)
            {
                if (SndIndex<2)
                {
                    SndIndex = SndIndex + 1;
                }
                else
                {
                    SndIndex = 0;
                }
                snd.Stop();
                snd.clip = audioClips[SndIndex];
                menuCanMove = false;
            }
        }
    }

    private void MenuSelect()
    {
        if (Input.GetKeyUp(KeyCode.JoystickButton0))   //windows中对应Button2。有差异。
        {
            if (MenuIndex == 0)
            {
                snd.Play();
                snd.loop = true;
                CamSnd.SetActive(true);
            }
            if (MenuIndex == 1)
            {
                snd.Stop();
                snd.loop = false;
                CamSnd.SetActive(false);
            }
        }
    }

    void MenuSetFocus()
    {
        if (Input.GetAxis("Horizontal") < -0.3)
        {
            if (menuCanMove)
            {
                MenuMoveBack();
                menuCanMove = false;
            }
            
        }
        if (Input.GetAxis("Horizontal") ==0)
        {
            menuCanMove = true;
        }
        if (Input.GetAxis("Horizontal") > 0.3)
        {

            if (menuCanMove)
            {
                MenuMoveNext();
                menuCanMove = false;
            }            
        }
        for (int i = 0; i < 2; i++)
        {
            Img[i].material = null;
        }
        Img[MenuIndex].material = matOutline;
        
    }
    void MenuMoveBack()
    {
        int ImgN;
        ImgN =1;
        if (MenuIndex == 0)
        {
            MenuIndex = ImgN;
        }
        else
        {
            MenuIndex = MenuIndex - 1;
        }
    }
    void MenuMoveNext()
    {
        int ImgN =1;
        if (MenuIndex == ImgN)
        {
            MenuIndex = 0;
        }
        else
        {
            MenuIndex = MenuIndex + 1;
        }
    }
}

注意:Joystick的键位对应android与windows平台有差异,代码中已标注。

对应input 设置如下:

技术分享图片

五、引用:Unity 2D图片添加加外边框Shader,为选择到的图片做外边框。建立新standard Shader,名为SpritesOutline,代码如下:

Shader "Custom/SpritesOutline"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Main texture Tint", Color) = (1,1,1,1)

        [Header(General Settings)]
        [MaterialToggle] _OutlineEnabled ("Outline Enabled", Float) = 1
        [MaterialToggle] _ConnectedAlpha ("Connected Alpha", Float) = 0
        [HideInInspector] _AlphaThreshold ("Alpha clean", Range (0, 1)) = 0
        _Thickness ("Width (Max recommended 100)", float) = 10
        [KeywordEnum(Solid, Gradient, Image)] _OutlineMode("Outline mode", Float) = 0
        [KeywordEnum(Contour, Frame)] _OutlineShape("Outline shape", Float) = 0
        [KeywordEnum(Inside under sprite, Inside over sprite, Outside)] _OutlinePosition("Outline Position (Frame Only)", Float) = 0

        [Header(Solid Settings)]
        _SolidOutline ("Outline Color Base", Color) = (1,1,1,1)

        [Header(Gradient Settings)]
        _GradientOutline1 ("Outline Color 1", Color) = (1,1,1,1)
        _GradientOutline2 ("Outline Color 2", Color) = (1,1,1,1)
        _Weight ("Weight", Range (0, 1)) = 0.5
        _Angle ("Gradient Angle (General gradient Only)", float) = 45
        //[KeywordEnum(General, Frame directed)] _FrameMode("Frame Mode (Frame Only)", Float) = 0

        [Header(Image Settings)]
        _FrameTex ("Frame Texture", 2D) = "white" {}
        _ImageOutline ("Outline Color Base", Color) = (1,1,1,1)
        [KeywordEnum(Stretch, Tile)] _TileMode("Frame mode", Float) = 0
    }

    SubShader
    {
        Tags
        { 
            "Queue"="Transparent" 
            "IgnoreProjector"="True" 
            "RenderType"="Transparent" 
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha

        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile _ PIXELSNAP_ON
            #pragma exclude_renderers d3d11_9x

            #include "UnityCG.cginc"
            
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
            };

            fixed4 _Color;
            fixed _Thickness;
            fixed _OutlineEnabled;
            fixed _ConnectedAlpha;
            fixed _OutlineShape;
            fixed _OutlinePosition;
            fixed _OutlineMode;

            fixed4 _SolidOutline;

            fixed4 _GradientOutline1;
            fixed4 _GradientOutline2;
            fixed _Weight;
            fixed _AlphaThreshold;
            fixed _Angle;
            //fixed _FrameMode;

            fixed4 _ImageOutline;
            fixed _TileMode;

            v2f vert(appdata_t IN)
            {
                v2f OUT;
                OUT.vertex = UnityObjectToClipPos(IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif

                return OUT;
            }

            sampler2D _MainTex;
            sampler2D _AlphaTex;
            float _AlphaSplitEnabled;
            uniform float4 _MainTex_TexelSize;

            sampler2D _FrameTex;
            uniform float4 _FrameTex_TexelSize;
            uniform float4 _FrameTex_ST;

            fixed4 SampleSpriteTexture (float2 uv)
            {
                float2 offsets;
                if((_OutlinePosition != 2 && _OutlineShape == 1) || _OutlineEnabled == 0) // not outside and frame
                {
                    offsets = float2(0, 0);
                }
                else
                {
                    offsets = float2(_Thickness * 2, _Thickness * 2);
                }
                float2 bigsize = float2(_MainTex_TexelSize.z, _MainTex_TexelSize.w);
                float2 smallsize = float2(_MainTex_TexelSize.z - offsets.x, _MainTex_TexelSize.w - offsets.y);

                float2 uv_changed = float2
                (
                    uv.x * bigsize.x / smallsize.x - 0.5 * offsets.x / smallsize.x,
                    uv.y * bigsize.y / smallsize.y - 0.5 * offsets.y / smallsize.y
                );

                if(uv_changed.x < 0 || uv_changed.x > 1 || uv_changed.y < 0 || uv_changed.y > 1)
                {
                    return float4(0, 0, 0, 0);
                }

                fixed4 color = tex2D (_MainTex, uv_changed);

#if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
                if (_AlphaSplitEnabled)
                    color.a = tex2D (_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED

                return color;
            }

            bool CheckOriginalSpriteTexture (float2 uv, bool ifZero)
            {
                float thicknessX = _Thickness / _MainTex_TexelSize.z;
                float thicknessY = _Thickness / _MainTex_TexelSize.w;
                int steps = 100;
                float angle_step = 360.0 / steps;

                float alphaThreshold = _AlphaThreshold / 10;
                float alphaCount = _AlphaThreshold * 10;

                // check if the basic points has an alpha to speed up the process and not use the for loop
                bool outline = false;
                float alphaCounter = 0;

                if(ifZero)
                {
                    
                }
                else
                {
                    outline =     SampleSpriteTexture(uv + fixed2(0, +thicknessY)).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(0, -thicknessY)).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(+thicknessX, 0)).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(-thicknessX, 0)).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(+thicknessX * cos (3.14 / 4), -thicknessY * sin (3.14 / 4))).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(-thicknessX * cos (3.14 / 4), +thicknessY * sin (3.14 / 4))).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(-thicknessX * cos (3.14 / 4), -thicknessY * sin (3.14 / 4))).a > alphaThreshold ||
                                SampleSpriteTexture(uv + fixed2(+thicknessX * cos (3.14 / 4), +thicknessY * sin (3.14 / 4))).a > alphaThreshold;
                }
                if(outline) return outline;

                for(int i = 0; i < steps; i++) // high number and not a variable to avoid stupid compiler bugs
                {
                    float angle = i * angle_step * 2 * 3.14 / 360;
                    if(ifZero && SampleSpriteTexture(uv + fixed2(thicknessX * cos(angle), thicknessY * sin(angle))).a == 0)
                    {
                        alphaCounter++;
                        if(alphaCounter >= alphaCount)
                        {
                            outline = true;
                            break;
                        }
                    }
                    else if(!ifZero && SampleSpriteTexture(uv + fixed2(thicknessX * cos(angle), thicknessY * sin(angle))).a > alphaThreshold)
                    {
                        outline = true;
                        break;
                    }
                }

                return outline;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                float thicknessX = _Thickness / _MainTex_TexelSize.z;
                float thicknessY = _Thickness / _MainTex_TexelSize.w;

                fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;

                c.rgb *= c.a;

                fixed alpha;

                fixed4 outlineC = fixed4(0, 0, 0, 1);

                if(_OutlineEnabled != 0)
                {
                    if(_OutlineMode == 0) // Solid
                    {
                        outlineC = _SolidOutline;

                        if(_ConnectedAlpha != 0)
                        {
                            outlineC.a *= _Color.a;
                        }
                        outlineC.rgb *= outlineC.a;
                    }
                    else if(_OutlineMode == 1) // Gradient
                    {
                        float x = IN.texcoord.x;
                        float y = IN.texcoord.y;

                        float ratio1 = 0;
                        float ratio2 = 0;

                        if(_OutlineShape == 0) // contour
                        {
                            if(
                                ((_OutlinePosition != 2 && _OutlineShape == 1) && c.a != 0 &&  // inside and frame
                                    (
                                        IN.texcoord.y + thicknessY > 1 || 
                                        IN.texcoord.y - thicknessY < 0 || 
                                        IN.texcoord.x + thicknessX > 1 || 
                                        IN.texcoord.x - thicknessX < 0 ||
                                        CheckOriginalSpriteTexture(IN.texcoord, true)
                                    )
                                )
                                ||
                                ((_OutlinePosition == 2 || _OutlineShape != 1) && c.a == 0 &&   // outside or contour
                                    CheckOriginalSpriteTexture(IN.texcoord, false)
                                )
                            )
                            {
                                if(_Angle >= 360)
                                {
                                    int div = _Angle / 360;
                                    _Angle = (_Angle / 360 - div) * 360;
                                }
                                _Angle *= 2 * 3.14 / 360;

                                ratio1 = (0.5 - x) * cos(_Angle) + (0.5 - y) * sin(_Angle) + 0.5;
                                ratio2 = (x - 0.5) * cos(_Angle) + (y - 0.5) * sin(_Angle) + 0.5;

                                ratio1 *= 2 * _Weight;
                                ratio2 *= 2 * (1 - _Weight);

                                if(_ConnectedAlpha != 0)
                                {
                                    _GradientOutline1.a *= _Color.a;
                                    _GradientOutline2.a *= _Color.a;
                                    //outlineC.rgb *= outlineC.a;
                                }
                                _GradientOutline1.rgb *= _GradientOutline1.a;
                                _GradientOutline2.rgb *= _GradientOutline2.a;
                                outlineC = _GradientOutline1 * ratio1 + _GradientOutline2 * ratio2;
                            }
                        }
                        else if(_OutlineShape == 1) // frame
                        {
                            if(    IN.texcoord.y + thicknessY > 1 ||
                                IN.texcoord.y - thicknessY < 0 ||
                                IN.texcoord.x + thicknessX > 1 ||
                                IN.texcoord.x - thicknessX < 0)
                            {
                                // between down left to up left
                                if (y * thicknessX - x * thicknessY > 0 &&
                                    y * thicknessX + x * thicknessY - thicknessX < 0 &&
                                    x < 0.5f)
                                {
                                    ratio1 = 1 - x / thicknessX;
                                    ratio2 = x / thicknessX;
                                }
                                // between down left to down right
                                else if (y * thicknessX - x * thicknessY < 0 &&
                                        y * thicknessX + x * thicknessY - thicknessY < 0 &&
                                        y < 0.5f)
                                {
                                    ratio1 = 1 - y / thicknessY;
                                    ratio2 = y / thicknessY;
                                }
                                // between down right to up right
                                else if (y * thicknessX - x * thicknessY - thicknessX + thicknessY < 0 &&
                                        y * thicknessX + x * thicknessY - thicknessY > 0 &&
                                        x > 0.5f)
                                {
                                    ratio1 = (x - 1) / thicknessX + 1;
                                    ratio2 = -(x - 1) / thicknessX;
                                }
                                // between up left to up right
                                else if (y * thicknessX - x * thicknessY - thicknessX + thicknessY > 0 &&
                                        y * thicknessX + x * thicknessY - thicknessX > 0 &&
                                        y > 0.5f)
                                {
                                    ratio1 = (y - 1) / thicknessY + 1;
                                    ratio2 = -(y - 1) / thicknessY;
                                }

                                ratio1 *= 2 * _Weight;
                                ratio2 *= 2 * (1 - _Weight);

                                if(_ConnectedAlpha != 0)
                                {
                                    _GradientOutline1.a *= _Color.a;
                                    _GradientOutline2.a *= _Color.a;
                                    //outlineC.rgb *= outlineC.a;
                                }
                                _GradientOutline1.rgb *= _GradientOutline1.a;
                                _GradientOutline2.rgb *= _GradientOutline2.a;
                                outlineC = _GradientOutline1 * ratio1 + _GradientOutline2 * ratio2;
                            }
                        }
                    }
                    else if(_OutlineMode == 2) // Image
                    {
                        outlineC = _ImageOutline;
                        fixed2 frame_coord;

                        if(_TileMode == 0)
                        {
                            frame_coord = IN.texcoord;
                        }
                        else if(_TileMode == 1)
                        {
                            frame_coord = fixed2
                            (
                                _FrameTex_ST.x * IN.texcoord.x * _MainTex_TexelSize.z / _FrameTex_TexelSize.z - _FrameTex_ST.z,
                                _FrameTex_ST.y * IN.texcoord.y * _MainTex_TexelSize.w / _FrameTex_TexelSize.w - _FrameTex_ST.w
                            );

                            if(frame_coord.x > 1)
                            {
                                frame_coord = fixed2
                                (
                                    frame_coord.x - floor(frame_coord.x),
                                    frame_coord.y
                                );
                            }
                            if(frame_coord.y > 1)
                            {
                                frame_coord = fixed2
                                (
                                    frame_coord.x,
                                    frame_coord.y - floor(frame_coord.y)
                                );
                            }
                        }
                        fixed4 text = tex2D(_FrameTex, frame_coord);

                        text.rgb *= text.a;

                        outlineC.rgb *= text.rgb;
                        outlineC.a *= text.a;

                        if(_ConnectedAlpha != 0)
                        {
                            outlineC.a *= _Color.a;
                        }
                        outlineC.rgb *= outlineC.a;
                    }

                    if(_OutlineShape == 1) // Frame
                    {
                        if(    IN.texcoord.y + thicknessY > 1 ||
                            IN.texcoord.y - thicknessY < 0 ||
                            IN.texcoord.x + thicknessX > 1 ||
                            IN.texcoord.x - thicknessX < 0)
                        {
                            if(_OutlinePosition == 0 && c.a != 0 && _Thickness > 0)
                            {
                                return c;
                            }
                            else
                            {
                                return outlineC;
                            }
                        }
                        else
                        {
                            return c;
                        }
                    }
                    else if(_OutlineShape == 0 && _Thickness > 0) // Contour
                    {
                        if((_OutlinePosition != 2 && _OutlineShape == 1) && c.a != 0 && // inside and frame
                            (
                                IN.texcoord.y + thicknessY > 1 ||
                                IN.texcoord.y - thicknessY < 0 ||
                                IN.texcoord.x + thicknessX > 1 ||
                                IN.texcoord.x - thicknessX < 0 || 
                                CheckOriginalSpriteTexture(IN.texcoord, true)
                            )
                        )
                        {
                            return outlineC;
                        }
                        else if((_OutlinePosition == 2 || _OutlineShape != 1) && c.a == 0 && // outside orcontour
                                (
                                    CheckOriginalSpriteTexture(IN.texcoord, false)
                                )
                            )
                        {
                            return outlineC;
                        }
                        else
                        {
                            return c;
                        }
                    }
                    else
                    {
                        return c;
                    }
                }
                else
                {
                    return c;
                }

                return c;
                //return c;
            }
        ENDCG
        }
    }
}

建立material,选择刚建好的shader,

技术分享图片

效果:

技术分享图片

unity3d可视化音频接入

原文:https://www.cnblogs.com/guaike01/p/13252469.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!