【问题标题】:With Instancing, I am not able to change the transparency/opacity of the individual child geometries使用 Instancing,我无法更改单个子几何图形的透明度/不透明度
【发布时间】:2019-12-03 20:12:31
【问题描述】:

我有一个由 1000 个球体实例组成的简单模型。我正在尝试使用实例化来减少绘图调用的数量。但是,我无法更改单个子几何图形的透明度/不透明度。

我已经尝试了以下方法:

我可以使用

更改每个球体的透明度
material.fragmentShader = "varying vec3 vColor;void main() {  gl_FragColor = vec4( vColor, 0.2 );}"; 

但是,这会将每个球体的不透明度更改为 0.2。

html文件是这样的:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>A-Frame Instancing component</title>
    <meta name="description" content="A-Frame Instancing component">
    <script>
    /*
    var WebVRConfig = {
        FORCE_ENABLE_VR: true,
        BUFFER_SCALE: 1.0
    };
    */
    </script>
    <script src="https://cdn.rawgit.com/aframevr/aframe/v0.4.0/dist/aframe-master.min.js"></script>
    <script src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v3.2.0/dist/aframe-extras.min.js"></script>
    <script type="text/javascript" src="build/aframe-instancing.js"></script>
  </head>
  <body>
    <a-scene stats>
      <a-assets>
        <img id="sky" src="https://cdn.rawgit.com/aframevr/aframe/master/examples/primitives/models/peach-gradient.jpg">
      </a-assets>
      <a-entity instancing="count:100"></a-entity>
      <a-sky src="#sky"></a-sky>
      <a-entity light="type:directional;color:#FFFFFF" position="-1 1 1"></a-entity>
    </a-scene>
  </body>
</html>

实现实例化的功能:

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

        var geometry = new THREE.InstancedBufferGeometry();
        geometry.copy(new THREE.SphereBufferGeometry(5.0));


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

         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 );',
            '}'
          ].join('\n')
        });

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

        this.model = mesh;
        el.setObject3D('mesh', mesh);

        el.emit('model-loaded', {format:'mesh', model: mesh});
        //try to change opacity here
        material.fragmentShader = "varying vec3 vColor;void main() {  gl_FragColor = vec4( vColor, 0.2 );}";

        material.transparent = true;

        //use the new opacity
        var mesh1 = new THREE.Mesh(geometry1, material);
        this.mesh = mesh1;
        el.setObject3D('mesh', mesh1);
        el.emit('model-loaded', {format:'mesh', model: mesh1});
      }   
    });
 }
 ]);

谁能告诉我,如何只改变一个球体的不透明度?提前谢谢!

另外,假设我正在尝试复制多个框。 其中之一如下:

    <a-box position="19.0 1.5 23.0"
           width="32.0"
           height="1.0"
           depth="40.0"
           color="#969696"
           shader="flat"
           flat-shading="true">
    </a-box>

我将填写 translateArray 和 vectorArray 的值是多少? 提前非常感谢!

【问题讨论】:

    标签: javascript three.js aframe buffer-geometry geometry-instancing


    【解决方案1】:

    您的颜色只是RGB 值,而不是RGBA。更新您的 color 属性以支持 4 个值,并将关联的 vec3 引用更改为使用 vec4。向量中的最后一个值将是您的 alpha(透明度)值。

    看起来您已经知道如何将值从您的vertex shader 发送到您的fragment shader,所以我不会在那里详细介绍。但是在您的fragment shader 中,您可以直接使用颜色,因为gl_FragColor 期望设置为vec4

    进一步说明:

    当您创建InstancedBufferAttribute 时,您为每个实例创建一个属性。因此,您的 color 属性目前仅包含每个实例的 RGB 值。

    硬编码10.2w 位置(即gl_FragColor = vec4( vColor, 1 );),您可以将其普遍应用于所有实例。因此,您需要在每个实例的基础上定义 alpha 值,最简单的方法是通过您已经创建和实例化的 color 属性。

    //geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 3, 1)
    geometry.addAttribute('color', new THREE.InstancedBufferAttribute(colorArray, 4, 1)
    

    上面的代码为您应该为每个球体提供的 alpha 值留出了空间。您的colorArray 将包含[ R, G, B, A, R, G, B, A, ... ] 之类的数据。

    然后,在你的着色器中...

    // vertex shader
    // ...
    attribute vec4 color;
    varying vec4 vColor;
    // ...
    void main(){
      // ...
      vColor = color;
      // ...
    }
    
    // fragment shader
    // ...
    varying vec4 vColor;
    // ...
    void main(){
      // ...
      gl_FragColor = vColor;
    }
    

    现在,您为每个球体实例提供的 alpha 值将仅用于该实例。例如,如果您希望索引 1 处的球体成为唯一透明的球体,您的 colorArray 缓冲区应如下所示:

    colorArray = [
      1.0, 1.0, 1.0, 1.0,
      1.0, 1.0, 1.0, 0.5,
      1.0, 1.0, 1.0, 1.0,
      // ...
    ];`
    

    重要提示

    此实现不对实例进行深度排序,因此混合将取决于渲染顺序。您可以在以下问题中阅读更多相关信息:

    Transparency within instanced shapes

    【讨论】:

    • 我理解第四项是alpha值。我的问题是,是否可以只改变一个球体的透明度,而不改变其他球体的透明度?缓冲区几何不允许这样做,实例化是否可能?感谢您的回复。
    • @ShubhamKumar 我添加了更多信息来澄清这一点。我希望它有所帮助。
    • 感谢您的回复!它解释了很多:)
    • 我在最后的问题中添加了一点疑问。你也能澄清一下吗?提前非常感谢!
    • @ShubhamKumar 我猜那是框架?我真的对此一无所知。此外,这似乎是一个单独的问题,值得单独提出一个问题。一定要标记一个框架。 :)
    猜你喜欢
    • 1970-01-01
    • 2018-12-07
    • 1970-01-01
    • 2016-12-02
    • 1970-01-01
    • 2013-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    相关资源
    最近更新 更多