Я знаю базовую c концепцию Interleaved и InstanceBuffer, но когда я загружаю огромное количество моделей в InterLeaved, такие функции, как увеличение / уменьшение, панорамирование и поворот, отстают. Реакция функциональности очень медленная. Итак, есть ли возможный способ загрузки InstancedMe sh в Interleaved. Я понятия не имею с этим, но мне нужны некоторые предложения относительно этого. Вот код, который я попробовал.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - buffergeometry - particles</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="container"></div>
<script type="module">
import * as THREE from '../build/three.module.js';
import Stats from './jsm/libs/stats.module.js';
import { OrbitControls } from './jsm/controls/OrbitControls.js';
var container, stats;
var camera, scene, renderer, mesh;
var instances = 5000;
var lastTime = 0;
var controls;
var moveQ = new THREE.Quaternion(0.5, 0.5, 0.5, 0.0).normalize();
var tmpQ = new THREE.Quaternion();
var tmpM = new THREE.Matrix4();
var currentM = new THREE.Matrix4();
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 190;
scene = new THREE.Scene();
scene.background = new THREE.Color('white');
// geometry
// var geometry = new THREE.InstancedBufferGeometry();
var geometry = new THREE.InstancedBufferGeometry();
// per mesh data x,y,z,w,u,v,s,t for 4-element alignment
// only use x,y,z and u,v; but x, y, z, nx, ny, nz, u, v would be a good layout
var vertexBuffer = new THREE.InterleavedBuffer(new Float32Array([
// Front
- 1, 1, 1, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 0, 0,
- 1, - 1, 1, 0, 0, 1, 0, 0,
1, - 1, 1, 0, 1, 1, 0, 0,
// Back
1, 1, - 1, 0, 1, 0, 0, 0,
- 1, 1, - 1, 0, 0, 0, 0, 0,
1, - 1, - 1, 0, 1, 1, 0, 0,
- 1, - 1, - 1, 0, 0, 1, 0, 0,
// Left
- 1, 1, - 1, 0, 1, 1, 0, 0,
- 1, 1, 1, 0, 1, 0, 0, 0,
- 1, - 1, - 1, 0, 0, 1, 0, 0,
- 1, - 1, 1, 0, 0, 0, 0, 0,
// Right
1, 1, 1, 0, 1, 0, 0, 0,
1, 1, - 1, 0, 1, 1, 0, 0,
1, - 1, 1, 0, 0, 0, 0, 0,
1, - 1, - 1, 0, 0, 1, 0, 0,
// Top
- 1, 1, 1, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 0, 0,
- 1, 1, - 1, 0, 0, 1, 0, 0,
1, 1, - 1, 0, 1, 1, 0, 0,
// Bottom
1, - 1, 1, 0, 1, 0, 0, 0,
- 1, - 1, 1, 0, 0, 0, 0, 0,
1, - 1, - 1, 0, 1, 1, 0, 0,
- 1, - 1, - 1, 0, 0, 1, 0, 0
]), 8);
// Use vertexBuffer, starting at offset 0, 3 items in position attribute
var positions = new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0);
geometry.setAttribute('position', positions);
// Use vertexBuffer, starting at offset 4, 2 items in uv attribute
var uvs = new THREE.InterleavedBufferAttribute(vertexBuffer, 2, 4);
geometry.setAttribute('uv', uvs);
var indices = new Uint16Array([
0, 1, 2,
2, 1, 3,
4, 5, 6,
6, 5, 7,
8, 9, 10,
10, 9, 11,
12, 13, 14,
14, 13, 15,
16, 17, 18,
18, 17, 19,
20, 21, 22,
22, 21, 23
]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// material
var material = new THREE.MeshBasicMaterial();
material.map = new THREE.TextureLoader().load('textures/crate.gif');
material.side = THREE.DoubleSide;
// per instance data
var matrix = new THREE.Matrix4();
var offset = new THREE.Vector3();
var orientation = new THREE.Quaternion();
var scale = new THREE.Vector3(1, 1, 1);
var x, y, z, w;
mesh = new THREE.InstancedMesh(geometry, material, instances);
for (var i = 0; i < instances; i++) {
// offsets
x = Math.random() * 100 - 50;
y = Math.random() * 100 - 50;
z = Math.random() * 100 - 50;
offset.set(x, y, z).normalize();
offset.multiplyScalar(5); // move out at least 5 units from center in current direction
offset.set(x + offset.x, y + offset.y, z + offset.z);
// orientations
x = Math.random() * 2 - 1;
y = Math.random() * 2 - 1;
z = Math.random() * 2 - 1;
w = Math.random() * 2 - 1;
orientation.set(x, y, z, w).normalize();
matrix.compose(offset, orientation, scale);
mesh.setMatrixAt(i, matrix);
}
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// //
controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true; // an animation loop is required when either damping or auto-rotation are enabled
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.minDistance = 0.1;
controls.maxDistance = 5000000;
controls.maxPolarAngle = Math.PI / 2;
//
container.appendChild(renderer.domElement);
if (renderer.extensions.get('ANGLE_instanced_arrays') === null) {
document.getElementById('notSupported').style.display = '';
return;
}
stats = new Stats();
// container.appendChild(stats.dom);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//
function animate() {
requestAnimationFrame(animate);
controls.update(); // required if controls.enableDamping = true, or if controls.autoRotate = true
render();
stats.update();
}
function render() {
// var time = performance.now();
// mesh.rotation.y = time * 0.00005;
// var delta = (time - lastTime) / 5000;
// tmpQ.set(moveQ.x * delta, moveQ.y * delta, moveQ.z * delta, 1).normalize();
// tmpM.makeRotationFromQuaternion(tmpQ);
for (var i = 0, il = instances; i < il; i++) {
mesh.getMatrixAt(i, currentM);
currentM.multiply(tmpM);
mesh.setMatrixAt(i, currentM);
}
mesh.instanceMatrix.needsUpdate = true;
// lastTime = time;
renderer.render(scene, camera);
}
</script>
</body>
</html>