顶点颜色取决于其高度

时间:2015-12-30 11:48:42

标签: javascript html css three.js vertex

我目前正在创建这个(惊人的)音频分析器: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&nbsp; &nbsp;C e n t a u r i&nbsp; &nbsp;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;
&#13;
&#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

1 个答案:

答案 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