threejs实例多个具有不同大小和位置的对象 [英] threejs instance multiple objects with different sizes and positions

查看:646
本文介绍了threejs实例多个具有不同大小和位置的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就在昨天,我开始尝试使用InstancedBufferGeometry方法,因为我想渲染具有良好性能的数千个对象。
以我为例,我想实例化彼此不同高度的多维数据集几何。
此刻我尝试了这段代码

just yesterday i started to tried the InstancedBufferGeometry method because i want to render thousand of objects with a good performance. In my case i want to instance cube geometries with different heights of each other. At moment i tried this code

AFRAME.registerComponent('instancing', {
  schema: {
    count: {type: 'int', default: 10000}
  },

  init: function () {
    this.count = this.data.count;
    this.model = null;
  },

  update: function () {
    if (this.model !== null) { return; }

    var data = this.data;
    var el = this.el;

    var count = this.count;

    var geometry = new THREE.InstancedBufferGeometry();
    geometry.copy(new THREE.BoxBufferGeometry(10, 5, 10));

    var translateArray = new Float32Array(count*3);
    var vectorArray = new Float32Array(count*3);
    var colorArray = new Float32Array(count*3);
    var vertices = new Float32Array(count * 24);

    for(var i = 0; i < count; i++){
      var y = Math.floor((Math.random() * 200) + 50);
      vertices[i*3+0] = 10;
      vertices[i*3+1] = y;
      vertices[i*3+2] = 10;

      vertices[i*24+3] = 10;
      vertices[i*24+4] = y;
      vertices[i*24+5] = -10;

      vertices[i*24+6] = 10;
      vertices[i*24+7] = -y;
      vertices[i*24+8] = 10;

      vertices[i*24+9] = 10;
      vertices[i*24+10] = -y;
      vertices[i*24+11] = -10;

      vertices[i*24+12] = -10;
      vertices[i*24+13] = y;
      vertices[i*24+14] = -10;

      vertices[i*24+15] = -10;
      vertices[i*24+16] = y;
      vertices[i*24+17] = 10;

      vertices[i*24+18] = -10;
      vertices[i*24+19] = -y;
      vertices[i*24+20] = -10;

      vertices[i*24+21] = -10;
      vertices[i*24+22] = -y;
      vertices[i*24+23] = 10;
   }

    for (var i = 0; i < count; i++) {
      translateArray[i*3+0] = (Math.random() - 0.5) * 100.0;
      translateArray[i*3+1] = (Math.random() - 0.5) * 100.0;
      translateArray[i*3+2] = (Math.random() - 0.5) * 100.0;
    }

    for (var i = 0; i < count; i++) {
      vectorArray[i*3+0] = (Math.random() - 0.5) * 100.0;
      vectorArray[i*3+1] = (Math.random() + 1.5) * 100.0;
      vectorArray[i*3+2] = (Math.random() - 0.5) * 100.0;
    }

    for (var i = 0; i < count; i++) {
      colorArray[i*3+0] = Math.random();
      colorArray[i*3+1] = Math.random();
      colorArray[i*3+2] = Math.random();
    }

    geometry.addAttribute('position', new THREE.InstancedBufferAttribute(vertices, 24, 1));
    geometry.addAttribute('translate', new THREE.InstancedBufferAttribute(translateArray, 3, 1));
    geometry.addAttribute('vector', new THREE.InstancedBufferAttribute(vectorArray, 3, 1));
    geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1));

    var material = new THREE.ShaderMaterial({
      uniforms: {
        time: {value: 0}
      },
      vertexShader: [
        'attribute vec3 translate;',
        'attribute vec3 vector;',
        'attribute vec3 color;',
        'uniform float time;',
        'varying vec3 vColor;',
        'const float g = 9.8 * 1.5;',
        'void main() {',
        '  vec3 offset;',
        '  offset.xz = vector.xz * time;',
        '  offset.y = vector.y * time - 0.5 * g * time * time;',
        '  gl_Position = projectionMatrix * modelViewMatrix * vec4( position + translate + offset, 1.0 );',
        '  vColor = color;',
  '}'
      ].join('\n'),
      fragmentShader: [
        'varying vec3 vColor;',
        'void main() {',
        '  gl_FragColor = vec4( vColor, 1.0 );',
        '}'
      ].join('\n')
    });

    var mesh = new THREE.Mesh(geometry, material);

    this.model = mesh;
    el.setObject3D('mesh', mesh);
    el.emit('model-loaded', {format:'mesh', model: mesh});
  },

  tick: function(time, delta) {
    if (this.model === null) { return; }

    var mesh = this.model;
    mesh.material.uniforms.time.value = (mesh.material.uniforms.time.value + delta / 1000) % 30.0;
  }
});

但我有此错误

[。Web上的WebGL-0x17d96d74a000] GL错误:GL_INVALID_VALUE:glVertexAttribPointer:大小GL_INVALID_VALUE
(索引):1 [.Web上的WebGL-0x17d96d74a000] GL错误:已启用GL_INVALID_OPERATION:glDrawElements属性1:没有缓冲区

招募到threejs低层函数。我从一个框架开始,但不幸的是,我发现在这种情况下,正常使用此框架不足以实现良好的性能。

im a recruit to threejs low level functions. i started with aframe but unfortunately i see that in my case the normal use of this framework is not sufficent to have good performances.

我的目标是拥有多个不同的多维数据集在不同位置的尺寸。有什么建议吗?预先感谢

my goal is to have multiple cubes with different sizes in different positions. any suggestion? thanks in advance

TheJim解决方案。

with TheJim solution.

推荐答案

首先,不应重新定义位置 ShaderMaterial 注入常见的属性,包括 position ,并且您的定义与此冲突。如果您想自己定义一切,请查看 RawShaderMaterial

First, position should not be re-defined. ShaderMaterial injects common attributes, including position, and your definition conflicts with that. If you'd like to define everything yourself, look into RawShaderMaterial.

第二,请记住,您正在定义一个多维数据集的顶点,索引和法线,然后使用着色器/实例化处理其余部分。仅将实例特定的数据定义为 InstancedBufferAttribute s。

Second, remember, you're defining the vertices, indices, and normals for ONE cube, then using shaders/instancing to manipulate the rest. Only instance-specific data should be defined as InstancedBufferAttributes.

请看以下示例:

var cubeGeo = new THREE.InstancedBufferGeometry().copy(new THREE.BoxBufferGeometry(10, 10, 10));
//cubeGeo.maxInstancedCount = 8;

cubeGeo.addAttribute("cubePos", new THREE.InstancedBufferAttribute(new Float32Array([
  25, 25, 25,
  25, 25, -25, -25, 25, 25, -25, 25, -25,
  25, -25, 25,
  25, -25, -25, -25, -25, 25, -25, -25, -25
]), 3, 1));

var vertexShader = [
  "precision highp float;",
  "",
  "uniform mat4 modelViewMatrix;",
  "uniform mat4 projectionMatrix;",
  "",
  "attribute vec3 position;",
  "attribute vec3 cubePos;",
  "",
  "void main() {",
  "",
  " gl_Position = projectionMatrix * modelViewMatrix * vec4( cubePos + position, 1.0 );",
  "",
  "}"
].join("\n");
var fragmentShader = [
  "precision highp float;",
  "",
  "void main() {",
  "",
  " gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);",
  "",
  "}"
].join("\n");

var mat = new THREE.RawShaderMaterial({
  uniforms: {},
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
  transparent: true
});

var mesh = new THREE.Mesh(cubeGeo, mat);

scene.add(mesh);

像您一样,我创建了一个多维数据集(仅一个多维数据集)。然后,我添加一个名为 cubePos InstancedBufferAttribute ,它将更改多维数据集的位置( cubePos 在此示例中适用于所有顶点。这类似于您的 translate 属性。

Like you, I've created a cube (just one cube). I then add an InstancedBufferAttribute named cubePos which will change the positions of the cubes (cubePos applies to ALL vertices in this example). This is similar to your translate attribute.

就拉伸多维数据集而言,您似乎很近和您的位置属性。如果只是给它一个非内置的名称,例如 stretch

As far as stretching the cubes, it looks like you may be close with your position attribute. It may work as you expect if you simply give it a name that is not built-in, like stretch.

个人而言,由于您似乎在两个方向上均等地拉伸它,因此我可能只需要为每个实例传递一个值,然后使用它在两个Y方向上缩放多维数据集。

Personally, since it looks like you're stretching it equally in both directions, I'd probably just pass in a single value per instance, and use it to scale the cube in both Y directions.

这篇关于threejs实例多个具有不同大小和位置的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆