The color of the vertices is transitioning to a pure white hue

When working with THREE.js points, I often find the need for them to have different colors on a per-point basis. In some cases, I also adjust the alpha value, which leads me to write my own shader programs.

Here is the JavaScript code I am using:

let materials;
if (pointCloudData.colors !== undefined) {
    geometry.colors = pointCloudData.colors.map(hexColor => new THREE.Color(hexColor));
    // If each point in the cloud has its own color...
    materials = new THREE.ShaderMaterial({
        vertexColors: THREE.VertexColors,
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        transparent: true,
    });
} else {
    // Set a uniform color for the entire cloud
    materials = new THREE.ShaderMaterial({
        uniforms: {
            unicolor: { value: pointCloudData.color },
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        transparent: true,
    });
}

const pointCloud = new THREE.Points(geometry, materials);

In essence, I assign a uniform color to the mesh, unless individual point colors are defined, in which case I set the vertexColors for the geometry accordingly. When inspecting the values stored in geometry.colors, they appear to be correct RGB values within the range of [0,1].

Below is my Vertex Shader code:

attribute float size;
attribute float alpha;

varying float vAlpha;
varying vec3 vColor;
void main() {
    vAlpha = alpha;

    #ifdef USE_COLOR
        vColor = color;
    #endif

    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_PointSize = size * ( 300.0 / -mvPosition.z );
    gl_Position = projectionMatrix * mvPosition;
}

And here is my Fragment shader code:

uniform vec3 unicolor;

varying vec3 vColor;
varying float vAlpha;
void main() {
    #ifdef USE_COLOR
        gl_FragColor = vec4(vColor, vAlpha);
    #else
        gl_FragColor = vec4(unicolor, vAlpha);
    #endif
}

Once again, I check if the vertexColor is defined and then pass it to the Fragment Shader for setting the individual point color.

For some unknown reason, all vertices appear white when trying to set the color per point. You can see a screenshot here, where the white pixels should actually be green or red. As someone who is not yet an advanced WebGL user, any help or guidance would be greatly appreciated. Could there be a mistake that I am overlooking?

Answer №1

Customizing a ShaderMaterial involves utilizing a specific pattern within the fragment shader:

#ifdef USE_COLOR
    vColor = color;
#endif

To properly implement this, it's essential to define the necessary settings in material.defines:

var defines = {};
defines[ "USE_COLOR" ] = "";

// Configure points material
var shaderMaterial = new THREE.ShaderMaterial( {

    defines:        defines,
    uniforms:       uniforms,
    vertexShader:   document.getElementById( 'vertexshader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
    transparent:    true

} );

Remember, omitting the setting of vertexColors: THREE.VertexColors is acceptable as it serves as an indicator for the renderer to handle the defines automatically.

Updated for three.js r.85

Answer №2

Finally, after some trial and error, I've managed to solve the issue as it seems to be functioning correctly now.

To tackle the problem, I made sure to specify the colors as geometry attributes in the following manner:

const colors = new Float32Array(n * 3);
for (let i = 0; i < n; i += 1) {
    new THREE.Color(pointCloudData.colors[i]).toArray(colors, i * 3);
}
geometry.addAttribute('colors', new THREE.BufferAttribute(colors, 1));

Additionally, I took into account WestLangley's advice by excluding

vertexColors: THREE.VertexColors,
from the Material definition and incorporating the necessary define setting:

materials = new THREE.ShaderMaterial({
    defines: {
        USE_COLOR: '',
    },
    vertexShader: document.getElementById('vertexshader').textContent,
    fragmentShader: document.getElementById('fragmentshader').textContent,
    transparent: true,
});

Subsequently, within my Vertex shader, I appended:

attributes vec3 colors;

This allowed me to receive the color information passed from the JavaScript code. The remaining process remained unchanged, with the color data being forwarded to the fragment shader utilizing a similar technique outlined in the original question.

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

Manipulating data with Angular's array object

I am having an issue with posting an object array. I anticipate the post to be in JSON format like this: {"campaign":"ben", "slots":[ { "base_image": "base64 code here" } ] } However, when I attempt to post ...

Is it possible to make a model draggable but disable it specifically on input fields?

I'm exploring the implementation of a draggable feature by using both a JavaScript directive and the simple draggable="true" attribute. (Testing each method separately). Here's my basic code structure: <div draggable="true& ...

The multi-level dropdown feature in the BootStrap-4 navbar extends off the screen when the dropdown menu is opened

I have been struggling to make this work. I used BS4 for responsiveness, and my navigation items are aligned to the right in the navbar. Despite trying various methods to position the submenu on the left of the parent menu, I still can't get it to dis ...

Updating coordinates on Google Maps using setTimeOut with jQuery and JavaScript

I am currently working on updating the markers and users' positions every five seconds so that the users can see their live position updates. I have managed to retrieve the current coordinates and update them at the correct interval, but I am struggli ...

Interacting across numerous tiers of nested directives

Allow me to explain the situation, it may seem a bit intricate. I have structured my directives in three layers: At the top layer, there is a popup directive In the middle layer, there is a switch-pane directive * The bottom layer consists of various vie ...

Failed to transfer form data to server using ajax in Node.js

I am attempting to utilize AJAX to send form data to a Node.js server. I had previously inquired about this on the following post. Below is a glimpse of my code: <div id="inputid" style="width: 400px; height:400px"> <p> Kindly input value ...

Apply a jQuery class to six randomly selected elements that share the same class attribute

I have a total of 12 elements that all have the "block" class, and I am looking to randomly assign the "active" class to exactly 6 out of the 12 elements. My initial thought was to use a for loop to achieve this task, but I'm unsure about how to go a ...

The XML data seems to be missing from the HTML page

I've been working on a project where I need to display XML data on an HTML page. To accomplish this, I'm using Django to generate the content in the XML file and Javascript to periodically check for new posts and load them onto the page. Below i ...

Understanding the time complexity of Object.entries()

Is the complexity of Object.entries() in JavaScript known? According to information from this question, it seems like it could possibly be O(n) if implemented by collecting keys and values as arrays and then combining them together? ...

Error message: NGINX combined with Express.js and socket.io, page not found

I currently have a node/express.js/socket.io application set up on an Ubuntu Server running on port 3002. I've made sure to open all ports on the machine for accessibility. When accessing the app directly at 11.111.111.1:3002/, everything runs smooth ...

Why isn't the Angular Google Maps Displaying in my Template View?

After configuring Angular Google Maps and following the provided steps, I am facing an issue where the map is not loading on the directive without any error. Below is the code snippet: Controller app.controller('MapCtrl', [ '$scope&apo ...

"Learn the method for retrieving the number of rows in Cloud Code within the Parse platform

So I ran into an issue with this code - it keeps giving me a message that says success/error was not called. Parse.Cloud.beforeSave("Offer", function(request, response) { var duplicationQuery = new Parse.Query("Offer"); console.log(duplicationQuery.count ...

How to Fetch JSON Data from a URL using JQuery AJAX?

Working on a coding project that involves retrieving data from an API. My approach is to fetch json data and decode it using file_get_contents and json_decode in PHP, which I've successfully done before. Here's the specific scenario: I am imple ...

Updating Elements in an Array Using JavaScript is Not Functioning as Expected

In my Angular application, I have included some lines of TypeScript code which involve Boolean variables in the constructor and an array of objects. Each object in this array contains input variables. selftest: boolean; failed: boolean; locoStateItem ...

Error: The object being added is not a valid instance of THREE.Object3D for the .add method

I encountered this error and I'm having trouble pinpointing its origin. It seems to be related to importing and creating 3D objects within my scene, but I can't figure out what exactly is causing the issue. Below is the code snippet where I call ...

Python script for downloading audio files loaded with JavaScript

I am currently working on a Python script to automate the process of downloading English audio files from a specific website. When I click on the play button, the audio file starts to load and play, but I am unsure how to capture and download the file in ...

Is there a way to prevent my token from being exposed when making an AJAX call?

When working on my HTML file, I encountered an issue with a Python Django URL integration where I need to pass a token to retrieve certain information. However, the problem is that my token is exposed when inspecting the page source in the HTML document. ...

What is the best way to reveal a hidden div using JavaScript after a form submission?

jQuery is not a language I am very familiar with, but I am attempting to display a simple animated gif when a form is submitted. When users click 'submit' to upload an image, I want the gif to show to indicate that the image is being uploaded. Th ...

Arrange divs in a grid layout with evenly distributed dynamic spacing

I am not a big fan of bootstrap, so I was wondering if it is possible to achieve the layout without using it. I have 6 divs that I want to arrange in 2 rows and 3 columns. I need the space between each row/column to be precise. While I can calculate this ...

I just made an object in my index.js file, now how can I ensure it is accessible in a router file?

In my project's index.js file, I perform the following tasks: initialize the Express app instance include a router.js file defining a POST endpoint create a Socket.IO object Here is the code snippet: const http = require("http"); const exp ...