Generate particles with custom z-index using BufferGeometry

Two particles were created using threejs BufferGeometry. I want to be able to click on each particle and display the corresponding image.

However, when I clicked on a particle, the image appeared but was then covered by another particle.

I am seeking a solution to remove the hierarchy control from the particles and ensure that the clicked particles always appear on top.

Here is the code:

var scene, camera, renderer,controls;
var points;
var shaderMaterial;

var particleCount = 2;

function init () {
      scene = new THREE.Scene();

      camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
      camera.position.x = 15;
      camera.position.y = 16;
      camera.position.z = 35;
      camera.lookAt(scene.position);

      renderer = new THREE.WebGLRenderer();

      renderer.setClearColor(0x000000, 1.0);

      renderer.setSize(window.innerWidth, window.innerHeight);

      var light = new THREE.AmbientLight( 0xcccccc );

      scene.add(light);

      document.body.appendChild(renderer.domElement);

      createParticles();

      createGrid();

      render();

      document.querySelector('canvas').addEventListener( 'click', interactive, false );

  }

function createParticles () {
    var geometry = new THREE.BufferGeometry();
    var positions = new Float32Array( particleCount * 3 );
    var sizes = new Float32Array( particleCount );
    var pop = new Float32Array( particleCount);

     for (var i = 0, i3 = 0; i < particleCount; i ++, i3 += 3) {
         positions[i3 + 0] = i* 10;
         positions[i3 + 1] = 0.1;
         positions[i3 + 2] = 1;

         sizes[i] = 15;
         pop[i] = 0.0;
     }

    geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
    geometry.addAttribute( 'size', new THREE.BufferAttribute( sizes, 1 ) );
    geometry.addAttribute( 'pop', new THREE.BufferAttribute( pop, 1 ) );

    shaderMaterial = new THREE.ShaderMaterial({
        uniforms: {
            'u_time': {type: 'f', value: 1.0},
            'u_texture_0':   { value: new THREE.TextureLoader().load('https://avatars2.githubusercontent.com/u/5829050?s=256&v=4') }},
        vertexShader:   document.getElementById( 'vs' ).textContent,
        fragmentShader: document.getElementById( 'fs' ).textContent,
        depthTest:      false,
        transparent:    true
    });
    shaderMaterial.uniforms['u_texture_0'].value.flipY = false;

    points = new THREE.Points(geometry, shaderMaterial);

    scene.add(points);

}
var raycaster = new THREE.Raycaster();
raycaster.params.Points.threshold = 5;

var touch = new THREE.Vector2();
var intersects, INTERSECTED;
var beforeIndex;

function interactive (event) {
    touch.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    touch.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    points.geometry.computeBoundingSphere();
    camera.updateMatrixWorld();
    var vector = new THREE.Vector3(touch.x, touch.y, 0.5 ).unproject(camera);
    raycaster.set(camera.position, vector.sub(camera.position ).normalize());
    
    raycaster.setFromCamera( touch, camera );

    intersects = raycaster.intersectObject(points);
    if ( intersects.length > 0 ) {
        if ( INTERSECTED != intersects[ 0 ].index ) {
            INTERSECTED = intersects[ 0 ].index;
            if (beforeIndex != INTERSECTED) {
                points.geometry.attributes.pop.array[ beforeIndex ] = 0.0;
            }
            points.geometry.attributes.pop.array[ INTERSECTED ] = 1.0;

            beforeIndex = INTERSECTED;

        }
    }

    points.geometry.attributes.size.needsUpdate = true;
    points.geometry.attributes.pop.needsUpdate = true;
}
    
function createGrid () {
    var helper = new THREE.GridHelper( 100, 20, 0x303030, 0x303030 );
    scene.add( helper );
}
 function render () {

    renderer.render(scene, camera);

    requestAnimationFrame(render);
}
  
init();
* {
      margin: 0;
      padding: 0;
  }
  html, body {
      width: 100%;
      height: 100%;
      background: #000;
  }
  canvas {
      display: block;
  }
<script src="https://threejs.org/build/three.js"></script>
<script id="fs" type="x-shader/x-fragment">
    precision highp float;
    uniform sampler2D u_texture_0;
    uniform float u_time;
    varying float u_pop;

    void main () {
    vec2 uv = gl_PointCoord.xy;
    vec4 rval = texture2D(u_texture_0,uv);

    vec2 posToCenter = (uv - vec2(.5, .5)) * 2.0;
    float distanceToCenter = length(posToCenter);
    float fadeOpacity = 1. - smoothstep(0.8, 1., distanceToCenter);
    float opacity = (1. - step(0.8, distanceToCenter)) + fadeOpacity;

    vec3 bgColor = mix(vec3(255., 255., 255.), vec3(252., 222., 184.), distanceToCenter) / 255.;

    vec4 color = vec4(mix(bgColor, rval.rgb, u_pop), 1.);
    color.a = opacity;

    gl_FragColor = color;
}
</script>
<script type="x-shader/x-vertex" id="vs">
    attribute float size;
    attribute float pop;

    varying float u_pop;
    void main() {
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
        gl_PointSize = size * ( 300.0 / -mvPosition.z );
        gl_Position = projectionMatrix * mvPosition;

        u_pop = pop;
    }
</script>

`

Answer №1

Your understanding of how 3D works seems to be a bit off, leading you to use incorrect concepts and terminology. In the world of 3D, there is no such thing as "Z-Index." Instead, we have what is known as a Z-buffer or Depth-buffer, which essentially determines the distance of objects from the viewpoint of the render (such as a camera or virtual observer). The purpose of the depth-buffer, along with depth-testing, is to ensure that objects further away are not mistakenly rendered in front of closer ones, thereby optimizing the rendering process by avoiding unnecessary computations. Furthermore, the order in which objects are displayed from background to foreground is not determined by any sort of hierarchy, unless explicitly implemented by the engine. Objects are typically rendered in the sequence they are provided. If depth-testing is turned off, the last object rendered will appear in front of all others. In a 3D scene, hierarchy usually pertains to transformations rather than display order, unless specifically arranged that way without depth-testing. If you want precise control over the visual layering of your sprites, you may need to disable depth-testing and manually dictate the rendering order to ensure that the desired object appears in the forefront. This can involve quite intricate manipulation at a lower level, potentially requiring adjustments to your approach or even building your own WebGL engine if tools like Three.JS do not provide this kind of granular control.

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

Using addClass and removeClass functions in JQuery when selecting a radio button

I am facing an issue with my radio buttons being displayed as images. When a picture (radio button) is selected, I want the other pictures to become hidden. To achieve this, I plan to add a class to the checked picture and then add another class to the unc ...

Guide to defining a conditional statement in a Nuxt.js application

I am working on displaying data from the Wordpress API in a Nuxt.js project. I am trying to organize the data by category, for example where ('post.category ', '=', 'categoryName '). Can anyone help me with the syntax in Vue.j ...

Deleting a string from a parameter

I have a string that reads: France (Republic of France) I am trying to extract only "France" and remove the rest of the string in parentheses. France (Republic of France) Any tips on how to achieve this? Thank you. ...

Disabling the intellisense feature for locale suggestions in Monaco is recommended

Switch the keyboard language to a different one (in this case Japanese using alt + shift), and when typing in Monaco editor, an intellisense menu appears with options to remove and search. Monaco Editor Version: V0.33.0 https://i.stack.imgur.com/SIyeV.pn ...

Change the input field font style in AngularJS

Check out this Plunker link for validation of input field: http://plnkr.co/edit/iFnjcq?p=preview The validation only allows numbers to be entered and automatically adds commas. My query is, if a negative number is entered in the field, how can I change th ...

Testing the React component with the useRouteMatch hook by running a unit test

Consider the code snippet below: import React, { useState, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { useRouteMatch, Link } from 'react-router-dom'; interface MyComponentProps { myId?: stri ...

Utilizing a Variety of Animations with D3 (version 5)

I am currently working on an animation that involves fading out text in a list and collapsing the list when the heading is clicked. However, I am facing a few issues with the code provided in this example. d3.select('.panel-heading') .on(&apos ...

Instructions for crafting a sliced circle with CSS3 and HTML5

I need assistance creating a unique sliced circle interface where each slice can be clicked to execute different commands, similar to buttons. The design specifications for the slices are as follows: 2 Circles: Main Outer circle and inner circle (half ...

Mixing various templates into a single outlet in ember.js

I have been working on an ember application that allows users to create, edit, and delete users, as well as view a list of all users. The app was created by following a tutorial on Ember (as I am still learning), but I am facing an issue. Currently, all th ...

Javascript - Array checking for overlapping numeric ranges

I am currently working with an array of time ranges that have both start and end values. var timeRanges = [{ start: 120, end: 140 },{ start: 180, end: 220 },{ start: 250, end: 300 }] My task requires me to determine if the selecte ...

What causes the inconsistency in the behavior of Number#toLocaleString() between the webkit console and the node console?

var num = 1234567; console.log(num.toLocaleString()) #=> '1234567' What is the reason for the similarity between toLocaleString() and toString in this specific scenario? ...

Trouble with Angular: Passing output between child components is not working

Just dipping my toes into Angular, I started learning it yesterday for a take-home job interview project. Please excuse any rookie mistakes in advance. For some hands-on practice, I decided to work on a basic project where the main component (app) has two ...

Mongodb/mongoose encountering issues with saving data only once, resulting in a 500 error

When I send json to my node.js/express app, it successfully receives the data and performs the desired action, but only once. After starting the appjs for the first time, it returns a 200 response code and saves the data to my mongodb. However, any subsequ ...

React 16 is encountering a discrepancy due to the absence of the data-reactroot attribute

As I was in the midst of updating some apps to React 16, I couldn't help but notice that the data-reactroot attribute is no longer present on the main root element. Although not a critical issue, it seems like we had certain code and styles that reli ...

ActiveX cannot be executed from the server

My MFC activeX control works fine when run from disk, but I encounter errors when hosting it on a server. Client: Windows 7 machine Server: Ubuntu running Apache Below is the HTML code along with the encountered errors. Any advice would be much ap ...

Conflicting Angular controller names within different modules

I'm facing an issue where two modules (A and B) with controllers of the same name are conflicting when imported into module C. Is there a recommended solution to prevent this conflict, such as using a naming convention like "module.controller" for ea ...

Utilizing THREE.js to guide a camera along a designated route

I'm currently working on developing a game using THREE.js. The game involves a path that consists of various curves and some straight paths. After finding an example online, I attempted to incorporate TrackballControls.js into the project to enable t ...

Unable to retrieve dynamically generated object property from an array in AngularJS 2+

Here is an example of an items array: this.itemList = [ { id: 1, name: 'a', address: 'as dasf a' }, { id: 2, name: 'b', address: 'as dasf a' }, { id: 3, name: 'c', address: 'as dasf a' } ]; ...

Having problems with the functionality of AngularJS Routes

I just started learning AngularJS, and I'm having trouble with my routes. I've tried searching on Google and implementing various solutions, but nothing seems to be working. Here is a snippet from my index.html file located in public/index.html: ...

Are there any risks associated with using nested setTimeout functions with the same name?

While reviewing the source code of typed.js, I noticed that the main function in this plugin utilizes a design pattern with multiple setTimeout functions nested inside one another. Here is a snippet of the code: self.timeout = setTimeout(function() { / ...