两年前,为项目做演示视频的时候用了一个AE模板弄了一个音乐可视化效果,当时也没想过会要做到项目里面。

后来项目落地的时候用了另外一个效果。前一段时间在学习图形学,突然想起这件事,对于那个未能完成的效果有点不死心,于是重新研究了一下,大致完成了这个效果:

先说下音乐可视化的原理。

原理:

  • 通过unity的内置函数采样音乐频域的数值,我们项目中因为是流媒体传输,所以方法有所不同,总之就是通过一系列代码获取音乐频域数值(关于音乐的频域,时域这些有一大堆的理论,还涉及到非常复杂的算法,有兴趣的可以去百度研究下)。
  • 将频域的数值记录下来,写入一张256像素宽度的贴图,这里参考的是某位大神的脚本,但是因为时间久远,找不到原文了,所以链接也没法给出来。
  • 写一个shader,采样音乐图,根据获取的数值计算想要的效果。

步骤:

  • 在场景中创建一个plane,挂上一个AudioSource 组件,选一首你喜欢的音乐,设置一下播放和循环:

  • 创建脚本,采样音乐的数值,并记录到一张贴图里,并且每帧更新。然后将脚本也挂在plane上面。这里要注意下对更新数值的延迟处理,会让最终的效果有个连续增长和连续减少的效果,如果不做这一步,就会让效果不够连续,会卡卡的感觉。

脚本代码:

using UnityEngine;
using System.Collections;
public class MusicTexture: MonoBehaviour {public Material material;[Range(0.0005f,0.5f)]public float delay = 0.0166f;public float multiplyer = 1.0f;[HideInInspector][System.NonSerialized]public float[] spactrumDataDelay;[HideInInspector][System.NonSerialized]public Texture2D dataTexture;public FilterMode filterMode; int numSamples = 512;void Start(){ dataTexture = new Texture2D(numSamples, 1, TextureFormat.RGBA32, false);dataTexture.filterMode = filterMode;material.SetTexture("_MusicData", dataTexture);spactrumDataDelay = new float[numSamples];}void Update() {float[] spectrum = new float[numSamples];//音乐采样GetComponent<AudioSource>().GetSpectrumData(spectrum, 0, FFTWindow.BlackmanHarris);int i = 1;while (i < numSamples+1) {float newData =  (spectrum[i - 1]*1.0f*multiplyer);//对更新数据进行延迟处理if(newData>spactrumDataDelay[i-1]){spactrumDataDelay[i-1] += (delay*Time.deltaTime);if(spactrumDataDelay[i-1] > newData){spactrumDataDelay[i-1] = newData;}}else{spactrumDataDelay[i-1] -= (delay*Time.deltaTime);if(spactrumDataDelay[i-1] <0f){spactrumDataDelay[i-1] = 0f;}}              // 设置像素颜色dataTexture.SetPixel(i - 1, 1, new Color((spactrumDataDelay[i - 1] * 255.0f), 0, 0, 0));i++;}// 更新texturedataTexture.Apply();}
}
  • 编写shader,采样传入的音乐贴图,然后用算法做出可视化效果。把plane的材质用上这个shader就可以了。

思路:利用了画圆的算法,用一个圆减另外一个圆画出圆环。将圆弧等分,圆弧弧度对应音乐贴图的UV.x。根据采样值改变圆环的粗细。然后再画一个细一点的圆环,用之前的减去它。

这样说可能有点拗口,下面用图来说明:

画一个圆;

减去一个圆,先画个圆环;

将圆弧等分,并且按照采样值,改变圆环粗细(两个圆的半径);

再画一个,改细一点,并且在每一小段弧中间要加上间隔;

间隔的代码,用step函数对圆弧做处理:

float Arc = step(distance(0.5, frac(arc * divides)), 0.46);
arcIn *= Arc;

相减。

当然思路是这样,代码中用到了各种函数,次序会有些不同。但是结果是一样的。最后加上背景虚化和颜色变化的效果,增加一些参数。

贴上全部shader代码:

Shader "Chain/Effects/MusicEffects"
{Properties{_Color("Color",Color) = (1,1,1,1)//音乐数据图输入_MusicData("MusicData (Alpha)", 2D) = "black" {}//将圆弧分成多少段_Divides("Divides",int) = 64//背景平滑度_Antialias("Antialias",Range(0,1)) = 0.1//圆半径_radius("Radius",Range(0,1)) = 0.2//变化参数_rayOffset("RayOffset",Range(0,1)) = 0.1//亮度_Brightness("Brightness",Range(0,2)) = 1}SubShader{Tags { "RenderType" = "Transparency" "IgnoreProjection" = "True""RenderQueue" = "Transparency"}Blend SrcAlpha OneZWrite OffPass{CGPROGRAM#pragma vertex vert#pragma fragment frag          #include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MusicData;float4 _MusicData_ST;int _Divides;fixed4 _Color;fixed _Antialias;fixed _OutAntialias;fixed _radius;fixed _rayOffset;fixed _Brightness;//用于变色的旋转矩阵float2x2 rotate2d(float angle) {return float2x2(cos(angle),-sin(angle),sin(angle),cos(angle));}//画特效形状的函数fixed2 effectShape(float2 uv, fixed2 center, float radius, float antialias, float offset,fixed arc,int divides) {float2 radiusVector = center - uv;float len = length(radiusVector);//圈圈内圆半径,根据音乐数据减小float radiusIn = radius - offset;//圈圈外圆半径,根据音乐数据增大,设定一个最小增大值,一定会比内圆大0.005float radiusOut = radius + offset + 0.005;//画内圈fixed arcIn = step(len, radiusOut) - step(len, radiusIn);//根据格子数取余,每一格来一个间隔float Arc = step(distance(0.5, frac(arc * divides)), 0.46);arcIn *= Arc;//外圈fixed arcOut = step(len, radiusOut - 0.004) - step(len, radiusIn - 0.004);//增加一个渐变输出,用于背景输出fixed arcgradient = smoothstep(radiusOut + antialias + 0.05, radiusOut, len) - smoothstep(radiusIn - 0.05 + antialias,radiusIn - 0.05, len);fixed arc_col = abs(arcOut - arcIn);arc_col = clamp(arc_col, 0.1, 1);//测试背景渐变效果//arc_col =arcIn;//输出方块效果//arc_col = arcgradient;//输出为两个通道,一个用来存储画的线,一个用来存储背景的渐变return fixed2(arc_col, arcgradient);}v2f vert(appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MusicData);return o;}fixed4 frag(v2f i) : SV_Target{//将坐标转换为圆圈的弧度坐标,然后用这个坐标去采样音乐图,获得音乐数据去改变圆圈的半径等fixed arcU = atan2(i.uv.x * 2 - 1,i.uv.y * 2 - 1) / UNITY_TWO_PI;//将弧度范围从-1~1转换到0~1arcU = arcU * 0.5 + 0.5;//取样音乐图的数据,将uv分为格子,取格子起始点的值,因为我们的音乐流数据很奇怪,所以前面加了1-,正常的话去掉fixed rayoffset = tex2D(_MusicData,float2(floor((arcU)*_Divides) / _Divides,0)).r;//圆圈中心点设在坐标中心fixed2 center = fixed2(0.5,0.5);//平滑范围最大不超过0.125fixed inantialias = _Antialias * 0.125;//以时间为旋转速度因子变色的函数fixed2 v = mul(rotate2d(_Time.y) , i.uv);//绘制fixed2 shape = effectShape(i.uv, center, _radius, inantialias, rayoffset*_rayOffset,arcU,_Divides);fixed4 final;//分拆函数的输出,分别作为背景和线条叠加起来final.rgb = shape.y * fixed3(v.x, v.y, 0.7 - v.y*v.x) + shape.x;final.rgb *= _Color * _Brightness;final.a = shape.x*0.5 + shape.y*0.2;return final;}ENDCG}}
}

总结:

我在做这个效果的时候是根据直观的视觉效果来分析的,还没有考虑优化,只是目测了一下帧率,目前这个效果应该在移动平台上问题不大。

另外如果要替代这个效果,而且算法比较复杂的话,可以考虑把背景发光等效果做成图片叠加可能会更省效率,项目中我是直接用图片替代了整个圆环的算法,不过效率孰优孰劣却没有很严谨的去验证了。

目前只是一个基础效果,如果实际应用的话,加上抗锯齿,还可以考虑加上bloom效果,再配合一些粒子特效应该会很棒,更多效果,可以参考ShaderToy。

后来又看了一下AE源文件的处理方法,发现用到了粒子,模糊,查找边缘后处理等手段。不知道以后会不会有时间再研究一下这种做法。

Unity音乐可视化效果研究相关推荐

  1. python音乐可视化效果_我的音悦台——音乐可视化的Python实现

    继音乐可视化的WEB实现之后,我继续研究基于Python的webpy实现 有关Python的web开发--简单开发环境的搭建(复杂的我也不会): 1.安装Python,路由器的话简单下载插件本地安装就 ...

  2. python音乐可视化效果_Python 一个漂亮的音乐节奏可视化方案!我觉得可行

    filezilla怎么用,e宠,甄[传小说全集 国外有个网友(u/avirzayev)分享了他的可视化方案.上方的视频就是用他的方案可视化Tattoo.mp3得到的结果,大家可以欣赏一下. 这份代码确 ...

  3. python音乐可视化效果_Python 一个漂亮的音乐节奏可视化方案!我觉得可行!

    国外有个网友(u/avirzayev)分享了他的可视化方案.上方的视频就是用他的方案可视化Tattoo.mp3得到的结果,大家可以欣赏一下. 这份代码确实有效地跟上了音乐的节奏,如果能加强可视化效果, ...

  4. python音乐可视化效果_Python 一个漂亮的音乐节奏可视化方案

    相信很多人都有这样的疑问:如何用Python将音乐的节奏可视化出来?我曾有过一篇文章:Python 提取音乐频谱并可视化,也不过是浅尝辄止,没有完成精美的可视化,只是将频谱用折线图进行了可视化. 国外 ...

  5. Unity音频采样器(用于Unity音乐可视化)

    主要用于音乐可视化 教程已经很多了,但是没有拖上来就能用的 直接提供组件,欢迎复制黏贴 using System.Collections; using System.Collections.Gener ...

  6. python音乐可视化效果_Python数据可视化 | 网易云音乐年度歌曲

    网易云音乐2018年度听歌报告-遇见你,真好. 相信有不少人在上周,应该已经看过自己网易云音乐的年度报告了. 小F也是去凑凑热闹,瞅了一波自己的年度听歌报告. 那么你在云村又听了多少首歌,听到最多的歌 ...

  7. python音乐可视化效果_python 音频可视化

    2020-07-18 11:50:05 更新一个线条颜色渐变的方法: import matplotlib.pyplot as plt import numpy as np import pyaudio ...

  8. Unity 音乐可视化(音乐频谱控制物体的运动)

    1.实现思想:通过改变物体的坐标值在update函数中实时更新物体的位置. using UnityEngine; using System.Collections;public class NewBe ...

  9. Unity 音乐可视化

    首先感谢 FransicZhang的博客,链接:https://blog.csdn.net/fransiczhang/article/details/78093131 下面获取输入音频及处理代码主要根 ...

最新文章

  1. php怎么接受,如何使php://input接收到另一个php的数据
  2. Javascript prototype理解
  3. 用python画xy散点图-python画时间序列散点图
  4. 对于按成本组件结构(要素)还原
  5. VS中怎样打开MSDN帮助文档
  6. 2019牛客暑期多校训练营(第十场)C - Gifted Composer (二分+哈希)
  7. 建造者模式源码解析(jdk-guava+mybatis)
  8. OpenCV与图像处理学习十二——图像形状特征之HOG特征
  9. 浅谈OpenGL、OpenGL ES
  10. runtime—新手必学
  11. BeautifulSoup库findAll()、find()方法详解
  12. oracle同一天,Oracle统计一个小时内,一天内、一个星期内、一个月内、一年内的数据...
  13. java解析搜狗词库scel文件到txt
  14. Sonic开源的云真机测试平台搭建记录
  15. 我,是广工的一名电商男孩。喜欢唱跳 rap 我们终究会遇见 有缘 李伟鸿
  16. Word文档输出为pdf时目录出现“错误!未定义书签!”
  17. opta planner_使用Excel Christmas Planner进行整理
  18. Bmob后端云的集成与使用
  19. python京东抢购软件神器_用Python在京东抢购商品
  20. ws832设置虚拟服务器,华为WS832路由器设置教程 | 192路由网

热门文章

  1. 怎么验证交易是否成功
  2. “斜杠青年” 的年终总结
  3. 我的世界服务器宝石系统,我的世界1.9-1.7宝石镶嵌插件
  4. Gtest 测试指导 入门基础(A)
  5. ec200t 拨号_Quectel EC200T驱动以及ppp拨号移植
  6. Windows10系统安装Oracle 11gR2
  7. Setup time和Holdon time
  8. typora显示版本过期,请下载最新版本,可是最新版本84块钱,咋办?
  9. 数据分析小实验(下)
  10. Rust:并发编程(concurrent programming)