在three.js中更新ShaderMaterial属性

6

three.js着色器教程中,我们了解到可以更新ShaderMaterial的uniform值:

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);
}

未提及的是这种行为是否延伸至属性。通过自己的实验,我尝试通过每帧分配随机位移来使球体演示的顶点摇晃。

  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);
  }

然而,结果是一个静态的畸形球。看起来属性只取其分配的第一个值。之后,它们无法更新。但是,这是 glsl 属性的预期行为吗?还是我需要采取其他步骤来更新属性?如果是后者,是否有一种方法可以实现所需效果,而不是在 JavaScript 中设置顶点位置?

1个回答

16

原来可以更新像uniforms这样的属性。在我的情况下,我漏掉了一个非常重要的代码行:

attributes.displacement.needsUpdate = true;

这行代码被遗漏在教程中,加上它后我得到了我所期望的完美效果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接