Three.js Object3D自定义顶点着色器

时间:2018-01-27 14:37:51

标签: three.js

我在场景中有一堆Object3d由不同的网格组成,例如:

const object3d = new Object3D();
const bodyMaterial = new MeshLambertMaterial();
const bezelMaterial = new MeshBasicMaterial({ color: "0xffffff" });
const mesh = new Mesh(MeshFactory.mesh1, [ bodyMaterial, bezelMaterial ]);
const textLabel = TextFactory.createText("mesh1");
object3d.add(mesh, textLabel);

我想在每个帧上移动position的{​​{1}}, 目前在CPU上执行此操作:

object3d

这很慢,因为我有数百个render() { object3D.position = calcPosition(); // new Vector3 } 个对象,每个对象应该单独移动。 所以我想写一个Object3d来移动每个帧上的xyz,但是, 如何为Object3D编写着色器? (改变所有网格的位置)?

1 个答案:

答案 0 :(得分:0)

听起来你可能会以错误的方式处理事情......

但是..
以下是三个.js中着色器中顶点位移的基本示例。 旋转在渲染循环中完成,但偏移值将发送到顶点着色器。

var camera, scene, renderer, mesh, material;
init();
animate();

function init() {
    // Renderer.
    renderer = new THREE.WebGLRenderer();
    //renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    // Add renderer to page
    document.body.appendChild(renderer.domElement);

    // Create camera.
    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 400;

    // Create scene.
    scene = new THREE.Scene();

    // Create material
    var uniforms = {
    	xOffset: { type: "f", value: 0.0 },
      yOffset: { type: "f", value: 0.0 },
      zOffset: { type: "f", value: 0.0 }
    };
    var vertexShader = document.getElementById('vertexShader').text;
    var fragmentShader = document.getElementById('fragmentShader').text;
    material = new THREE.ShaderMaterial(
      {
        uniforms : uniforms,
        vertexShader : vertexShader,
        fragmentShader : fragmentShader
      });

    // Create cube and add to scene.
    var geometry = new THREE.BoxGeometry(200, 200, 200);
    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    // Create ambient light and add to scene.
    var light = new THREE.AmbientLight(0x404040); // soft white light
    scene.add(light);

    // Create directional light and add to scene.
    var directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.position.set(1, 1, 1).normalize();
    scene.add(directionalLight);

    // Add listener for window resize.
    window.addEventListener('resize', onWindowResize, false);
    
    // set up gui.
    var gui = new dat.GUI();
  	gui.add(uniforms.xOffset, 'value', -500, 500).name('X Offset');
    gui.add(uniforms.yOffset, 'value', -500, 500).name('Y Offset');;
    gui.add(uniforms.zOffset, 'value', -500, 500).name('Z Offset');;

}

function animate() {
    requestAnimationFrame(animate);
    mesh.rotation.x += 0.005;
    mesh.rotation.y += 0.01;
    renderer.render(scene, camera);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
    padding: 0;
    margin: 0;
}
canvas {
  display: block;
}
<script src="https://rawgit.com/mrdoob/three.js/r89/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/dataarts/dat.gui/v0.6.2/build/dat.gui.min.js"></script>


<script id="vertexShader" type="x-shader/x-vertex">
    uniform float xOffset;
    uniform float yOffset;
    uniform float zOffset;
    void main( void ) {
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position + vec3(xOffset, yOffset, zOffset),1.0);
    }
  </script>

  <script id="fragmentShader" type="x-shader/x-fragment">
    void main() {
      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
  </script>