【问题标题】:Updating InstancedBufferGeometry and InstancedBufferAttributes code from r95 to r124将 InstancedBufferGeometry 和 InstancedBufferAttributes 代码从 r95 更新到 r124
【发布时间】:2021-01-18 11:57:46
【问题描述】:

我的问题与几年前回答的 Q 有关,我正在努力: three.js texture across InstanceGeometry

我正在将我的应用程序从 r95 更新到最新的 r124。

首先我创建了 InstancedBufferGeometry(Geometry.createBuffered 是我自己的位,它可以从一些 JSON 中弹出任何类型的几何):

let bg = Geometry.createBuffered(id, params.instance.geo),
        ig : InstancedBufferGeometry = new InstancedBufferGeometry(),
        mesh;
    
    ig.copy( bg );

然后我开始从 JSON 参数生成 InstancedBufferAttributes 并将它们分配给 IBG:

for(var x = 0; x < xl; x++){
    for ( var y = 0; y < yl; y++) {
        for ( var z = 0; z < zl; z++) {

            ox = ( x * params.instance.arrayPlacement.spacing[0] - disX ) + Math.random() * ( params.instance.arrayPlacement.displacement[1] - params.instance.arrayPlacement.displacement[0] ) + params.instance.arrayPlacement.displacement[0];
            oy = ( y * params.instance.arrayPlacement.spacing[1] - disY ) + Math.random() * ( params.instance.arrayPlacement.displacement[1] - params.instance.arrayPlacement.displacement[0] ) + params.instance.arrayPlacement.displacement[0];
            oz = ( z * params.instance.arrayPlacement.spacing[2] - disZ ) + Math.random() * ( params.instance.arrayPlacement.displacement[1] - params.instance.arrayPlacement.displacement[0] ) + params.instance.arrayPlacement.displacement[0];

            offsets[ count * 3 ] = ox;
            offsets[ ( count * 3 ) + 1 ] = oy;
            offsets[ ( count * 3 ) + 2 ] = oz;
            
            scales[count] = Math.random() * (params.instance.arrayPlacement.scale[1] - params.instance.arrayPlacement.scale[0]) + params.instance.arrayPlacement.scale[0];
            
            orientations[ count * 4 ] = -0.5;
            orientations[ ( count * 4 ) + 1 ] = -0.5;
            orientations[ ( count * 4 ) + 2 ] = -0.5; 
            orientations[ ( count * 4 ) + 3 ] = 0.5;

            uvOffsets[ count * 2 ] = y;  
            uvOffsets[ ( count * 2 ) + 1 ] = x; 

            iCount[ count * 2 ] = 1/yl; 
            iCount[ ( count * 2 ) + 1 ] = 1/xl;

            
            
            count++;
        }
    }
}

let roti : InstancedBufferAttribute = new InstancedBufferAttribute( orientations, 4).setUsage( DynamicDrawUsage ),
    offs : InstancedBufferAttribute = new InstancedBufferAttribute( offsets, 3 ).setUsage( DynamicDrawUsage ),
    uvOffs : InstancedBufferAttribute = new InstancedBufferAttribute( uvOffsets, 2 ).setUsage( DynamicDrawUsage ),
    iC : InstancedBufferAttribute = new InstancedBufferAttribute( iCount, 2 ).setUsage ( DynamicDrawUsage ),
    scas : InstancedBufferAttribute = new InstancedBufferAttribute( scales, 1 ).setUsage( DynamicDrawUsage );


ig.setAttribute( 'offset', offs );
ig.setAttribute( 'uvOffset',  uvOffs);
ig.setAttribute('iCount', iC);
ig.setAttribute( 'iScale', scas );
ig.setAttribute( 'orientation',  roti );

然后,我使用带有 uvoffsets 和颜色的自定义着色器制作材质。但是,当我使用基本的 3js 材质创建网格时,什么也没有出现。如果我检查场景,网格就在那里,没有错误screenshot

更新: @Mugen87 是正确的,我仍在运行 r115。对于那个很抱歉。我现在在 r124 上,但奇怪的是,当我创建 IBG 时,我仍然看到 maxInstancedCount 以及 instanceCount(未定义)。此外,当我使用 IBG.copy(BoxBufferGeometry) 时,几何似乎没有被复制。我假设 BoxBufferGeometry 创建了一个 BufferGeometry?还是在 r125 中推出?

【问题讨论】:

  • maxInstancedCount 在您的照片上未定义。您需要使用实例数量进行设置。只需ig.maxInstancedCount = _some_integer_;,在您设置属性之后。

标签: three.js


【解决方案1】:

您的屏幕截图具有误导性,因为 r124 InstancedBufferGeometry 没有 maxInstanceCount 属性。

r117 maxInstancedCount 被重命名为 instanceCount。因为它的默认值是Infinity,如果你想渲染几何体中的所有实例,就不需要设置它。

我建议您使用以下代码作为您自己的应用程序的模板:

let camera, scene, renderer;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10);
    camera.position.z = 2;

    scene = new THREE.Scene();

    // geometry

    const vector = new THREE.Vector4();

    const instances = 50000;

    const positions = [];
    const offsets = [];
    const colors = [];
    const orientationsStart = [];
    const orientationsEnd = [];

    positions.push(0.025, -0.025, 0);
    positions.push(-0.025, 0.025, 0);
    positions.push(0, 0, 0.025);

    // instanced attributes

    for (let i = 0; i < instances; i++) {

        // offsets

        offsets.push(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5);

        // colors

        colors.push(Math.random(), Math.random(), Math.random(), Math.random());

        // orientation start

        vector.set(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1);
        vector.normalize();

        orientationsStart.push(vector.x, vector.y, vector.z, vector.w);

        // orientation end

        vector.set(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1);
        vector.normalize();

        orientationsEnd.push(vector.x, vector.y, vector.z, vector.w);

    }

    const geometry = new THREE.InstancedBufferGeometry();

    geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
    geometry.setAttribute('offset', new THREE.InstancedBufferAttribute(new Float32Array(offsets), 3));
    geometry.setAttribute('color', new THREE.InstancedBufferAttribute(new Float32Array(colors), 4));
    geometry.setAttribute('orientationStart', new THREE.InstancedBufferAttribute(new Float32Array(orientationsStart), 4));
    geometry.setAttribute('orientationEnd', new THREE.InstancedBufferAttribute(new Float32Array(orientationsEnd), 4));

    // material

    const material = new THREE.RawShaderMaterial({

        uniforms: {
            "time": {
                value: 1.0
            },
            "sineTime": {
                value: 1.0
            }
        },
        vertexShader: document.getElementById('vertexShader').textContent,
        fragmentShader: document.getElementById('fragmentShader').textContent,
        side: THREE.DoubleSide,
        transparent: true

    });

    //

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

    //

    renderer = new THREE.WebGLRenderer();
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    //

    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);

    render();

}

function render() {

    const time = performance.now();

    const object = scene.children[0];

    object.rotation.y = time * 0.0005;
    object.material.uniforms["time"].value = time * 0.005;
    object.material.uniforms["sineTime"].value = Math.sin(object.material.uniforms["time"].value * 0.05);

    renderer.render(scene, camera);

}
body {
  margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three@0.124/build/three.js"></script>

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

        uniform float sineTime;

        uniform mat4 modelViewMatrix;
        uniform mat4 projectionMatrix;

        attribute vec3 position;
        attribute vec3 offset;
        attribute vec4 color;
        attribute vec4 orientationStart;
        attribute vec4 orientationEnd;

        varying vec3 vPosition;
        varying vec4 vColor;

        void main(){

            vPosition = offset * max( abs( sineTime * 2.0 + 1.0 ), 0.5 ) + position;
            vec4 orientation = normalize( mix( orientationStart, orientationEnd, sineTime ) );
            vec3 vcV = cross( orientation.xyz, vPosition );
            vPosition = vcV * ( 2.0 * orientation.w ) + ( cross( orientation.xyz, vcV ) * 2.0 + vPosition );

            vColor = color;

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

        }

    </script>

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

        precision highp float;

        uniform float time;

        varying vec3 vPosition;
        varying vec4 vColor;

        void main() {

            vec4 color = vec4( vColor );
            color.r += sin( vPosition.x * 10.0 + time ) * 0.5;

            gl_FragColor = color;

        }

    </script>

【讨论】:

  • 谢谢你! instanceCount你拯救了我的一天!!我在更改日志中看不到它,好奇你是怎么知道的?
猜你喜欢
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多