将Perlin噪声着色器仅应用于网格中的某些对象

时间:2015-03-09 23:31:08

标签: three.js glsl webgl shader

我想使用perlin噪声修改网格中的一个对象。我现在怎么做...

  1. 我正在创建对象并将它们添加到3d对象...

     spheres = new THREE.Object3D();
     for ( var i = 0; i < 40; i ++ ) {
         var ball = new THREE.Mesh(new THREE.SphereGeometry(20,20,20), material);
         ball.position.x = Math.random() * 600 - 300;
         ball.position.y = Math.random() * 600 - 300;
         ball.position.z = Math.random() * 600 - 300;
         spheres.add(ball);
    }
    scene.add(spheres);
    
  2. 我正在使用着色器材料......

    material = new THREE.ShaderMaterial({
      uniforms: { 
    time: { 
        type: "f", 
        value: 0.0 
    },
    noisemax: { 
        type: "f", 
        value: 100.0 
    },
    transparent: true
    
    },
    vertexShader: document.getElementById( 'vertexShader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentShader' ).textContent
    });
    
  3. 着色器材料适用于所有40个球没问题。我想做的是改变着色器说spheres.children[0]。是否可以更改一个对象的perlin噪声值(noiseMax),还是自然地使用该材质对所有对象的材质进行影响?

1 个答案:

答案 0 :(得分:2)

你有几个选择。

简单的方法是为每个不同的项目创建和使用单独的ShaderMaterial,并且您可以轻松设置其制服。 e.g。

var firstMaterial = new THREE.ShaderMaterial({
    uniforms: { noisemax: { type: 'f', value: 3}}
});

var secondMaterial = new THREE.ShaderMaterial({
    uniforms: { noisemax: { type: 'f', value: 10}}
});

var firstBall = new THREE.Mesh(new THREE.SphereGeometry(20,20,20), firstMaterial);
var secondBall = new THREE.Mesh(new THREE.SphereGeometry(20,20,20), secondMaterial);

// or in your case
spheres.children[0].material = secondMaterial;

或者也许最好根据您的情况(至少从性能角度来看)是您应该将noisemax更改为属性,这样您就可以为每个对象设置单独的值。

您必须记住属性是每个顶点,因此您需要复制属于每个对象的所有顶点的值。这会使事情变得复杂一点。

编辑:要减少内存使用量,您可以使用THREE.InstancedBufferGeometry with THREE.InstancedBufferAttribute