Transparency within instanced shapes

前端 未结 2 1625
庸人自扰
庸人自扰 2021-01-24 23:09

I\'ve been playing with THREE.InstancedBufferGeometry. I finally got an example to work, and have now been playing with the shader. The first thing I tried was sett

2条回答
  •  遇见更好的自我
    2021-01-24 23:52

    After discussion with WestLangley in the comments, I added a sorter for my instances. It sorts the instances positions based on their distance from the camera.

    (Side-note: If I had any other THREE.InstancedBufferAttributes I would need to re-order them at the same time.)

    The biggest downside to this is that it becomes more and more expensive as the scene gets bigger, both in instanced and non-instanced shapes.

    // Instances Sorter, called each frame
    function sortObjectInstances(obj) {
      if (obj.geometry) {
        if (obj.geometry instanceof THREE.InstancedBufferGeometry) {
          var array = obj.geometry.attributes.cubePos.array,
            vecArray = [];
          for (var i = 0, l = array.length / 3; i < l; ++i) {
            vecArray.push(new THREE.Vector3(array[(i * 3)], array[(i * 3) + 1], array[(i * 3) + 2]));
          }
          vecArray.sort(function(a, b) {
            if (a.distanceTo(camera.position) > b.distanceTo(camera.position)) {
              return -1;
            }
            if (a.distanceTo(camera.position) < b.distanceTo(camera.position)) {
              return 1;
            }
            return 0;
          });
          for (var i = 0, l = vecArray.length; i < l; ++i) {
            array[(i * 3)] = vecArray[i].x;
            array[(i * 3) + 1] = vecArray[i].y;
            array[(i * 3) + 2] = vecArray[i].z;
          }
          obj.geometry.attributes.cubePos.needsUpdate = true;
        }
      } else {
        for (var i = 0, l = obj.children.length; i < l; ++i) {
          sortObjectInstances(obj.children[i]);
        }
      }
    }
    
    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);
    html * {
      padding: 0;
      margin: 0;
      width: 100%;
      overflow: hidden;
    }
    
    #host {
      width: 100%;
      height: 100%;
    }
    
    
    
    

提交回复
热议问题