Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating ShaderMaterial attribute in three.js

From the three.js tutorial on shaders, we learn we can update uniform values of a ShaderMaterial:

var attributes = {
  displacement: {
    type: 'f', // a float
    value: [] // an empty array
  }
};
var uniforms = {
  amplitude: {
    type: 'f', // a float
    value: 1
  }
};

var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');

// create the final material
var shaderMaterial =
    new THREE.MeshShaderMaterial({
      uniforms:       uniforms,
      attributes:     attributes,
      vertexShader:   vShader.text(),
      fragmentShader: fShader.text()
    });
...

var frame = 0;
function update() {

  // update the amplitude based on
  // the frame value.
  uniforms.amplitude.value =
    Math.cos(frame);

  // update the frame counter
  frame += 0.1;

  renderer.render(scene, camera);

  // set up the next call
  requestAnimFrame(update);
}

What isn't mentioned is whether this same behavior extends to attributes. From my own experimenting, I tried making vertices from the sphere demo jitter about by assigning random displacements every frame, e.g.:

  function update() {

    // update the amplitude based on
    // the frame value.
    values = attributes.displacement.value

    for(var v = 0; v < vertCount; v++) {
        values[v] = (Math.random() * 30);
    }

    renderer.render(scene, camera);

    // set up the next call
    requestAnimFrame(update);
  }

However the result is a static misshapen ball. It appears that attributes only take on the first value to which they are assigned. After that, they cannot be updated. However, is this a behavior expected of glsl attributes or is there an additional step I need to take to update attributes? If the latter, is there a workaround available to achieve the desired besides setting vertex positions in javascript?

like image 262
16807 Avatar asked Nov 28 '13 19:11

16807


1 Answers

Turns out it is possible to update attributes like uniforms. In my case, I was missing one all important line of code:

attributes.displacement.needsUpdate = true;

The line was omitted from the tutorial and upon adding it I get the exact behavior I was hoping for.

like image 157
16807 Avatar answered Oct 21 '22 05:10

16807