это не оставило меня в покое, и мне пришло в голову, что если я предварительно выделю геометрию буфера, мне придется сделать это с шейдерами для каждой группы. Я бы сейчас сделал это намного сложнее, чем с ".clone ()". хорошо, что я проверил еще раз. Ваш совет прекрасно работает. Я исправил обновление позиционирования, и это именно тот результат, который я имел в виду. Вот индивидуальный код для всех, кого это интересует. Теперь я объединю это с моим эмиттером частиц.
var camera, controls, scene, renderer, container;
var PI = Math.PI;
var clock = new THREE.Clock();
var plane;
var MAX_Planes = 2000;
var velocity = [];
var geometry;
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
//renderer.sortObjects = true;
container = document.getElementById('container');
renderer.setSize(container.clientWidth, container.clientHeight);
container.appendChild( renderer.domElement );
var aspect = container.clientWidth / container.clientHeight;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
camera = new THREE.PerspectiveCamera( 45, container.clientWidth / container.clientHeight, 1, 100000 );
camera.position.set(0, 0, 4000);
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = true;
controls.enabled = true;
controls.target.set(0, 0, 0);
//---------------shader---------------
var VertexShader = `
varying vec3 sPos;
uniform vec3 pos;
uniform float stretch;
void main() {
float rotation = 0.0;
sPos = position;
vec3 scale;
scale.x = 1.0*stretch;
scale.y = 1.0*stretch;
scale.z = 1.0*stretch;
vec3 alignedPosition = vec3(position.x * scale.x, position.y * scale.y, 0.0);
vec3 rotatedPosition;
rotatedPosition.x = cos(rotation) * alignedPosition.x - sin(rotation) * alignedPosition.y;
rotatedPosition.y = sin(rotation) * alignedPosition.x + cos(rotation) * alignedPosition.y;
rotatedPosition.z = alignedPosition.z;
vec4 finalPosition;
finalPosition = modelViewMatrix * vec4( pos, 1.0 );
finalPosition.xyz += rotatedPosition;
finalPosition = projectionMatrix * finalPosition;
gl_Position = finalPosition;
}`;
var FragmentShader = `
varying vec3 sPos;
void main() {
vec3 nDistVec = normalize(sPos);
float dist = pow(sPos.x, 2.0) + pow(sPos.y, 2.0);
float magnitude = 1.0/dist * pow(3.0, 2.0);
float alpha = 1.0;
if(magnitude < 0.01){
alpha = 0.0;
}
gl_FragColor = vec4(vec3(1.0, 1.0, 0.8), alpha) * magnitude;
// gl_FragColor = vec4(vec3(1.0, 1.0, 0.8), 1.0);
}`;
var uniform = {
stretch: {type: 'f', value: 1.0},
pos: { value: new THREE.Vector3(0,0,0) },
}
var Shader = new THREE.ShaderMaterial( {
uniforms: uniform,
vertexShader: VertexShader,
fragmentShader: FragmentShader,
transparent: true,
depthTest: false,
depthWrite: false
});
//-------------------------------------------------
//create a plane: points, normals, uv
const vertices = [
{ pos: [-20, -20, 0], norm: [ 0, 0, 1], uv: [0, 1], },
{ pos: [ 20, -20, 0], norm: [ 0, 0, 1], uv: [1, 1], },
{ pos: [-20, 20, 0], norm: [ 0, 0, 1], uv: [0, 0], },
{ pos: [ 20, 20, 0], norm: [ 0, 0, 1], uv: [1, 0], },
];
const numVertices = vertices.length;
const positionNumComponents = 3;
const normalNumComponents = 3;
const uvNumComponents = 2;
//arrays for buffergeometry
const positions = new Float32Array(numVertices * positionNumComponents * MAX_Planes);
const normals = new Float32Array(numVertices * normalNumComponents * MAX_Planes);
const uvs = new Float32Array(numVertices * uvNumComponents * MAX_Planes);
//fill arrays with vertices
var posPointer = 0;
var nrmPointer = 0;
var uvPointer = 0;
for(var i = 0; i <= MAX_Planes; i++) {
var posNdx = 0;
var nrmNdx = 0;
var uvNdx = 0;
for (const vertex of vertices) {
positions.set(vertex.pos, posNdx + posPointer);
normals.set(vertex.norm, nrmNdx + nrmPointer);
uvs.set(vertex.uv, uvNdx + uvPointer);
posNdx += positionNumComponents;
nrmNdx += normalNumComponents;
uvNdx += uvNumComponents;
}
posPointer = i * posNdx;
nrmPointer = i * nrmNdx;
uvPointer = i * uvNdx;
}
//create buffergeometry and assign the attribut arrays
geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, positionNumComponents));
geometry.setAttribute('normal', new THREE.BufferAttribute(normals, normalNumComponents));
geometry.setAttribute('uv', new THREE.BufferAttribute(uvs, uvNumComponents));
var ndx = 0;
var indices = [];
//instead 6 vertices for the both triangles of a plane i used 4, so reindication is neccessary
for(var i = 0; i < MAX_Planes; i++){
indices.push(ndx, ndx + 1, ndx + 2, ndx + 2, ndx + 1, ndx + 3);
ndx += 4;
}
geometry.setIndex(indices);
var materials = [];
geometry.clearGroups();
for(var i = 0; i < MAX_Planes; i++){
geometry.addGroup( 6*i, 6, i );
materials.push(Shader.clone());
}
plane = new THREE.Mesh(geometry, materials);
scene.add(plane);
//----------------------velocity---------------------------
for(var i = 0; i < MAX_Planes; i++){
velocity[i] = new THREE.Vector3(
Math.random()*2-1,
Math.random()*2-1,
Math.random()*2-1);
}
}//-------End init----------
function animate() {
requestAnimationFrame( animate );
render();
}//-------End animate----------
var loop = 0;
function render() {
loop = loop + 0.5;
for(var i = 0; i < MAX_Planes; i++){
var pos = new THREE.Vector3(0, 0, 0);
pos.x += velocity[i].x*loop;
pos.y += velocity[i].y*loop;
pos.z += velocity[i].z*loop;
plane.material[i].uniforms.pos.value = pos;
}
plane.geometry.attributes.position.needsUpdate = true;
camera.updateMatrixWorld();
camera.updateProjectionMatrix();
renderer.render(scene, camera);
}//-------End render----------
Я установил здесь 2000 прямоугольников и приятно удивлен тем, насколько плавно работает код. Даже с 5000 прямоугольников все прошло гладко, хотя каждый прямоугольник имеет свой шейдер. геометрия буфера действительно классная.
Спасибо TheJim01
без вашего совета я бы предварительно инициализировал все шейдеры в a для l oop. Такие как vertexshader [i], fragmentshader [i], uniforms [i], Shader [i]. Использование ".clone ()", конечно, намного лучше ?