我目前正在创建这个(惊人的)音频分析器:http://cyxo.cf/audio-analyser/
使用Three.js
制作。
以下是代码:
//initial setup of scene qualities
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setSize(window.innerWidth-4, window.innerHeight-4);
document.getElementById("container").appendChild(renderer.domElement);
/*
global THREE
global AudioContext
global requestAnimationFrame
*/
//audio
var player = document.getElementById('player');
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var source = context.createMediaElementSource(player);
var analyser = context.createAnalyser();
source.connect(analyser);
analyser.connect(context.destination);
// we could configure the analyser: e.g. analyser.fftSize (for further infos read the spec)
// frequencyBinCount tells you how many values you'll receive from the analyser
var frequencyData = new Uint8Array(analyser.frequencyBinCount);
//for controls
var yrot = 0;
var it = 0;
var seuil = 60;
//make cube
var magicnumber = 48;
var geometry = new THREE.PlaneGeometry(magicnumber,magicnumber,24,24);
// var material = new THREE.ShaderMaterial( {
// vertexShader: document.getElementById( 'vertexShader' ).textContent,
// fragmentShader: document.getElementById( 'fragmentShader' ).textContent
// } );
//var material = new THREE.MeshNormalMaterial();
var material = new THREE.MeshLambertMaterial( { color: 0x009522, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } );
var group = new THREE.Object3D();
var plane = new THREE.Mesh(geometry, material);
group.add(plane);
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = 0;
plane.rotation.x = -Math.PI/2;
var verts = geometry.vertices;
geometry.dynamic = true;
scene.add(group);
//set camera position and direction
camera.position.z = -30;
camera.position.y = 15;
var origin = new THREE.Vector3( 0, 0, 0 );
// create a sun
var pointLight = new THREE.PointLight(0xFFFFFF,1,500,5);
var sungeo = new THREE.SphereGeometry(1,10,10);
var sunmat = new THREE.MeshBasicMaterial({color:0xffffff});
var sun = new THREE.Mesh(sungeo, sunmat);
var lightg = new THREE.Object3D();
lightg.add(pointLight);
lightg.add(sun);
lightg.position.x = 0;
lightg.position.y = 0;
lightg.position.z = 0;
scene.add(lightg);
// create a moon
var moonLight = new THREE.PointLight(0x8888FF,0.85,150);
var moongeo = new THREE.SphereGeometry(1,10,10);
var moonmat = new THREE.MeshBasicMaterial({color:0xaaaaff});
var moon = new THREE.Mesh(moongeo, moonmat);
var moong = new THREE.Object3D();
moong.add(moonLight);
moong.add(moon);
moong.position.x = 0;
moong.position.y = 0;
moong.position.z = 0;
scene.add(moong);
var al = new THREE.AmbientLight(0x222223);
scene.add(al);
// Setup blur function
///////////////////////////////////////////functions
var moy;
function wobble(){
moy = 0;
analyser.getByteFrequencyData(frequencyData);
for(var i=0; i < verts.length; i++){
verts[i].z = frequencyData[i] / 25;
moy += frequencyData[i];
}
moy = moy/frequencyData.length;
geometry.verticesNeedUpdate = true;
geometry.colorsNeedUpdate = true;
}
/*ID3.loadTags("Alpha_Centauri_Prime.mp3", function() {
var tags = ID3.getAllTags("Alpha_Centauri_Prime.mp3");
alert(tags.artist + " - " + tags.title + ", " + tags.album);
});*/
//////////////////////////////////////////
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
yrot += 0.005;
camera.position.x = -30*Math.cos(yrot);
camera.position.z = -30*Math.sin(yrot);
camera.lookAt(origin);
it = player.currentTime/9.5;
lightg.position.x = 30*Math.sin(it);
lightg.position.y = 20*Math.cos(it);
moong.position.x = -30*Math.sin(it);
moong.position.y = -20*Math.cos(it);
wobble();
$('#skyday').css({opacity: .5 + Math.sin(it + Math.PI/2)/2});
$('#skynight').css({opacity: .5-Math.sin(it + Math.PI/2)/2});
document.getElementById('debug').innerHTML = player.textTracks[0];
document.getElementById('top-cover').style.height = 50 - moy + '%';
document.getElementById('bottom-cover').style.height = 50 - moy + '%';
if (moy > seuil){
renderer.domElement.style.webkitFilter = 'blur('+Math.floor(moy-seuil)+'px)';
if (moy > seuil+8) renderer.domElement.style.opacity = 1 - (moy - (seuil+8))/10;
} else {
renderer.domElement.style.webkitFilter = '';
renderer.domElement.style.opacity = 1;
}
if (player.currentTime <= 10) document.getElementById('title').style.opacity =
document.getElementById('artist').style.opacity = (10 - player.currentTime) / 10;
if (player.currentTime >= player.duration - 10) document.getElementById('title').style.opacity =
document.getElementById('artist').style.opacity = (player.currentTime-player.duration + 10) / 10;
}
render();
&#13;
html,body,#container{
margin: 0;
padding: 0;
width: 98%;
height: 98%;
}
::-moz-selection { /* Code for Firefox */
color: inherit;
background: rgba(0,0,0,0);
}
::selection {
color: inherit;
background: rgba(0,0,0,0);
}
h1{
text-transform: uppercase;
font-size: 300%;
font-family: Verdana;
position: absolute;
z-index: 3;
text-align: center;
width: 100%;
}
#title{
color: white;
top: 35%;
}
#artist{
color: #00ccff;
bottom: 35%;
}
#container{
cursor: none;
}
canvas{
z-index: 0 !important;
}
audio{
position: absolute;
z-index: 2;
top: 5px;
right: 5px;
}
#debug{
top: 5px;
left: 5px;
position: absolute;
color: white;
z-index: 3;
}
.cover{
background: #000;
width: 100%;
position: absolute;
-webkit-transition: height 400ms ease-in-out;
-moz-transition: height 400ms ease-in-out;
-ms-transition: height 400ms ease-in-out;
-o-transition: height 400ms ease-in-out;
transition: height 400ms ease-in-out;
-webkit-box-shadow: 0 0 5px 2px #000000;
box-shadow: 0 0 5px 2px #000000;
z-index: 2;
}
.top{
top: 0;
}
.bottom{
bottom: 0;
}
#skyday{position:absolute; left:0; top:0; z-index:-100; width:100%; height:100%;
background-image: linear-gradient(bottom, rgb(218,237,255) 27%, rgb(30,153,235) 81%);
background-image: -o-linear-gradient(bottom, rgb(218,237,255) 27%, rgb(30,153,235) 81%);
background-image: -moz-linear-gradient(bottom, rgb(218,237,255) 27%, rgb(30,153,235) 81%);
background-image: -webkit-linear-gradient(bottom, rgb(218,237,255) 27%, rgb(30,153,235) 81%);
background-image: -ms-linear-gradient(bottom, rgb(218,237,255) 27%, rgb(30,153,235) 81%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.27, rgb(218,237,255)),
color-stop(0.81, rgb(30,153,235))
);}
#skynight{position:absolute; left:0; top:0; z-index:-100; width:100%; height:100%;
background: #080830; /* Old browsers */
background: -moz-linear-gradient(top, #080830 20%, #08162a 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(20%,#080830), color-stop(100%,#08162a)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #080830 20%,#08162a 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #080830 20%,#08162a 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #080830 20%,#08162a 100%); /* IE10+ */
background: linear-gradient(to bottom, #080830 20%,#08162a 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#080830', endColorstr='#08162a',GradientType=0 ); /* IE6-9 */
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r72/three.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="container">
<div id="skyday"></div>
<div id="skynight"></div>
<div class="top cover" id="top-cover"></div>
<div class="bottom cover" id="bottom-cover"></div>
<h1 id="title">A l p h a C e n t a u r i P r i m e</h1>
<h1 id="artist">P a u l o l o l</h1>
</div>
<span id="debug"></span>
<audio id="player" src="http://cyxo.cf/audio-analyser/Alpha_Centauri_Prime.mp3" autoplay="" controls=""></audio>
<script type="x-shader/x-vertex" id="vertexShader">
// Vertex shader content
</script>
<script type="x-shader/x-vertex" id="fragmentShader">
// Fragment shader content
</script>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
&#13;
但我想要的不是这个(漂亮的)绿色,顶点会根据它们在Z轴上的高度而着色。
颜色应该在数组中,如下所示:
//Pseudo-code :
var colors = [0x000000, 0x888888, 0xFFFFFF]
for i = 0 to vertices.length :
if (vertices[i].position.z <= 66) then vertices[i].color = colors[0]
if (vertices[i].position.z > 66 && vertices[i].position.z < 133) then vertices[i].color = colors[1]
if (vertices[i].position.z >= 133) then vertices[i].color = colors[2]
你能帮帮我吗?
PS:在HTML代码中,如果需要,有一些着色器的位置,可以包含在这样的材质中:
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
答案 0 :(得分:0)
嗯,我让那些着色器工作了:
// Vertex shader
varying vec3 col;
void main() {
col = position;
vec4 offset = vec4(col.x, col.y, col.z, 1.0);
gl_Position = projectionMatrix * modelViewMatrix * offset;
}
// Fragment shader
varying vec3 col;
lowp float g;
void main(void) {
g = float(col.z > 5.0);
gl_FragColor = vec4(0.6*g, 0.5*(1.0-g) + 0.6*g, 0.6*g, 1.0);
}
它介于绿色和灰色之间,但不是很平滑: http://grab.by/N2qG