Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added sounds/music.mp3
Binary file not shown.
Binary file added sounds/music2.mp3
Binary file not shown.
191 changes: 155 additions & 36 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,167 @@
const THREE = require('three'); // older modules are imported like this. You shouldn't have to worry about this much
import Framework from './framework'

// Colors
var additionalControls = {
'Color' : [255, 255, 255],
'scale' : 1.,
'music' : true,
'inv persistence' : 2.,
'radius' : 0.7,
'detail' : 6.
};

// Local global to allow for modifying variables
var noiseCloud = {
mesh : {},
};

// called after the scene loads
function onLoad(framework) {
var scene = framework.scene;
var camera = framework.camera;
var renderer = framework.renderer;
var gui = framework.gui;
var stats = framework.stats;

// LOOK: the line below is synyatic sugar for the code above. Optional, but I sort of recommend it.
// var {scene, camera, renderer, gui, stats} = framework;

// initialize a simple box and material
var box = new THREE.BoxGeometry(1, 1, 1);

var adamMaterial = new THREE.ShaderMaterial({
uniforms: {
image: { // Check the Three.JS documentation for the different allowed types and values
type: "t",
value: THREE.ImageUtils.loadTexture('./adam.jpg')
}
},
vertexShader: require('./shaders/adam-vert.glsl'),
fragmentShader: require('./shaders/adam-frag.glsl')
});
var adamCube = new THREE.Mesh(box, adamMaterial);

// set camera position
camera.position.set(1, 1, 2);
camera.lookAt(new THREE.Vector3(0,0,0));

scene.add(adamCube);

// edit params and listen to changes like this
// more information here: https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage
gui.add(camera, 'fov', 0, 180).onChange(function(newVal) {
camera.updateProjectionMatrix();
});
var scene = framework.scene;
var camera = framework.camera;
var renderer = framework.renderer;
var gui = framework.gui;
var stats = framework.stats;

// LOOK: the line below is synyatic sugar for the code above. Optional, but I sort of recommend it.
// var {scene, camera, renderer, gui, stats} = framework;
var adamMaterial = new THREE.ShaderMaterial({
uniforms: {
image: { // Check the Three.JS documentation for the different allowed types and values
type: "t",
value: THREE.ImageUtils.loadTexture('./adam.jpg')
},
inv_persistence: {
type: "f",
value: 2.0
},
time: {
type: "f",
value: 0.
},
music: {
type: "f",
value: 1.
},
music2: {
type: "f",
value: 1.
},
colorMult: {
value: new THREE.Vector3(additionalControls['Color'][0]/255, additionalControls['Color'][1]/255, additionalControls['Color'][2]/255,)
}
},
vertexShader: require('./shaders/adam-vert.glsl'),
fragmentShader: require('./shaders/adam-frag.glsl')
});

var iso = new THREE.IcosahedronBufferGeometry(0.7, 6);
noiseCloud.mesh = new THREE.Mesh(iso, adamMaterial);
noiseCloud.mesh.name = "adamCube";

// set camera position
camera.position.set(1, 1, 6);
camera.lookAt(new THREE.Vector3(0,0,0));

scene.add(noiseCloud.mesh);

// edit params and listen to changes like this
// more information here: https://workshop.chromeexperiments.com/examples/gui/#1--Basic-Usage
gui.add(camera, 'fov', 0, 180).onChange(function(newVal) {
camera.updateProjectionMatrix();
});

gui.add(additionalControls, 'inv persistence', 1., 10.).onChange(function(newVal) {
noiseCloud.mesh.material.uniforms.inv_persistence.value = newVal;
});

gui.add(additionalControls, 'music').onChange(function(newVal) {
additionalControls.music = newVal;
});

// Color menu
gui.addColor(additionalControls, 'Color').onChange(function(newVal) {
noiseCloud.mesh.material.uniforms.colorMult.value = new THREE.Vector3(newVal[0]/255, newVal[1]/255, newVal[2]/255,);
});


// Audio stuff below
// http://raathigesh.com/Audio-Visualization-with-Web-Audio-and-ThreeJS/
// http://stackoverflow.com/questions/27589179/basic-web-audio-api-not-playing-a-mp3-file
// http://stackoverflow.com/questions/3273552/html5-audio-looping
var context = new AudioContext();
var jsNode = context.createScriptProcessor(2048,1,1);
jsNode.connect(context.destination);

// Load file and set to repeat
var audio = new Audio();
audio.src = "./sounds/music2.mp3"; //https://www.jamendo.com/track/1350213/jumper
audio.controls = true;
audio.autoplay = true;
audio.addEventListener('ended', function(){
this.currentTime = 0;
this.play();
}, false);
audio.loop = true;

// Play file
var source = context.createMediaElementSource(audio);
source.connect(context.destination);
source.mediaElement.play();

// Analyze waveform data
var analyser = context.createAnalyser();
analyser.fftSize = 128;
analyser.smoothingTimeConstat = 0.8;
source.connect(analyser);

// Action to take with processed data
jsNode.onaudioprocess = function () {

// If music sync box is checked
if (additionalControls.music) {
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
// console.log(analyser.maxDecibels)

var Z = [array.slice(0, 9).reduce((a, b) => a + b, 0) / 10 /256,
array.slice(10, 19).reduce((a, b) => a + b, 0) / 10 /256,
array.slice(20, 29).reduce((a, b) => a + b, 0) / 10 /256,
array.slice(30, 39).reduce((a, b) => a + b, 0) / 10 /256,
array.slice(40, 49).reduce((a, b) => a + b, 0) / 10 /256,
array.slice(50, 59).reduce((a, b) => a + b, 0) / 10 /256];
// console.log(Z);

noiseCloud.mesh.material.uniforms.music.value = Z[4];
noiseCloud.mesh.material.uniforms.music2.value = Z[1];
} else {
noiseCloud.mesh.material.uniforms.music.value = 1.;
noiseCloud.mesh.material.uniforms.music2.value = 0.;
}


}


}

// called on frame updates
function onUpdate(framework) {
console.log(`the time is ${new Date()}`);


framework.scene.traverse(function (object)
{
if (object instanceof THREE.Mesh)
{
if (object.name === 'adamCube') {
// var d = new Date();
// console.log(`the time is ${(object.material.uniforms.time.value)}`);
object.material.uniforms.time.value += .01;

}
}
});
}

// when the scene is done initializing, it will call onLoad, then on frame updates, call onUpdate
Expand Down
8 changes: 6 additions & 2 deletions src/shaders/adam-frag.glsl
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
varying vec2 vUv;
varying vec3 nor;
varying float noise;
varying float mus;

uniform sampler2D image;
uniform vec3 colorMult;


void main() {

vec4 color = texture2D( image, vUv );

gl_FragColor = vec4( color.rgb, 1.0 );

gl_FragColor = vec4( (1. - noise) * nor.rgb + noise * colorMult, 1.0 );
// gl_FragColor = vec4( mus * color.rgb, 1.0 );
}
80 changes: 78 additions & 2 deletions src/shaders/adam-vert.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,82 @@

varying vec2 vUv;
varying vec3 nor;
varying float noise;
varying float mus;

uniform float inv_persistence;
uniform float time;
uniform float music;
uniform float music2;

#define M_PI 3.14159265
const int N_OCTAVES = 5;

float sampleNoise(vec3 pos) {
float x = fract(sin(dot(pos, vec3(134.9235, 63.5879, 218.9542))) * 27495.2467);
return x;
}

float interpolate(float a, float b, float t) {
float cos_t = (1. - cos(t * M_PI)) * 0.5;
return a * (1. - cos_t) + b * cos_t;
}

float interpNoise(vec3 pos, float f) {

// Calculate the min/max positions of cube
vec3 p0 = floor(pos * f) / f;
vec3 p1 = p0 + 1. / f;
vec3 t = (pos - p0) * f;

// Find noise values at corners of cube
float A = sampleNoise(vec3(p0.x, p0.y, p0.z));
float E = sampleNoise(vec3(p1.x, p0.y, p0.z));

float B = sampleNoise(vec3(p0.x, p1.y, p0.z));
float F = sampleNoise(vec3(p1.x, p1.y, p0.z));

float C = sampleNoise(vec3(p0.x, p0.y, p1.z));
float G = sampleNoise(vec3(p1.x, p0.y, p1.z));

float D = sampleNoise(vec3(p0.x, p1.y, p1.z));
float H = sampleNoise(vec3(p1.x, p1.y, p1.z));

// First pass of interpolation
float interpLi_AE = interpolate(A, E, t.x);
float interpLi_BF = interpolate(B, F, t.x);
float interpLi_CG = interpolate(C, G, t.x);
float interpLi_DH = interpolate(D, H, t.x);

// Second pass of interpolation
float interpBi_12 = interpolate(interpLi_AE, interpLi_BF, t.y);
float interpBi_34 = interpolate(interpLi_CG, interpLi_DH, t.y);

// Third pass
return interpolate(interpBi_12, interpBi_34, t.z);
}

float multiOctaveNoise(float offset) {

float total = 0.;
float persistence = 1. / inv_persistence;

for (int i = 0; i < N_OCTAVES; i++) {

float frequency = pow(2., float(i));
float amplitude = pow(persistence, float(i));
total += interpNoise(position + offset, frequency) * amplitude;
}

return total;
}

void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
mus = music;

noise = multiOctaveNoise(time);
nor = vec3(projectionMatrix * modelViewMatrix * vec4(normal, 0.));
gl_Position = projectionMatrix * modelViewMatrix * vec4(position + noise * nor * music, 1.);
}