无法让 Three.js InstancedBufferGeometry 出现在场景中

编程入门 行业动态 更新时间:2024-10-28 19:20:58
本文介绍了无法让 Three.js InstancedBufferGeometry 出现在场景中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送ChatGPT账号..

我似乎无法再让 InstancedBufferGeometry 出现在场景中.我尝试了以下技术:

I can't seem to get an InstancedBufferGeometry to appear in a scene anymore. I've tried the following technique:

let bg = BoxBufferGeometry(3,3,3),
    ig : InstancedBufferGeometry = new InstancedBufferGeometry(),
    mesh : Mesh;

    ig.index = bg.index;
    ig.attributes.position = bg.attributes.position;
    ig.attributes.uv = bg.attributes.uv;
    
    //ig.copy( bg ); <- also tried this
    
    ig.instanceCount = Infinity; <- otherwise this populates as undefined

    var offsets = [];
    var orientations = [];
    var vector = new Vector4();
    var x, y, z, w;

for ( var i = 0; i < 1000; i ++ ) {

    // offsets
    x = Math.random() * 100 - 50;
    y = Math.random() * 100 - 50;
    z = Math.random() * 100 - 50;

    vector.set( x, y, z, 0 ).normalize();
    vector.multiplyScalar( 5 );

    offsets.push( x + vector.x, y + vector.y, z + vector.z );

    // orientations
    x = Math.random() * 2 - 1;
    y = Math.random() * 2 - 1;
    z = Math.random() * 2 - 1;
    w = Math.random() * 2 - 1;

    vector.set( x, y, z, w ).normalize();
    orientations.push( vector.x, vector.y, vector.z, vector.w );
}

var offsetAttribute = new InstancedBufferAttribute( new Float32Array( offsets ), 3 );
var orientationAttribute = new InstancedBufferAttribute( new Float32Array( orientations ), 4 ).setUsage( DynamicDrawUsage );

ig.setAttribute( 'offset', offsetAttribute );
ig.setAttribute( 'orientation', orientationAttribute );

let m = new MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } );

mesh = new Mesh( ig, m );
scene.add(mesh);

我没有收到任何错误,并且当我检查时网格确实出现在场景中.我已经尝试了 IBG 中的所有属性组合.

I don't get any errors and the mesh does appear in the scene when I inspect. I've tried all combinations of attributes in the IBG.

这种方法不再有效了吗?(它在 r97 中有效......我知道,很久以前.)

Will this approach no longer work? (It worked in r97... I know, ages ago. )

推荐答案

let m = new MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } );

let m = new MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } );

当使用 InstancedBufferGeometry 时,您不能使用像 MeshPhongMaterial 这样的内置材质创建网格.相反,您必须创建一个利用实例化属性的自定义着色器.示例:

When using InstancedBufferGeometry, you can't create a mesh with built-in materials like MeshPhongMaterial. Instead you have to create a custom shader that utilizes the instanced attributes. Example:

var camera, scene, renderer;

init();
animate();

function init() {

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.z = 100;

  scene = new THREE.Scene();

  var geometry = new THREE.BoxBufferGeometry();

  var ig = new THREE.InstancedBufferGeometry();
  ig.index = geometry.index;
  ig.attributes.position = geometry.attributes.position;

  var offsets = [];
  var orientations = [];
  var vector = new THREE.Vector4();
  var x, y, z, w;

  for (var i = 0; i < 1000; i++) {

    // offsets
    x = Math.random() * 100 - 50;
    y = Math.random() * 100 - 50;
    z = Math.random() * 100 - 50;

    vector.set(x, y, z, 0).normalize();

    offsets.push(x + vector.x, y + vector.y, z + vector.z);

    // orientations
    x = Math.random() * 2 - 1;
    y = Math.random() * 2 - 1;
    z = Math.random() * 2 - 1;
    w = Math.random() * 2 - 1;

    vector.set(x, y, z, w).normalize();
    orientations.push(vector.x, vector.y, vector.z, vector.w);
  }

  var offsetAttribute = new THREE.InstancedBufferAttribute(new Float32Array(offsets), 3);
  var orientationAttribute = new THREE.InstancedBufferAttribute(new Float32Array(orientations), 4);

  ig.setAttribute('offset', offsetAttribute);
  ig.setAttribute('orientation', orientationAttribute);

  var material = new THREE.RawShaderMaterial({
    vertexShader: document.getElementById('vertexShader').textContent,
    fragmentShader: document.getElementById('fragmentShader').textContent,
    side: THREE.DoubleSide
  });

  mesh = new THREE.Mesh(ig, material);
  scene.add(mesh);

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

}

function animate() {

  requestAnimationFrame(animate);
  renderer.render(scene, camera);

}

body {
      margin: 0;
}

<script src="https://cdn.jsdelivr/npm/three@0.124/build/three.js"></script>

<script id="vertexShader" type="x-shader/x-vertex">
        precision highp float;

        uniform mat4 modelViewMatrix;
        uniform mat4 projectionMatrix;

        attribute vec3 position;
        attribute vec3 offset;
        attribute vec4 orientation;

        void main(){

            vec3 pos = offset + position;
            vec3 vcV = cross( orientation.xyz, pos );
            pos = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + pos );

            gl_Position = projectionMatrix * modelViewMatrix * vec4( pos, 1.0 );

        }

    </script>

    <script id="fragmentShader" type="x-shader/x-fragment">

        precision highp float;

        void main() {

            gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);

        }

    </script>

考虑使用 InstancedMesh 以获得更直接的用法实例化渲染.

Consider to use InstancedMesh for a more straightforward usage of instanced rendering.

这篇关于无法让 Three.js InstancedBufferGeometry 出现在场景中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

更多推荐

[db:关键词]

本文发布于:2023-04-30 14:55:50,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1395762.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:景中   js   InstancedBufferGeometry

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!