我有三个点的动画。我想使用着色器来更快地使动画。由于我是着色器的新手,所以我想从一分点开始动画开始。在每个时间步骤中,我都想分配保存在向量数组(位置)中的预定位置。因此,如果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也许这种方法不是很正确。这只是一个主意。