Some notes about the idea and the process behind this demo. I’ve started to work thinking that it could be nice to put some rings that move up and down on the trees, maybe in sync whith music. Using ofxLsystem was pretty easy to have a mesh containing a forest of ~80 trees, all I need to do is to put rings on them.

## The rings

After reading the wonderful The book of shaders, and especially the chapter dedicated to the shaping functions, I’ve decided to use a shader to draw the ring on the surface of the trees. In the book was linked this example, that uses a function called `cubicPulse` by Iñigo Quiles to create a smooth effect.

``````#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

//  Function from Iñigo Quiles
//  www.iquilezles.org/www/articles/functions/functions.htm
float cubicPulse( float c, float w, float x ){
x = abs(x - c);
if( x>w ) return 0.0;
x /= w;
return 1.0 - x*x*(3.0-2.0*x);
}

void main() {
vec2 st = gl_FragCoord.xy/u_resolution;
// now the ring is moving following the time, it has to move following the sound!
float y = cubicPulse(mod(u_time,0.99),0.2,st.y);
vec3 color = vec3(y);
color = color*vec3(0.0,1.0,0.0);
gl_FragColor = vec4(color,1.0);
}
``````

## The mesh containing the trees

I did not want to apply a shader for each tree because it could have been slow, also considering that I will need to continuously update the uniform containing the current sound amplitude to have the rings moving in sync with the music. That’s why, in openFrameworks, I’ve merged all the trees in a single mesh.This mesh will be loaded later in the threeJS sketch.

``````for(int i = 0; i<nTree; i++){
ofxLSystem tree;
tree.setAxiom("A(100)");
tree.setRules({"A(s) -> F(s)[+A(s/R)][-A(s/R)]"});
tree.setRandomYRotation(true);
tree.setConstants(constants);
tree.setStep(abs(ofRandom(5, 10)));
tree.setScaleWidth(true);
tree.setStepWidth(abs(ofRandom(30.5, 40.5)));
tree.setStepLength(abs(ofRandom(150,300)));
tree.build();
tree.pan(ofRandom(30.00, 330.00));
auto pos = ofVec2f(ofRandom(-halfScreen, halfScreen),
ofRandom(-halfScreen, halfScreen));

tree.setPosition(ofVec3f(pos.x, 0, pos.y));
for (int i=0; i<tree.getMesh().getNumVertices(); i++) {
auto actualVert =tree.getMesh().getVerticesPointer()[i];
auto newVert = actualVert * tree.getGlobalTransformMatrix();
tree.getMesh().getVerticesPointer()[i] = newVert;
}
forest.append(tree.getMesh());
}
``````

In this repository, in the folder “example-rings” you can find the whole openFrameworks application, shaders and onset detection included. The mesh was still pretty big, as I do not need high resolution, I’ve used meshLab to simplyfy the mesh.

## The sound

Maximilian is not only a c++ library that can be easily integrated with openFrameworks using ofxMaxim, but it has also a javascript port that simplifies a lot working with sound in the browser.

To play a sample in with Maximilian is super easy.

``````var maxiAudio = new maximJs.maxiAudio(); // the maxi audio object
var sample = new maximJs.maxiSample(); // object that will contain the song loaded
var ctx = new AudioContext(); // the audio context. see http://www.html5rocks.com/en/tutorials/webaudio/intro/

\$.when(
).then(
function (_, treePly) {
init(treePly);
animate();
},
function (error) {
console.log(error);
}
);
``````

In the `init` method I’ve added a method called `initAudio` that plays the sample

``````
function initAudio(){
maxiAudio.init();
// I need the output as an array later
maxiAudio.outputIsArray(true, 2);
maxiAudio.play = function(scenography) {
var wave1 = sample.play();
var mix = wave1 * config.volume; // in case you have other samples, just add them here: var mix =  wave1 +wave2;
this.output = mix;
this.output = this.output;
var left = this.output;
var right = this.output;
}
}

``````

The function `maxiAudio.loadSample` sets the variable `sample`. The third parameter `ctx` is the AudioContext created at the beginning. In the init method of the threejs sketch I call `initAudio`. This function get called only once, but the content of the loop `maxiAudio.play = function() {` get executed until we close the page. This is related to the nature of the `AudioContext`. There is a good introduction of Web Audio API at this page

## Beat detection

What i wanted to do is to move the rings up and down depending on the music. The easiest way is to implement an onset detection, a way to find “the beat”, the moment when the sound “kicks”. I’ve used Root Mean Square calculation (RMS), there is a nice explanation of it in the ofBook. I’ve edited the `initAudio` method setting the value of `rms` as follow:

``````function initAudio(){
maxiAudio.init(); //initialize the maxiAudio
maxiAudio.outputIsArray(true, 2); // the output is an array containing 2 channels, left and right
maxiAudio.play = function() {
bufferCount++;
var wave1 = sample.play(); // play the sample
var mix = wave1 * config.volume; // in case you have other samples, just add them here: var mix =  wave1 +wave2;
this.output = mix;
this.output = this.output;
// in case we want to do smth else in the future with the current bufferOut
bufferOut[bufferCount % 1024] = mix;
var left = this.output;
var right = this.output;
rms += left * left;
rms += right * right;
examplesCounted += 2;
}
}
``````

later, in the `animate` function of the threejs sketch i’ve smoothed the `rms` value, and updated the related uniform.

``````function calcRms(bufferOut) {
if (bufferOut.length === 1024) {
rms /= examplesCounted;
rms = Math.sqrt(rms);

threshold = lerp(threshold, this.config.minTreshold, this.config.decayRate);
if (rms > threshold) {
threshold = rms;
}
treeMaterial.uniforms.rms.value = threshold;
}
}
``````

Unsing a `sin(u_time)` in the previous shader, the rings are moving like this: To move the the ring up and down I’ve first to identify a 0 value on the y axis, then add a uniform containing the previously calculated `rms` value, decide how tick the ring will be , calculating the padding between the rings and finally draw as many ring as desidered. To simply draw a ring at the base of the mesh, that moves up and down following the rms value, i can modify the previuos shader like this:

``````vec4 tmpCol = vec4(treeColor, 1.0);
float y = cubicPulse(mod(rms * scaleRing, 1.0),ringThickness,screenY);
tmpCol += vec4( vec3( dProd ) *vec3( y ) * vec3(ringColor), y);
``````

`treeColor` is the color of the tree, `rms` is the currently calculated rms, `scaleRing` is a value used to amplify the movement of the ring, `ringThickness` is a value that decide the thickness of the ring, and screenY is a value calculated in the vertex shader with `screenY = position.y/uResolution.y`, that determinates the initial position of the ring. You can change all these uniforms in the demo, pressing `g` to see how they affect it.

To draw more than one ring I’ve used a loop. Compared to OpenGL, WebGL has some limitations for loops. In webGL, the upper limit of the loop has to be a declared constant, `MAX_NUM_RINGS` in my shader. When the shader compile, this loop is unrolled as many time as defined in that constant. To execute the instruction contained in the loop as many time as defined in the uniform `ringNumber`, I’ve to break the loop at the desidered value.

``````#define MAX_NUM_RINGS 18
for (int i = 0; i< MAX_NUM_RINGS; i++) {
if (i == ringNumber ) break;
//draw the ring!
end
``````

The distance between each ring is stored in the variable `padding` and it depends on how many rings are currently drawn. It is calculated like this:

``````float inc = 1.0/float(ringNumber);
//arbitrary light position
vec3 lightPos = vec3(0.5, 0.2, 0.5);
vec3 lightDirection = normalize(vecPos.xyz - lightPos);
float dProd = max(0.6,dot(vecNormal, lightDirection));

vec4 tmpCol = vec4(treeColor, 1.0);
for (int i = 0; i< MAX_NUM_RINGS; i++) {
if (i == ringNumber ) break;
float y = cubicPulse(mod(rms * scaleRing, 1.0),ringThickness,screenY - padding);
//apply light only to the rings
tmpCol += vec4( vec3( dProd ) *vec3( y ) * vec3(ringColor), y); 