Customizing vertex sizes in BufferGeometry for diverse shapes

Currently, I am working on creating a 2D scatterplot using three.js and I need to customize the sizes of the points. You can check out my progress here. I'm struggling with adjusting the sizes of the points based on the "radius" property and also adding a small black border around each point, similar to this example. While vertexShaders are usually used for such modifications, I want to create a static image without any runtime changes. Below is the relevant code snippet:

    var coordinates = new Float32Array(data_points.length*3);
    var colors = new Float32Array(data_points.length*3);
    var sizes = new Float32Array(data_points.length);

    for (var i=0; i<data_points.length; i++) {
        // Extract vector coordinates from data
        let vertex = new THREE.Vector3(data_points[i].x, data_points[i].y, 0);
        let color = new THREE.Color(color_array[data_points[i].label]);
        vertex.toArray(coordinates, i*3);
        color.toArray(colors, i*3);
        sizes[i] = data_points[i].radius*100;
    }

    let geometry = new THREE.BufferGeometry();
    geometry.setAttribute('position', new THREE.BufferAttribute(coordinates, 3));
    geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
    geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1 ));

    let pointsMaterial = new THREE.PointsMaterial({
        size: 100,
        sizeAttenuation: true,
        vertexColors: THREE.VertexColors,
        map: new THREE.TextureLoader().load("https://fastforwardlabs.github.io/visualization_assets/circle-sprite.png"),
        transparent: true
    });

    let points = new THREE.Points(geometry, pointsMaterial);

Solving this issue should be straightforward, but as a javascript novice, I would appreciate any assistance or guidance. Thank you in advance!

Answer №1

If you want to utilize Points, it's likely that you'll need to create a custom shader (vertex+fragment).

However, have you considered using meshes instead if your data is not too large? You could achieve the desired outcome by combining scaled CircleBufferGeometry as a Mesh and a Line (or fat lines).

let W = window.innerWidth;
let H = window.innerHeight;
const frustumSize = 100;

const renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true
});
document.body.appendChild(renderer.domElement);

// More code for setting up scene, camera, circle, outline, data point, resizing, rendering, etc.

// Interval function for reacting to mouseovers
let over = true;
setInterval(() => {
  // Code for applying scaling matrix on group based on mouseover state
}, 2000);
html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
  background: white;
}
<script src="https://threejs.org/build/three.js"></script>

If using meshes doesn't fit your requirements, there's also the option of the SVGRenderer, which can render shapes as SVG objects. This might be a more suitable solution depending on your specific data. Check out a demo here:

Answer №2

To achieve the desired effect, it is not possible to use PointsMaterial. You will either need a custom shader material for this task or you can try enhancing PointsMaterial with Material.onBeforeCompile(). I recommend studying the implementation of the official example provided below to explore the former method:

An essential aspect of the code lies in the vertex shader, which allows points to have varying sizes:

attribute float size;
attribute vec3 customColor;

varying vec3 vColor;

void main() {

    vColor = customColor;

    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );

    gl_PointSize = size * ( 300.0 / -mvPosition.z );

    gl_Position = projectionMatrix * mvPosition;

}

Take note of the extra size attribute.

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

What are the steps to use the vue-text-highlight feature?

I am attempting to implement an example from the basic usage section of https://github.com/AlbertLucianto/vue-text-highlight. However, upon opening index.html in Firefox, I am only greeted with a blank page. You can find the code I am using at https://git ...

Ways to specify the default value for a component

A sample of my custom component code (Amount.tsx) is shown below: const Price = ({ price, prevPrice }) => { return ( <div className="product-amount"> <div className="price"> {prevPrice ? (<del class ...

The proper way to incorporate HTML within JSON in Django Templates for safe usage

What is the best way to securely display JSON data in a Django web application? In my Django server, I create JSON data and then display it in a Django template. Sometimes, this JSON data contains snippets of HTML. While this usually works fine, if the &l ...

Leveraging the power of the vuejs plugin within the main.js script

My goal is to develop a plugin to manage the OAuth2 token data in my Vue.js application. I followed several tutorials available on the internet to create this plugin. var plugin = {} plugin.install = function (Vue, options) { var authStorage = { ...

Modify the color of the header on Material-UI Date Picker

I recently integrated a Material-UI Date Picker into my React Single Page Application and now I'm facing an issue with changing the header color. I attempted to modify it using the muiTheme palette property, but unfortunately, the header color remains ...

Error: The specified module could not be found: Could not resolve 'react-hot-loader/webpack'

After constructing my React project, I encountered the error shown below. How can I resolve this issue? I am utilizing the latest version of react-hot-loader. I have attached a screenshot of the error here ...

Placing text on top of objects using three.js

Struggling with incorporating text into my three.js script. Despite extensive searches, all working models I come across seem to be based on outdated versions of three.js, making it challenging for me to implement them. Additionally, TextGeometry appears ...

Learn how to integrate Bootstrap with Vue.js TreeView in this tutorial

If you're looking to create a treeview using Vue.js, the code structure would resemble something like this: HTML: <!-- item template --> <script type="text/x-template" id="item-template"> <li> <div ...

What is the most effective way to communicate to my client that attempting to conceal the browser toolbar is an ill-advised decision?

One of my clients has a friend who claims to be conducting 'security testing' and insists that the PHP Zend Framework application I developed for them should implement certain browser-side features: hide the location bar, toolbar, bookmarks, me ...

Update the div content to completely replace it with fresh data using Ajax

I'm currently working on implementing a currency switcher feature for my website, allowing users to toggle between two different currencies. The site is a reservation platform with a booking form displayed on the left side and the booking details occu ...

Node.js can provide a reusable email framework that can be used across

When it comes to sending emails based on specific business functions in nodejs, I have been following a particular approach. However, I am exploring the possibility of improving this method by composing email content more efficiently. Instead of hardcoding ...

Retrieve the text inside the DIV that contains the clicked link

I'm facing an issue with my JS code: $(document).on("click", '.like', function (e) { $(this).parent().html("<a href = '#' class = 'unlike'><div class = 'heart'></div></a>"); ...

Tips for reconstructing a path in Raphael JS

I am encountering a unique issue with my implementation of Raphael JS. Currently, I am working on drawing a donut element and seeking advice similar to the content found in this helpful link How to achieve 'donut holes' with paths in Raphael) var ...

Integrate CSS and JavaScript files into Node Express

I am facing an issue including my CSS file and JavaScript file in a node-express application, as I keep getting a 404 not found error. Here is the code snippet that I am using: 1. In server.js var http = require('http'); var app = require(' ...

Launching an external software using electron

I am in the process of developing my own personalized Electron app for managing other applications on my device. One issue I have encountered is the inability to create a link that opens my own .exe applications. I have attempted various methods without su ...

Looking to simplify the complex JSON structure by converting it into an array using JavaScript

Being a newcomer to javascript, I am struggling with breaking down a complex structure into an array. The current structure is as follows: [ { "Key": "ProducePRINKA0370001", "Record": { "docType": "Produce", "PR ...

Ways to incorporate error handling in node.js/express when using mySQL operations

I am currently focusing on enhancing the error handling capabilities in my node/express application, however, I find myself a bit confused. As an example, here is a route within my code that I wish to refine: app.get("/api/max-value", function (req, res) ...

Experiencing difficulties when trying to pan and zoom the data obtained from d3.json within a line chart

I am currently working on developing a trend component that can zoom and pan into data fetched using d3.json. Here is the code I have written so far: <script> var margin = { top: 20, right: 80, bottom: 20, left: 50 }, width = $("#trendc ...

Having trouble with uploading a file through ajax

I'm currently working on uploading form data through ajax, but I've encountered an issue with uploading images/files. Form Code <form class="form-inline" id="form_add" enctype="multipart/form-data"> <input type="file" id="file-inpu ...

React state object iteration doesn't produce any visible output

Trying to dynamically showcase checkboxes with starting values from the state using Material-UI for UI components. tagState: { All: true, Pizza: false, Breakfast: false, Chicken: false } Utilized Object entries and forEach to generate checkbox ...