Instancing prohibits me from adjusting the transparency or opacity of each specific child geometry

I am currently working on a project that involves a simple model made up of 1000 instances of spheres. In an effort to optimize performance by reducing the number of draw calls, I decided to implement instancing. However, I encountered an issue with changing the transparency or opacity of each individual sphere within the model.

Here are the solutions I have attempted so far:

I managed to alter the transparency of all spheres using the following code:

material.fragmentShader = "varying vec3 vColor;void main() {  gl_FragColor = vec4( vColor, 0.2 );}"; 

Unfortunately, this adjustment applied an opacity of 0.2 to every sphere, which is not what I intended.

Below is a snippet of the HTML file structure:

<!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>

Here's the instance function to implement instancing:

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});
        //attempting to change opacity here
        material.fragmentShader = "varying vec3 vColor;void main() {  gl_FragColor = vec4( vColor, 0.2 );}";

        material.transparent = true;

        //applying 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});
      }   
    });
 }
 ]);

I would appreciate any advice on how to alter the opacity of a single sphere rather than all spheres in the model. Thank you!

Furthermore, if I were to replicate multiple boxes, the structure of one box instance would be as follows:

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

What specific values should be used in translateArray and vectorArray? Your insights would be greatly appreciated. Thank you!

Answer №1

Your current color values are limited to RGB, without the alpha channel (RGBA). To include transparency, update your color attribute to support all 4 values and adjust the corresponding references in vec3 to vec4. The last value in the vector will represent the alpha (transparency) level.

Based on your existing knowledge of passing values from the vertex shader to the fragment shader, it is assumed you understand that gl_FragColor requires a vec4 input. Therefore, you can directly use the color in the fragment shader.

Additional Explanation:

When creating an InstancedBufferAttribute, one attribute is generated per instance. Currently, your color attribute only holds RGB values for each instance.

By hard-coding 1 or 0.2 in the w place (e.g. gl_FragColor = vec4( vColor, 1 );), the alpha value applies universally to all instances. To set alpha on a per-instance basis, utilize the instanced color attribute already defined.

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

The updated code accommodates alpha values supplied for each sphere. Your colorArray should contain data in the format [ R, G, B, A, R, G, B, A, ... ].

Subsequently, in your shaders...

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

With this setup, the alpha value specified for each sphere instance will be isolated to that instance. For instance, to make only index 1 sphere transparent, the colorArray buffer should have entries like:

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,
  // ...
];`

Important Note

This implementation does not sort the instances by depth, so blending will rely on render order. For more information, refer to the following question:

Understanding Transparency in Instanced Shapes

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Push the accordion tab upwards towards the top of the browser

I am working on an accordion menu that contains lengthy content. To improve user experience, I want to implement a slide effect when the accordion content is opened. Currently, when the first two menu items are opened, the content of the last item is disp ...

What is the best method to showcase an array representing a key-value pair enclosed in {} as a list item within VueJS?

I have a specific object structure with a key that contains an array as its value. How can I present this information to the user in a list format? allComponents: [ {name: 'Standard field', uses: ['Inconsistent inputs', 'Formul ...

Converting HTML widget code to NEXTjs code for integration in an application (CoinMarketCap Price Marquee Ticker)

Having trouble integrating the CoinMarketCap Price Marquee Ticker Widget into my NEXTjs app. I'm outlining my process and hoping for some suggestions from others who may have attempted this. Template Code: To embed the widget in an HTML page, here is ...

Loading an HTML page using jQuery's .load() method that contains embedded JavaScript

I'm facing an issue with loading .html pages (including JavaScript) into a div element. Below is my div setup: <div class="content"></div> This is my php code: <?php if(!$_POST['page']) die("0"); $page = (int)$_POST[&a ...

What is the best method for converting a variable with HTML content into a printable string?

In an attempt to display user-entered data from a text box to an HTML div, there seems to be an issue when the data contains HTML content. Instead of displaying the content as a string, it shows it as HTML elements. For example: let text = "<h1>Worl ...

Can someone explain why my Laravel route is consistently showing a 404 error?

Currently, I am attempting to perform an AJAX request for a form post type. However, the PHP parse script I am trying to send the data to is returning a 404 error as observed through Chrome developer tools. Below is the code snippet: <script type="text ...

The Javascript logic on the NewForm for a Sharepoint 2013 on-premise list is failing to trigger

Screen shot linkThere seems to be an issue with the code I have written. The save button should only be enabled if all 5 checkboxes are ticked, but currently, the button is not disabled on form load. I have tried adding the code in both CEWP and SEWP, bu ...

Is it possible to expand the CORS permissions to the routers directly from the app?

I have a couple of questions: Is it possible to just use cors() once in my server.js instead of having to call and use it in every router file? Can I simply require express once in my server.js without having to call it in all my router files? Currently, ...

How can I prevent mouse movement hover effects from activating in a media query?

I have implemented a custom image hover effect for links in my text using mousemove. However, I want to disable this feature when a specific media query is reached and have the images simply serve as clickable links without the hover effect. I attempted ...

The controller is unable to provide the output in JSON format within the AJAX response

My task requires me to continuously call and fetch data from a REST API every second. To achieve this, I am calling the method with a time interval of 1 second as shown below: var myVar = setInterval(function(){ getData1() }, 1000); Below is the JavaScri ...

Collaborating on a single instance across several processes

I have a messaging bot in my project, where the connection is established using a class instance. class MessagingBot { public bot; constructor() { this.bot = new TelegramBot(); } } export default MessagingBot; In another file, I create an inst ...

Is it possible to eliminate the dedupe feature in npm?

By mistake, I accidentally ran the command npm dedupe and now all of my node_modules directories are flattened. While this reduces file size, it's making it more difficult to find things. Is there a way to reverse this and return to the hierarchical f ...

Create names for links using jQuery based on the data received from an AJAX response

I am currently utilizing the jQuery UI tooltip script available at this link. As a result, I have tooltip links with varying "data-id" attributes like so: <a tooltip-link data-id="12555"></a> <a tooltip-link data-id="38"& ...

Prevent incorrect data input by users - Enhancing JavaScript IP address validation

I have been trying to create a masked input field for entering IP addresses, but every solution I come across seems to have some flaws. The best solution I found so far is , but it still allows values higher than 255 to be entered. It works fine initially ...

What is the best way to efficiently import multiple variables from a separate file in Vue.JS?

When working with a Vue.JS application and implementing the Vuex Store, I encountered an issue in my state.js file where I needed to import configurations from another custom file, specifically config.js. Upon running it, I received the following warning ...

Using JQuery and Javascript to retrieve information from one drop down list based on the selection made in another drop down

I'm currently working on a project that involves 2 drop-down menus. The first menu allows you to select a general model, while the second menu displays specific models based on your selection. http://jsfiddle.net/QskM9/ Here's an example of how ...

Integrating a personalized dropdown feature into the Froala editor within an AngularJS environment

After searching for a JavaScript rich text editor that doesn't use frames and allows easy customization of the toolbar with custom dropdowns, I came across the Froala editor. It also offers AngularJS-friendly directives. Previously, I tried using Text ...

Node.js expressing caution about the use of backslashes in console logging statements

While this issue may not be considered crucial, I have observed an unexpected behavior when it comes to logging backslashes to the console. To verify the results, please try the following two examples in your terminal. I experimented with versions 0.10 an ...

The protection ensured by employing an extensive hash in the query string for the recognition of a changing document

I am currently developing a small web application that creates exercise program printouts. The concept is simple - a user like a personal trainer can craft an exercise regimen and send it to their client via email using a unique link. http://www.myurl ...

How to access a component attribute in a JavaScript library method in Angular 8

Within my Angular project, I am utilizing Semantic UI with the code snippet below: componentProperty: boolean = false; ngOnInit() { (<any>$('.ui.dropdown')).dropdown(); (<any>$('.ui.input')).popup({ ...