根据 THREE 中着色器的位置数组对点的位置进行动画处理.js



我有三个点的动画。我想使用着色器来更快地使动画。由于我是着色器的新手,所以我想从一分点开始动画开始。在每个时间步骤中,我都想分配保存在向量数组(位置)中的预定位置。因此,如果time = 1,点的位置将等于positions [1]

我试图将位置保存为统一,并将其传递给顶点着色器,但它不起作用。

我应该做些什么?这是正确的方法吗?

点声明

//example array with only three vectors but I would like to use arrays which thousands of vectors
var positions = [
    new THREE.Vector3(1.6, 2.5, 4.0),
    new THREE.Vector3(1.8, 2.5, 3.8),
    new THREE.Vector3(1.2, 2.0, 3.0)
]
var geometry = new THREE.BufferGeometry();    
geometry.addAttribute("position", new THREE.Float32BufferAttribute([1.6, 2.5, 4.0],3))
var material = new THREE.ShaderMaterial({
    vertexShader: document.getElementById( 'vertexShader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
    uniforms: {
        time: { type: 'f', value: 0 },
        positionArray: {type: "v3v", value: positions} 
    }
})
var point = new THREE.Points(geometry, material);
scene.add(point)

动画

function animate() {
    requestAnimationFrame(animate);
    time = time + 1
    material.uniforms.time.value = time;
    controls.update();
    renderer.render(scene, camera);
    stats.update();
}

顶点着色器

uniform vec3 positionArray[3];      
uniform float time;
void main () {
    vec3 newPosition;
    newPosition= positionArray[time];
    gl_PointSize = 10.0;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
    }

可以没有着色器。

想法:您有一个Float32Array()

的数组
var data = [
  new Float32Array([...]),
  new Float32Array([...]),
  //and so on
];

,每个键入的数组在给定时间密钥中包含几何学中每个点的数据;然后,当时间是1时,您只需将data数组中元素1的数据分配给geometry.attributes.position.array

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 2, 25);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(100, 100, "white", "white"));
var data = []; // arry of Float32Array
for (let i = 0; i < 10; i++){
  let arr = [];
  for(let x = -50; x <= 50; x++){
    for(let y = -50; y <=50; y++){
       arr.push(x, i * 2, y);
    }
  }
  data.push(new Float32Array(arr));
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array(data[0].slice()), 3 ) );
var material = new THREE.PointsMaterial({
  size: .25,
  color: "red"
});
var plane = new THREE.Points(geometry, material);
scene.add(plane);
var clock = new THREE.Clock();
var time = 0;
var floorTime = 0;
var oldTime = -1;
var delta = 0;
render();
function render() {
  delta = clock.getDelta();
  time += delta;
  requestAnimationFrame(render);
  if (time >= 10) time = 0;
  floorTime = Math.floor(time);
  if (floorTime != oldTime) { // a very rough approach of managing the time keys
    geometry.attributes.position.array.set(data[floorTime]); // set the data of points
    geometry.attributes.position.needsUpdate = true;
    oldTime = floorTime;
  }
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

ps也许这种方法不是很正确。这只是一个主意。

最新更新