日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity音乐可视化效果研究

發(fā)布時(shí)間:2023/12/14 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity音乐可视化效果研究 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

兩年前,為項(xiàng)目做演示視頻的時(shí)候用了一個(gè)AE模板弄了一個(gè)音樂可視化效果,當(dāng)時(shí)也沒想過會(huì)要做到項(xiàng)目里面。

后來項(xiàng)目落地的時(shí)候用了另外一個(gè)效果。前一段時(shí)間在學(xué)習(xí)圖形學(xué),突然想起這件事,對(duì)于那個(gè)未能完成的效果有點(diǎn)不死心,于是重新研究了一下,大致完成了這個(gè)效果:

先說下音樂可視化的原理。

原理:

  • 通過unity的內(nèi)置函數(shù)采樣音樂頻域的數(shù)值,我們項(xiàng)目中因?yàn)槭橇髅襟w傳輸,所以方法有所不同,總之就是通過一系列代碼獲取音樂頻域數(shù)值(關(guān)于音樂的頻域,時(shí)域這些有一大堆的理論,還涉及到非常復(fù)雜的算法,有興趣的可以去百度研究下)。
  • 將頻域的數(shù)值記錄下來,寫入一張256像素寬度的貼圖,這里參考的是某位大神的腳本,但是因?yàn)闀r(shí)間久遠(yuǎn),找不到原文了,所以鏈接也沒法給出來。
  • 寫一個(gè)shader,采樣音樂圖,根據(jù)獲取的數(shù)值計(jì)算想要的效果。

?

步驟:

  • 在場(chǎng)景中創(chuàng)建一個(gè)plane,掛上一個(gè)AudioSource 組件,選一首你喜歡的音樂,設(shè)置一下播放和循環(huán):

  • 創(chuàng)建腳本,采樣音樂的數(shù)值,并記錄到一張貼圖里,并且每幀更新。然后將腳本也掛在plane上面。這里要注意下對(duì)更新數(shù)值的延遲處理,會(huì)讓最終的效果有個(gè)連續(xù)增長(zhǎng)和連續(xù)減少的效果,如果不做這一步,就會(huì)讓效果不夠連續(xù),會(huì)卡卡的感覺。

腳本代碼:

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);//對(duì)更新數(shù)據(jù)進(jìn)行延遲處理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;}} // 設(shè)置像素顏色dataTexture.SetPixel(i - 1, 1, new Color((spactrumDataDelay[i - 1] * 255.0f), 0, 0, 0));i++;}// 更新texturedataTexture.Apply();} }
  • 編寫shader,采樣傳入的音樂貼圖,然后用算法做出可視化效果。把plane的材質(zhì)用上這個(gè)shader就可以了。

思路:利用了畫圓的算法,用一個(gè)圓減另外一個(gè)圓畫出圓環(huán)。將圓弧等分,圓弧弧度對(duì)應(yīng)音樂貼圖的UV.x。根據(jù)采樣值改變圓環(huán)的粗細(xì)。然后再畫一個(gè)細(xì)一點(diǎn)的圓環(huán),用之前的減去它。

這樣說可能有點(diǎn)拗口,下面用圖來說明:

畫一個(gè)圓;

減去一個(gè)圓,先畫個(gè)圓環(huán);

將圓弧等分,并且按照采樣值,改變圓環(huán)粗細(xì)(兩個(gè)圓的半徑);

再畫一個(gè),改細(xì)一點(diǎn),并且在每一小段弧中間要加上間隔;

間隔的代碼,用step函數(shù)對(duì)圓弧做處理:

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

相減。

當(dāng)然思路是這樣,代碼中用到了各種函數(shù),次序會(huì)有些不同。但是結(jié)果是一樣的。最后加上背景虛化和顏色變化的效果,增加一些參數(shù)。

貼上全部shader代碼:

Shader "Chain/Effects/MusicEffects" {Properties{_Color("Color",Color) = (1,1,1,1)//音樂數(shù)據(jù)圖輸入_MusicData("MusicData (Alpha)", 2D) = "black" {}//將圓弧分成多少段_Divides("Divides",int) = 64//背景平滑度_Antialias("Antialias",Range(0,1)) = 0.1//圓半徑_radius("Radius",Range(0,1)) = 0.2//變化參數(shù)_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;//用于變色的旋轉(zhuǎn)矩陣float2x2 rotate2d(float angle) {return float2x2(cos(angle),-sin(angle),sin(angle),cos(angle));}//畫特效形狀的函數(shù)fixed2 effectShape(float2 uv, fixed2 center, float radius, float antialias, float offset,fixed arc,int divides) {float2 radiusVector = center - uv;float len = length(radiusVector);//圈圈內(nèi)圓半徑,根據(jù)音樂數(shù)據(jù)減小float radiusIn = radius - offset;//圈圈外圓半徑,根據(jù)音樂數(shù)據(jù)增大,設(shè)定一個(gè)最小增大值,一定會(huì)比內(nèi)圓大0.005float radiusOut = radius + offset + 0.005;//畫內(nèi)圈fixed arcIn = step(len, radiusOut) - step(len, radiusIn);//根據(jù)格子數(shù)取余,每一格來一個(gè)間隔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);//增加一個(gè)漸變輸出,用于背景輸出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);//測(cè)試背景漸變效果//arc_col =arcIn;//輸出方塊效果//arc_col = arcgradient;//輸出為兩個(gè)通道,一個(gè)用來存儲(chǔ)畫的線,一個(gè)用來存儲(chǔ)背景的漸變r(jià)eturn 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{//將坐標(biāo)轉(zhuǎn)換為圓圈的弧度坐標(biāo),然后用這個(gè)坐標(biāo)去采樣音樂圖,獲得音樂數(shù)據(jù)去改變圓圈的半徑等fixed arcU = atan2(i.uv.x * 2 - 1,i.uv.y * 2 - 1) / UNITY_TWO_PI;//將弧度范圍從-1~1轉(zhuǎn)換到0~1arcU = arcU * 0.5 + 0.5;//取樣音樂圖的數(shù)據(jù),將uv分為格子,取格子起始點(diǎn)的值,因?yàn)槲覀兊囊魳妨鲾?shù)據(jù)很奇怪,所以前面加了1-,正常的話去掉fixed rayoffset = tex2D(_MusicData,float2(floor((arcU)*_Divides) / _Divides,0)).r;//圓圈中心點(diǎn)設(shè)在坐標(biāo)中心fixed2 center = fixed2(0.5,0.5);//平滑范圍最大不超過0.125fixed inantialias = _Antialias * 0.125;//以時(shí)間為旋轉(zhuǎn)速度因子變色的函數(shù)fixed2 v = mul(rotate2d(_Time.y) , i.uv);//繪制fixed2 shape = effectShape(i.uv, center, _radius, inantialias, rayoffset*_rayOffset,arcU,_Divides);fixed4 final;//分拆函數(shù)的輸出,分別作為背景和線條疊加起來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}} }

總結(jié):

我在做這個(gè)效果的時(shí)候是根據(jù)直觀的視覺效果來分析的,還沒有考慮優(yōu)化,只是目測(cè)了一下幀率,目前這個(gè)效果應(yīng)該在移動(dòng)平臺(tái)上問題不大。

另外如果要替代這個(gè)效果,而且算法比較復(fù)雜的話,可以考慮把背景發(fā)光等效果做成圖片疊加可能會(huì)更省效率,項(xiàng)目中我是直接用圖片替代了整個(gè)圓環(huán)的算法,不過效率孰優(yōu)孰劣卻沒有很嚴(yán)謹(jǐn)?shù)娜ヲ?yàn)證了。

目前只是一個(gè)基礎(chǔ)效果,如果實(shí)際應(yīng)用的話,加上抗鋸齒,還可以考慮加上bloom效果,再配合一些粒子特效應(yīng)該會(huì)很棒,更多效果,可以參考ShaderToy。

后來又看了一下AE源文件的處理方法,發(fā)現(xiàn)用到了粒子,模糊,查找邊緣后處理等手段。不知道以后會(huì)不會(huì)有時(shí)間再研究一下這種做法。

總結(jié)

以上是生活随笔為你收集整理的Unity音乐可视化效果研究的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。